]> git.proxmox.com Git - rustc.git/commitdiff
Imported Upstream version 1.2.0+dfsg1
authorSylvestre Ledru <sylvestre@debian.org>
Sun, 9 Aug 2015 18:20:49 +0000 (20:20 +0200)
committerSylvestre Ledru <sylvestre@debian.org>
Sun, 9 Aug 2015 18:20:49 +0000 (20:20 +0200)
1098 files changed:
AUTHORS.txt
CONTRIBUTING.md
Makefile.in
README.md
RELEASES.md
configure
man/rustc.1
man/rustdoc.1
mk/cfg/aarch64-apple-ios.mk
mk/cfg/x86_64-pc-windows-msvc.mk [new file with mode: 0644]
mk/cfg/x86_64-unknown-linux-musl.mk
mk/clean.mk
mk/crates.mk
mk/debuggers.mk
mk/dist.mk
mk/docs.mk
mk/llvm.mk
mk/main.mk
mk/platform.mk
mk/prepare.mk
mk/reconfig.mk
mk/rt.mk
mk/rustllvm.mk
mk/target.mk
mk/tests.mk
mk/util.mk
src/compiletest/common.rs
src/compiletest/compiletest.rs
src/compiletest/runtest.rs
src/doc/complement-design-faq.md
src/doc/complement-lang-faq.md
src/doc/footer.inc
src/doc/grammar.md
src/doc/index.md
src/doc/not_found.md
src/doc/reference.md
src/doc/style/errors/ergonomics.md
src/doc/style/features/functions-and-methods/README.md
src/doc/style/features/functions-and-methods/input.md
src/doc/style/features/functions-and-methods/output.md
src/doc/style/features/let.md
src/doc/style/features/traits/generics.md
src/doc/style/features/traits/reuse.md
src/doc/style/features/types/newtype.md
src/doc/style/ownership/builders.md
src/doc/style/style/features.md
src/doc/style/style/imports.md
src/doc/style/style/whitespace.md
src/doc/trpl/README.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/associated-types.md
src/doc/trpl/benchmark-tests.md
src/doc/trpl/borrow-and-asref.md
src/doc/trpl/box-syntax-and-patterns.md
src/doc/trpl/closures.md
src/doc/trpl/comments.md
src/doc/trpl/concurrency.md
src/doc/trpl/conditional-compilation.md
src/doc/trpl/const-and-static.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/dining-philosophers.md
src/doc/trpl/documentation.md
src/doc/trpl/enums.md
src/doc/trpl/error-handling.md
src/doc/trpl/ffi.md
src/doc/trpl/for-loops.md
src/doc/trpl/functions.md
src/doc/trpl/generics.md
src/doc/trpl/glossary.md
src/doc/trpl/guessing-game.md
src/doc/trpl/hello-cargo.md
src/doc/trpl/inline-assembly.md
src/doc/trpl/installing-rust.md
src/doc/trpl/intrinsics.md
src/doc/trpl/iterators.md
src/doc/trpl/lang-items.md
src/doc/trpl/lifetimes.md
src/doc/trpl/macros.md
src/doc/trpl/method-syntax.md
src/doc/trpl/mutability.md
src/doc/trpl/nightly-rust.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/testing.md
src/doc/trpl/the-stack-and-the-heap.md
src/doc/trpl/trait-objects.md
src/doc/trpl/traits.md
src/doc/trpl/vectors.md
src/doc/trpl/while-loops.md
src/error-index-generator/main.rs
src/etc/2014-06-rewrite-bytes-macros.py [deleted file]
src/etc/add-authors.sh [new file with mode: 0644]
src/etc/check-sanitycheck.py
src/etc/check-summary.py
src/etc/debugger_pretty_printers_common.py [new file with mode: 0644]
src/etc/errorck.py
src/etc/featureck.py
src/etc/gdb_rust_pretty_printing.py
src/etc/lldb_rust_formatters.py
src/etc/mklldef.py [new file with mode: 0644]
src/etc/mklldeps.py
src/etc/snapshot.pyc
src/etc/tidy.py
src/etc/unicode.py
src/jemalloc/VERSION
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/libarena/lib.rs
src/libcollections/binary_heap.rs
src/libcollections/bit.rs
src/libcollections/borrow.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/range.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollections/vec_map.rs
src/libcollectionstest/binary_heap.rs
src/libcollectionstest/bit/set.rs
src/libcollectionstest/bit/vec.rs
src/libcollectionstest/btree/map.rs
src/libcollectionstest/btree/set.rs
src/libcollectionstest/enum_set.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/linked_list.rs
src/libcollectionstest/str.rs
src/libcollectionstest/string.rs
src/libcollectionstest/vec.rs
src/libcollectionstest/vec_deque.rs
src/libcollectionstest/vec_map.rs
src/libcore/any.rs
src/libcore/array.rs
src/libcore/atomic.rs
src/libcore/cell.rs
src/libcore/char.rs
src/libcore/clone.rs
src/libcore/cmp.rs
src/libcore/convert.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/intrinsics.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/nonzero.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/flt2dec/bignum.rs
src/libcore/num/flt2dec/mod.rs
src/libcore/num/flt2dec/strategy/dragon.rs
src/libcore/num/flt2dec/strategy/grisu.rs
src/libcore/num/int_macros.rs
src/libcore/num/isize.rs
src/libcore/num/mod.rs
src/libcore/num/uint_macros.rs
src/libcore/num/usize.rs
src/libcore/num/wrapping.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/panicking.rs
src/libcore/prelude.rs
src/libcore/ptr.rs
src/libcore/raw.rs
src/libcore/result.rs
src/libcore/simd.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcore/ty.rs [deleted file]
src/libcoretest/atomic.rs
src/libcoretest/cell.rs
src/libcoretest/char.rs
src/libcoretest/fmt/mod.rs
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/option.rs
src/libcoretest/result.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libgetopts/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/ziggurat_tables.rs
src/librand/isaac.rs
src/librand/lib.rs
src/librbml/lib.rs
src/librustc/ast_map/blocks.rs [new file with mode: 0644]
src/librustc/ast_map/mod.rs [new file with mode: 0644]
src/librustc/diagnostics.rs
src/librustc/lib.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/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/cast.rs [new file with mode: 0644]
src/librustc/middle/cfg/construct.rs
src/librustc/middle/cfg/graphviz.rs
src/librustc/middle/cfg/mod.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_rvalues.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/dependency_format.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/fast_reject.rs
src/librustc/middle/free_region.rs
src/librustc/middle/implicator.rs
src/librustc/middle/infer/bivariate.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/equate.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/freshen.rs
src/librustc/middle/infer/glb.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/lattice.rs
src/librustc/middle/infer/lub.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/graphviz.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/infer/resolve.rs
src/librustc/middle/infer/sub.rs
src/librustc/middle/infer/type_variable.rs
src/librustc/middle/intrinsicck.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/subst.rs
src/librustc/middle/traits/README.md
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/error_reporting.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/object_safety.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_match.rs
src/librustc/middle/ty_relate/mod.rs
src/librustc/middle/ty_walk.rs
src/librustc/plugin/registry.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/util/fs.rs
src/librustc/util/ppaux.rs
src/librustc_back/archive.rs
src/librustc_back/lib.rs
src/librustc_back/sha2.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/windows_msvc_base.rs [new file with mode: 0644]
src/librustc_back/target/x86_64_pc_windows_msvc.rs [new file with mode: 0644]
src/librustc_bitflags/lib.rs
src/librustc_borrowck/borrowck/README.md
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/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_borrowck/lib.rs
src/librustc_data_structures/graph/mod.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/lib.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/record_exports.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs [new file with mode: 0644]
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
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/build.rs
src/librustc_trans/trans/builder.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/cleanup.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/datum.rs
src/librustc_trans/trans/debuginfo/create_scope_map.rs
src/librustc_trans/trans/debuginfo/metadata.rs
src/librustc_trans/trans/debuginfo/mod.rs
src/librustc_trans/trans/debuginfo/namespace.rs
src/librustc_trans/trans/debuginfo/type_names.rs
src/librustc_trans/trans/declare.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/assoc.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/README.md
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/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/constrained_type_params.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance.rs
src/librustc_unicode/char.rs
src/librustc_unicode/lib.rs
src/librustc_unicode/tables.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/simplify.rs
src/librustdoc/core.rs
src/librustdoc/doctree.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
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/plugins.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libstd/ascii.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/state.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/error.rs
src/libstd/ffi/c_str.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/error.rs
src/libstd/io/lazy.rs
src/libstd/io/mod.rs
src/libstd/io/stdio.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/mod.rs
src/libstd/net/parser.rs
src/libstd/net/tcp.rs
src/libstd/net/test.rs
src/libstd/net/udp.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/num/float_macros.rs
src/libstd/num/int_macros.rs
src/libstd/num/isize.rs
src/libstd/num/uint_macros.rs
src/libstd/num/usize.rs
src/libstd/os/android/raw.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/rand/mod.rs
src/libstd/rand/os.rs
src/libstd/rt/args.rs
src/libstd/rt/at_exit_imp.rs
src/libstd/rt/backtrace.rs
src/libstd/rt/mod.rs
src/libstd/rt/unwind.rs [deleted file]
src/libstd/rt/unwind/gcc.rs [new file with mode: 0644]
src/libstd/rt/unwind/mod.rs [new file with mode: 0644]
src/libstd/rt/unwind/seh.rs [new file with mode: 0644]
src/libstd/rt/util.rs
src/libstd/rtdeps.rs
src/libstd/sync/condvar.rs
src/libstd/sync/future.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/blocking.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/semaphore.rs
src/libstd/sys/common/backtrace.rs
src/libstd/sys/common/condvar.rs
src/libstd/sys/common/mutex.rs
src/libstd/sys/common/net.rs
src/libstd/sys/common/poison.rs
src/libstd/sys/common/remutex.rs
src/libstd/sys/common/rwlock.rs
src/libstd/sys/common/stack.rs
src/libstd/sys/common/thread_local.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/condvar.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/mutex.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/rwlock.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/stdio.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/thread_local.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/condvar.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/ext/mod.rs
src/libstd/sys/windows/ext/process.rs [new file with mode: 0644]
src/libstd/sys/windows/ext/raw.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/handle.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/net.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/process.rs
src/libstd/sys/windows/rwlock.rs
src/libstd/sys/windows/stdio.rs
src/libstd/sys/windows/thread_local.rs
src/libstd/sys/windows/time.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/thread/scoped_tls.rs
src/libstd/thunk.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs [deleted file]
src/libsyntax/ast_map/mod.rs [deleted file]
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostic.rs
src/libsyntax/diagnostics/metadata.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/bounds.rs
src/libsyntax/ext/deriving/clone.rs
src/libsyntax/ext/deriving/cmp/eq.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/deriving/cmp/partial_eq.rs
src/libsyntax/ext/deriving/cmp/partial_ord.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/default.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/hash.rs
src/libsyntax/ext/deriving/mod.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/deriving/show.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/test.rs
src/libsyntax/util/parser_testing.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libterm/terminfo/parm.rs
src/libtest/lib.rs
src/rt/arch/i386/morestack.S
src/rt/rust_builtin.c
src/rt/rust_test_helpers.c
src/rust-installer/install-template.sh
src/rustbook/build.rs
src/rustbook/css.rs
src/rustbook/javascript.rs
src/rustbook/main.rs
src/rustbook/subcommand.rs
src/rustbook/term.rs
src/rustllvm/ExecutionEngineWrapper.cpp
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-auto-clean-trigger
src/rustllvm/rustllvm.h
src/snapshots.txt
src/test/auxiliary/attr_plugin_test.rs [new file with mode: 0644]
src/test/auxiliary/const_fn_lib.rs [new file with mode: 0644]
src/test/auxiliary/custom_derive_plugin.rs
src/test/auxiliary/custom_derive_plugin_attr.rs
src/test/auxiliary/extern_calling_convention.rs
src/test/auxiliary/issue-17718.rs
src/test/auxiliary/issue-18913-1.rs [new file with mode: 0644]
src/test/auxiliary/issue-18913-2.rs [new file with mode: 0644]
src/test/auxiliary/issue-19190-3.rs
src/test/auxiliary/issue13507.rs
src/test/auxiliary/lang-item-public.rs
src/test/auxiliary/lifetime_bound_will_change_warning_lib.rs [new file with mode: 0644]
src/test/auxiliary/linkage-visibility.rs
src/test/auxiliary/llvm_pass_plugin.rs
src/test/auxiliary/macro_crate_test.rs
src/test/auxiliary/xcrate_associated_type_defaults.rs [new file with mode: 0644]
src/test/bench/core-set.rs
src/test/bench/core-std.rs
src/test/bench/msgsend-ring-mutex-arcs.rs
src/test/bench/shootout-fannkuch-redux.rs
src/test/bench/shootout-fasta-redux.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-k-nucleotide.rs
src/test/bench/shootout-mandelbrot.rs
src/test/bench/shootout-meteor.rs
src/test/bench/shootout-nbody.rs
src/test/bench/shootout-spectralnorm.rs
src/test/bench/std-smallintmap.rs
src/test/bench/task-perf-alloc-unwind.rs
src/test/codegen/coercions.rs [new file with mode: 0644]
src/test/codegen/function-arguments.rs [new file with mode: 0644]
src/test/codegen/iterate-over-array.cc [deleted file]
src/test/codegen/iterate-over-array.rs [deleted file]
src/test/codegen/loads.rs [new file with mode: 0644]
src/test/codegen/scalar-function-call.cc [deleted file]
src/test/codegen/scalar-function-call.rs [deleted file]
src/test/codegen/single-return-value.cc [deleted file]
src/test/codegen/single-return-value.rs [deleted file]
src/test/codegen/small-dense-int-switch.cc [deleted file]
src/test/codegen/small-dense-int-switch.rs [deleted file]
src/test/codegen/stack-alloc-string-slice.cc [deleted file]
src/test/codegen/stack-alloc-string-slice.rs [deleted file]
src/test/codegen/static-method-call-multi.cc [deleted file]
src/test/codegen/static-method-call-multi.rs [deleted file]
src/test/codegen/static-method-call.cc [deleted file]
src/test/codegen/static-method-call.rs [deleted file]
src/test/codegen/stores.rs [new file with mode: 0644]
src/test/codegen/virtual-method-call-struct-return.cc [deleted file]
src/test/codegen/virtual-method-call-struct-return.rs [deleted file]
src/test/codegen/virtual-method-call.cc [deleted file]
src/test/codegen/virtual-method-call.rs [deleted file]
src/test/compile-fail-fulldeps/plugin-attr-register-deny.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/qquote.rs
src/test/compile-fail/asm-src-loc-codegen-units.rs
src/test/compile-fail/assoc-inherent.rs
src/test/compile-fail/associated-const-type-parameters.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-incomplete-object.rs
src/test/compile-fail/associated-types-path-2.rs
src/test/compile-fail/bad-expr-path.rs
src/test/compile-fail/bad-expr-path2.rs
src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs
src/test/compile-fail/builtin-superkinds-self-type.rs
src/test/compile-fail/cast-ptr-to-int-const.rs [new file with mode: 0644]
src/test/compile-fail/cast-rfc0401.rs [new file with mode: 0644]
src/test/compile-fail/cast-to-bare-fn.rs
src/test/compile-fail/check-static-values-constraints.rs
src/test/compile-fail/coherence-impl-trait-for-trait.rs
src/test/compile-fail/const-cast-different-types.rs
src/test/compile-fail/const-deref-ptr.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-mismatch.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-not-in-trait.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-not-safe-for-const.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability-calls-2.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability-calls-3.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability-calls.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability.rs [new file with mode: 0644]
src/test/compile-fail/cross-fn-cache-hole.rs [new file with mode: 0644]
src/test/compile-fail/dead-code-closure-bang.rs
src/test/compile-fail/destructure-trait-ref.rs
src/test/compile-fail/dropck_arr_cycle_checked.rs
src/test/compile-fail/dropck_tarena_cycle_checked.rs
src/test/compile-fail/dropck_trait_cycle_checked.rs
src/test/compile-fail/dropck_vec_cycle_checked.rs
src/test/compile-fail/dst-object-from-unsized-type.rs
src/test/compile-fail/fat-ptr-cast.rs
src/test/compile-fail/feature-gate-assoc-type-defaults.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-simd-ffi.rs
src/test/compile-fail/feature-gate-static-assert.rs [deleted file]
src/test/compile-fail/functional-struct-update-respects-privacy.rs
src/test/compile-fail/impl-duplicate-methods.rs
src/test/compile-fail/issue-12796.rs
src/test/compile-fail/issue-14845.rs
src/test/compile-fail/issue-15167.rs
src/test/compile-fail/issue-16538.rs
src/test/compile-fail/issue-17444.rs
src/test/compile-fail/issue-17458.rs
src/test/compile-fail/issue-17718-const-borrow.rs
src/test/compile-fail/issue-18058.rs [new file with mode: 0644]
src/test/compile-fail/issue-18343.rs
src/test/compile-fail/issue-19660.rs
src/test/compile-fail/issue-20801.rs
src/test/compile-fail/issue-21554.rs
src/test/compile-fail/issue-22289.rs
src/test/compile-fail/issue-22673.rs
src/test/compile-fail/issue-23073.rs [new file with mode: 0644]
src/test/compile-fail/issue-23173.rs [new file with mode: 0644]
src/test/compile-fail/issue-23589.rs [new file with mode: 0644]
src/test/compile-fail/issue-2392.rs [new file with mode: 0644]
src/test/compile-fail/issue-24081.rs [new file with mode: 0644]
src/test/compile-fail/issue-24322.rs [new file with mode: 0644]
src/test/compile-fail/issue-24446.rs
src/test/compile-fail/issue-2478.rs [deleted file]
src/test/compile-fail/issue-24968.rs [new file with mode: 0644]
src/test/compile-fail/issue-25396.rs [new file with mode: 0644]
src/test/compile-fail/issue-25700.rs [new file with mode: 0644]
src/test/compile-fail/issue-25826.rs [new file with mode: 0644]
src/test/compile-fail/issue-26194.rs [new file with mode: 0644]
src/test/compile-fail/issue-26262.rs [new file with mode: 0644]
src/test/compile-fail/issue-4265.rs
src/test/compile-fail/issue-5153.rs
src/test/compile-fail/issue-6801.rs
src/test/compile-fail/issue-7364.rs
src/test/compile-fail/kindck-copy.rs
src/test/compile-fail/kindck-impl-type-params.rs
src/test/compile-fail/lifetime-bound-will-change-warning.rs [new file with mode: 0644]
src/test/compile-fail/lint-dead-code-4.rs
src/test/compile-fail/lint-dead-code-variant.rs [new file with mode: 0644]
src/test/compile-fail/lint-exceeding-bitshifts.rs
src/test/compile-fail/lint-missing-doc.rs
src/test/compile-fail/lint-type-overflow.rs
src/test/compile-fail/macro-followed-by-seq-bad.rs [new file with mode: 0644]
src/test/compile-fail/macro-seq-followed-by-seq.rs [new file with mode: 0644]
src/test/compile-fail/match-ill-type1.rs [deleted file]
src/test/compile-fail/match-range-fail.rs
src/test/compile-fail/match-static-const-lc.rs
src/test/compile-fail/method-help-unsatisfied-bound.rs [new file with mode: 0644]
src/test/compile-fail/mod_file_correct_spans.rs
src/test/compile-fail/move-closure-span.rs [new file with mode: 0644]
src/test/compile-fail/nonbool_static_assert.rs [deleted file]
src/test/compile-fail/not-utf8.rs
src/test/compile-fail/object-lifetime-default-mybox.rs
src/test/compile-fail/object-lifetime-default.rs
src/test/compile-fail/private-struct-field-cross-crate.rs
src/test/compile-fail/private-struct-field.rs
src/test/compile-fail/pub-struct-field-span-26083.rs [new file with mode: 0644]
src/test/compile-fail/redundant-link-args.rs [deleted file]
src/test/compile-fail/regions-bounded-by-trait-requiring-static.rs
src/test/compile-fail/static-assert.rs [deleted file]
src/test/compile-fail/static-assert2.rs [deleted file]
src/test/compile-fail/static-mut-not-constant.rs
src/test/compile-fail/static-vec-repeat-not-constant.rs
src/test/compile-fail/std-uncopyable-atomics.rs
src/test/compile-fail/struct-field-assignability.rs [deleted file]
src/test/compile-fail/syntax-extension-minor.rs
src/test/compile-fail/syntaxt-default-trait-impls.rs
src/test/compile-fail/trait-bounds-cant-coerce.rs
src/test/compile-fail/trait-bounds-on-structs-and-enums.rs
src/test/compile-fail/trait-or-new-type-instead.rs
src/test/compile-fail/traits-negative-impls.rs
src/test/compile-fail/typeck-cast-pointer-to-float.rs
src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs
src/test/compile-fail/typo-suggestion.rs [new file with mode: 0644]
src/test/compile-fail/ufcs-qpath-missing-params.rs
src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs
src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs
src/test/compile-fail/unsafe-fn-deref-ptr.rs
src/test/compile-fail/unsized5.rs
src/test/compile-fail/use-paths-as-items.rs [new file with mode: 0644]
src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs
src/test/compile-fail/vector-cast-weirdness.rs
src/test/debuginfo/constant-debug-locs.rs
src/test/debuginfo/gdb-pretty-std.rs [deleted file]
src/test/debuginfo/gdb-pretty-struct-and-enums.rs [deleted file]
src/test/debuginfo/generic-trait-generic-static-default-method.rs [deleted file]
src/test/debuginfo/issue11600.rs [deleted file]
src/test/debuginfo/option-like-enum.rs
src/test/debuginfo/pretty-std.rs [new file with mode: 0644]
src/test/debuginfo/simd.rs
src/test/debuginfo/trait-generic-static-default-method.rs [deleted file]
src/test/parse-fail/extern-crate-unexpected-token.rs [new file with mode: 0644]
src/test/parse-fail/extern-expected-fn-or-brace.rs
src/test/parse-fail/issue-14182.rs [deleted file]
src/test/parse-fail/macros-no-semicolon.rs
src/test/parse-fail/no-unsafe-self.rs
src/test/parse-fail/regions-fn-bound.rs [deleted file]
src/test/parse-fail/regions-infer-paramd-method.rs [deleted file]
src/test/parse-fail/regions-trait-2.rs [deleted file]
src/test/parse-fail/regions-trait-3.rs [deleted file]
src/test/pretty/do1.rs
src/test/pretty/record-trailing-comma.rs [deleted file]
src/test/run-fail-fulldeps/qquote.rs
src/test/run-fail/bug-2470-bounds-check-overflow-2.rs [deleted file]
src/test/run-fail/bug-2470-bounds-check-overflow-3.rs [deleted file]
src/test/run-fail/extern-panic.rs [deleted file]
src/test/run-fail/issue-2061.rs [deleted file]
src/test/run-fail/overflowing-simd-lsh-1.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-lsh-2.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-lsh-3.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-lsh-4.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-rsh-1.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-rsh-2.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-rsh-3.rs [new file with mode: 0644]
src/test/run-fail/overflowing-simd-rsh-4.rs [new file with mode: 0644]
src/test/run-fail/panic.rs
src/test/run-fail/too-much-recursion-unwinding.rs [deleted file]
src/test/run-make/execution-engine/Makefile [new file with mode: 0644]
src/test/run-make/execution-engine/test.rs [new file with mode: 0644]
src/test/run-make/extern-flag-disambiguates/d.rs
src/test/run-make/extern-fn-reachable/main.rs
src/test/run-make/intrinsic-unreachable/exit-unreachable.rs
src/test/run-make/issue-25581/Makefile [new file with mode: 0644]
src/test/run-make/issue-25581/test.c [new file with mode: 0644]
src/test/run-make/issue-25581/test.rs [new file with mode: 0644]
src/test/run-make/issue-26006/Makefile [new file with mode: 0644]
src/test/run-make/issue-26006/in/libc/lib.rs [new file with mode: 0644]
src/test/run-make/issue-26006/in/time/lib.rs [new file with mode: 0644]
src/test/run-make/issue-26092/Makefile [new file with mode: 0644]
src/test/run-make/issue-26092/blank.rs [new file with mode: 0644]
src/test/run-make/static-unwinding/main.rs
src/test/run-make/volatile-intrinsics/main.rs
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass-fulldeps/issue-15149.rs
src/test/run-pass-fulldeps/qquote.rs
src/test/run-pass-valgrind/cast-enum-with-dtor.rs [new file with mode: 0644]
src/test/run-pass-valgrind/dst-dtor-2.rs
src/test/run-pass/arith-2.rs
src/test/run-pass/artificial-block.rs
src/test/run-pass/asm-in-out-operand.rs
src/test/run-pass/assignability-trait.rs
src/test/run-pass/associated-const-range-match-patterns.rs [new file with mode: 0644]
src/test/run-pass/associated-types-conditional-dispatch.rs
src/test/run-pass/associated-types-iterator-binding.rs
src/test/run-pass/associated-types-method.rs [new file with mode: 0644]
src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
src/test/run-pass/associated-types-return.rs
src/test/run-pass/auto-encode.rs [deleted file]
src/test/run-pass/backtrace-debuginfo.rs
src/test/run-pass/binary-heap-panic-safe.rs
src/test/run-pass/bitv-perf-test.rs
src/test/run-pass/bool.rs
src/test/run-pass/borrowck-nested-calls.rs [deleted file]
src/test/run-pass/box-of-array-of-drop-1.rs
src/test/run-pass/box-of-array-of-drop-2.rs
src/test/run-pass/builtin-superkinds-capabilities-transitive.rs
src/test/run-pass/builtin-superkinds-capabilities-xc.rs
src/test/run-pass/builtin-superkinds-capabilities.rs
src/test/run-pass/builtin-superkinds-self-type.rs
src/test/run-pass/c-stack-returning-int64.rs
src/test/run-pass/cast-rfc0401-vtable-kinds.rs [new file with mode: 0644]
src/test/run-pass/cast-rfc0401.rs [new file with mode: 0644]
src/test/run-pass/cci_impl_exe.rs
src/test/run-pass/cci_iter_exe.rs
src/test/run-pass/check-static-slice.rs
src/test/run-pass/class-impl-very-parameterized-trait.rs
src/test/run-pass/cmp-default.rs
src/test/run-pass/const-big-enum.rs
src/test/run-pass/const-enum-structlike.rs
src/test/run-pass/const-enum-vec-index.rs
src/test/run-pass/const-enum-vec-ptr.rs
src/test/run-pass/const-enum-vector.rs
src/test/run-pass/const-fn-cross-crate.rs [new file with mode: 0644]
src/test/run-pass/const-fn-method.rs [new file with mode: 0644]
src/test/run-pass/const-fn-nested.rs [new file with mode: 0644]
src/test/run-pass/const-fn.rs [new file with mode: 0644]
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/const-trait-to-trait.rs [new file with mode: 0644]
src/test/run-pass/deep-vector.rs [deleted file]
src/test/run-pass/deep-vector2.rs [deleted file]
src/test/run-pass/deep.rs
src/test/run-pass/default-associated-types.rs [new file with mode: 0644]
src/test/run-pass/deref-rc.rs
src/test/run-pass/deriving-associated-types.rs
src/test/run-pass/deriving-encodable-decodable-box.rs
src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs
src/test/run-pass/deriving-encodable-decodable.rs [deleted file]
src/test/run-pass/deriving-eq-ord-boxed-slice.rs
src/test/run-pass/deriving-hash.rs
src/test/run-pass/deriving-self-lifetime.rs [deleted file]
src/test/run-pass/deriving-via-extension-struct-tuple.rs
src/test/run-pass/discriminant_value.rs
src/test/run-pass/dst-coerce-custom.rs
src/test/run-pass/dst-coerce-rc.rs
src/test/run-pass/dst-deref-mut.rs
src/test/run-pass/dst-deref.rs
src/test/run-pass/dst-raw.rs
src/test/run-pass/dst-struct-sole.rs
src/test/run-pass/dst-struct.rs
src/test/run-pass/dst-trait.rs
src/test/run-pass/enum-discr.rs
src/test/run-pass/enum-disr-val-pretty.rs
src/test/run-pass/enum-null-pointer-opt.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/eq-multidispatch.rs
src/test/run-pass/evec-internal.rs [deleted file]
src/test/run-pass/expr-block-fn.rs
src/test/run-pass/expr-block-unique.rs
src/test/run-pass/expr-block.rs
src/test/run-pass/expr-if-panic.rs
src/test/run-pass/exterior.rs
src/test/run-pass/fat-ptr-cast.rs
src/test/run-pass/for-loop-no-std.rs
src/test/run-pass/foreach-external-iterators-break.rs
src/test/run-pass/foreach-external-iterators-nested.rs
src/test/run-pass/foreach-external-iterators.rs
src/test/run-pass/format-no-std.rs
src/test/run-pass/generic-fn-infer.rs
src/test/run-pass/generic-tag-values.rs
src/test/run-pass/generic-temporary.rs
src/test/run-pass/global-scope.rs
src/test/run-pass/html-literals.rs
src/test/run-pass/i32-sub.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/infinite-loops.rs [deleted file]
src/test/run-pass/into-iterator-type-inference-shift.rs
src/test/run-pass/intrinsic-assume.rs
src/test/run-pass/intrinsic-move-val-cleanups.rs [new file with mode: 0644]
src/test/run-pass/intrinsic-unreachable.rs
src/test/run-pass/intrinsics-math.rs
src/test/run-pass/issue-10734.rs
src/test/run-pass/issue-11709.rs
src/test/run-pass/issue-11736.rs
src/test/run-pass/issue-11958.rs
src/test/run-pass/issue-13259-windows-tcb-trash.rs
src/test/run-pass/issue-13494.rs
src/test/run-pass/issue-13763.rs
src/test/run-pass/issue-15080.rs
src/test/run-pass/issue-15673.rs
src/test/run-pass/issue-15689-1.rs
src/test/run-pass/issue-15734.rs
src/test/run-pass/issue-16530.rs
src/test/run-pass/issue-17718-static-unsafe-interior.rs
src/test/run-pass/issue-17718.rs
src/test/run-pass/issue-17897.rs
src/test/run-pass/issue-18188.rs
src/test/run-pass/issue-18655.rs [new file with mode: 0644]
src/test/run-pass/issue-18809.rs [new file with mode: 0644]
src/test/run-pass/issue-18845.rs [new file with mode: 0644]
src/test/run-pass/issue-18913.rs [new file with mode: 0644]
src/test/run-pass/issue-18988.rs [new file with mode: 0644]
src/test/run-pass/issue-19811-escape-unicode.rs
src/test/run-pass/issue-20797.rs
src/test/run-pass/issue-21058.rs
src/test/run-pass/issue-21384.rs
src/test/run-pass/issue-21486.rs
src/test/run-pass/issue-21622.rs [new file with mode: 0644]
src/test/run-pass/issue-2185.rs [deleted file]
src/test/run-pass/issue-2190-1.rs
src/test/run-pass/issue-2190-2.rs [deleted file]
src/test/run-pass/issue-22864-1.rs [new file with mode: 0644]
src/test/run-pass/issue-22864-2.rs [new file with mode: 0644]
src/test/run-pass/issue-23037.rs
src/test/run-pass/issue-23550.rs
src/test/run-pass/issue-23649-1.rs [new file with mode: 0644]
src/test/run-pass/issue-23649-2.rs [new file with mode: 0644]
src/test/run-pass/issue-23649-3.rs [new file with mode: 0644]
src/test/run-pass/issue-23968-const-not-overflow.rs [new file with mode: 0644]
src/test/run-pass/issue-24085.rs [new file with mode: 0644]
src/test/run-pass/issue-24227.rs [new file with mode: 0644]
src/test/run-pass/issue-24258.rs [new file with mode: 0644]
src/test/run-pass/issue-24308.rs [new file with mode: 0644]
src/test/run-pass/issue-24589.rs [new file with mode: 0644]
src/test/run-pass/issue-24779.rs [new file with mode: 0644]
src/test/run-pass/issue-25180.rs [new file with mode: 0644]
src/test/run-pass/issue-25279.rs [new file with mode: 0644]
src/test/run-pass/issue-25339.rs [new file with mode: 0644]
src/test/run-pass/issue-25394.rs [new file with mode: 0644]
src/test/run-pass/issue-25497.rs [new file with mode: 0644]
src/test/run-pass/issue-25515.rs [new file with mode: 0644]
src/test/run-pass/issue-25549-multiple-drop.rs [new file with mode: 0644]
src/test/run-pass/issue-25679.rs [new file with mode: 0644]
src/test/run-pass/issue-25700-1.rs [new file with mode: 0644]
src/test/run-pass/issue-25700-2.rs [new file with mode: 0644]
src/test/run-pass/issue-25746-bool-transmute.rs [new file with mode: 0644]
src/test/run-pass/issue-25757.rs [new file with mode: 0644]
src/test/run-pass/issue-2904.rs
src/test/run-pass/issue-333.rs
src/test/run-pass/issue-4120.rs [deleted file]
src/test/run-pass/issue-4241.rs [deleted file]
src/test/run-pass/issue-5239-2.rs
src/test/run-pass/issue-6898.rs
src/test/run-pass/issue-7663.rs
src/test/run-pass/issue-7784.rs
src/test/run-pass/issue-8498.rs
src/test/run-pass/issue-9737.rs
src/test/run-pass/issue18173.rs [new file with mode: 0644]
src/test/run-pass/issue26127.rs [new file with mode: 0644]
src/test/run-pass/istr.rs
src/test/run-pass/iter-cloned-type-inference.rs
src/test/run-pass/linear-for-loop.rs
src/test/run-pass/linkage-visibility.rs
src/test/run-pass/lint-dead-code-variant.rs [new file with mode: 0644]
src/test/run-pass/logging-only-prints-once.rs
src/test/run-pass/macro-2.rs
src/test/run-pass/macro-followed-by-seq.rs [new file with mode: 0644]
src/test/run-pass/macro-pat-follow.rs [new file with mode: 0644]
src/test/run-pass/macro-tt-followed-by-seq.rs [new file with mode: 0644]
src/test/run-pass/macro-with-braces-in-expr-position.rs
src/test/run-pass/match-implicit-copy-unique.rs
src/test/run-pass/match-pattern-lit.rs
src/test/run-pass/match-range-infer.rs [new file with mode: 0644]
src/test/run-pass/match-static-const-rename.rs
src/test/run-pass/match-var-hygiene.rs
src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs
src/test/run-pass/method-self-arg-aux1.rs
src/test/run-pass/method-self-arg-aux2.rs
src/test/run-pass/method-self-arg-trait.rs
src/test/run-pass/method-self-arg.rs
src/test/run-pass/minmax-stability-issue-23687.rs
src/test/run-pass/monad.rs
src/test/run-pass/move-2-unique.rs
src/test/run-pass/move-2.rs
src/test/run-pass/move-4-unique.rs
src/test/run-pass/move-arg-2-unique.rs
src/test/run-pass/move-arg-2.rs
src/test/run-pass/move-arg.rs
src/test/run-pass/multi-let.rs
src/test/run-pass/mut-function-arguments.rs
src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs
src/test/run-pass/nested-vec-3.rs
src/test/run-pass/new-box-syntax.rs
src/test/run-pass/new-unicode-escapes.rs
src/test/run-pass/no-std-xcrate.rs [deleted file]
src/test/run-pass/no-std-xcrate2.rs [deleted file]
src/test/run-pass/nullable-pointer-iotareduction.rs
src/test/run-pass/operator-associativity.rs
src/test/run-pass/overloaded-autoderef-vtable.rs
src/test/run-pass/overloaded-autoderef.rs
src/test/run-pass/overloaded-deref.rs
src/test/run-pass/overloaded-index-assoc-list.rs
src/test/run-pass/overloaded_deref_with_ref_pattern.rs [new file with mode: 0644]
src/test/run-pass/overloaded_deref_with_ref_pattern_issue15609.rs [new file with mode: 0644]
src/test/run-pass/packed-struct-generic-layout.rs
src/test/run-pass/packed-struct-layout.rs
src/test/run-pass/packed-tuple-struct-layout.rs
src/test/run-pass/parallel-codegen-closures.rs [new file with mode: 0644]
src/test/run-pass/preempt.rs [deleted file]
src/test/run-pass/process-detach.rs [deleted file]
src/test/run-pass/process-sigpipe.rs [new file with mode: 0644]
src/test/run-pass/range.rs
src/test/run-pass/ranges-precedence.rs
src/test/run-pass/readalias.rs
src/test/run-pass/realloc-16687.rs
src/test/run-pass/regions-lifetime-static-items-enclosing-scopes.rs
src/test/run-pass/repeat-expr-in-static.rs
src/test/run-pass/resolve-issue-2428.rs
src/test/run-pass/resource-destruct.rs
src/test/run-pass/rfc-1014-2.rs [new file with mode: 0644]
src/test/run-pass/rfc-1014.rs [new file with mode: 0644]
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/self-re-assign.rs
src/test/run-pass/self-shadowing-import.rs
src/test/run-pass/send-is-not-static-par-for.rs
src/test/run-pass/shadow.rs
src/test/run-pass/simd-binop.rs
src/test/run-pass/simd-issue-10604.rs
src/test/run-pass/simd-shift-near-oflo.rs [new file with mode: 0644]
src/test/run-pass/slice-2.rs
src/test/run-pass/slice-of-zero-size-elements.rs
src/test/run-pass/slice-panic-1.rs
src/test/run-pass/slice-panic-2.rs
src/test/run-pass/slice.rs
src/test/run-pass/spawn.rs
src/test/run-pass/static-assert.rs [deleted file]
src/test/run-pass/static-mut-foreign.rs
src/test/run-pass/static-mut-xc.rs
src/test/run-pass/std-sync-right-kind-impls.rs
src/test/run-pass/string-escapes.rs
src/test/run-pass/struct-order-of-eval-3.rs
src/test/run-pass/struct-order-of-eval-4.rs
src/test/run-pass/supported-cast.rs
src/test/run-pass/swap-1.rs
src/test/run-pass/sync-send-iterators-in-libcollections.rs
src/test/run-pass/sync-send-iterators-in-libcore.rs [new file with mode: 0644]
src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment
src/test/run-pass/syntax-extension-source-utils.rs
src/test/run-pass/tag-variant-disr-val.rs
src/test/run-pass/task-comm-10.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/trait-contravariant-self.rs [deleted file]
src/test/run-pass/trait-impl.rs
src/test/run-pass/trait-inheritance-subst.rs
src/test/run-pass/trait-to-str.rs
src/test/run-pass/trait-with-bounds-default.rs
src/test/run-pass/tydesc-name.rs
src/test/run-pass/type-namespace.rs
src/test/run-pass/type-sizes.rs
src/test/run-pass/typeid-intrinsic.rs
src/test/run-pass/typestate-multi-decl.rs
src/test/run-pass/ufcs-polymorphic-paths.rs
src/test/run-pass/unboxed-closures-manual-impl.rs
src/test/run-pass/unboxed-closures-unique-type-id.rs
src/test/run-pass/unfold-cross-crate.rs
src/test/run-pass/unique-cmp.rs
src/test/run-pass/unique-in-vec.rs
src/test/run-pass/unique-kinds.rs
src/test/run-pass/unsized3.rs
src/test/run-pass/utf8_chars.rs
src/test/run-pass/vec-concat.rs
src/test/run-pass/vec-dst.rs
src/test/run-pass/vec-macro-no-std.rs
src/test/run-pass/vec-matching-autoslice.rs
src/test/run-pass/vec-tail-matching.rs
src/test/run-pass/vector-sort-panic-safe.rs
src/test/run-pass/where-for-self.rs
src/test/run-pass/while-prelude-drop.rs
src/test/run-pass/wrapping-int-api.rs
src/test/run-pass/x86stdcall2.rs
src/test/run-pass/zero-size-type-destructors.rs
src/test/rustdoc/assoc-types.rs
src/test/rustdoc/hidden-line.rs
src/test/rustdoc/issue-19190-2.rs
src/test/rustdoc/issue-19190-3.rs
src/test/rustdoc/issue-19190.rs
src/test/rustdoc/search-index.rs
src/test/rustdoc/where.rs

index 6e79eec3e795b73dab62b172585ddb1858151ed9..7e542470c2b7e75b9f9e4f8d5301e9d9945a5406 100644 (file)
@@ -1,14 +1,14 @@
 Rust was written by these fine people:
 
-A.J. Gardner <mrhota@users.noreply.github.com>
 Aaron Friel <mayreply@aaronfriel.com>
+Aaron Gallagher <_@habnab.it>
 Aaron Laursen <aaronlaursen@gmail.com>
 Aaron Liblong <liblonga@physics.utoronto.ca>
 Aaron Raimist <aaron@aaronraimist.com>
 Aaron Todd <github@opprobrio.us>
 Aaron Turon <aturon@mozilla.com>
 Aaron Weiss <aaronweiss74@gmail.com>
-Abhishek Chanda <abhishek@cloudscaling.com>
+Abhishek Chanda <abhishek.becs@gmail.com>
 Adam Bozanich <adam.boz@gmail.com>
 Adam Jacob <adam@opscode.com>
 Adam Roben <adam@roben.org>
@@ -20,59 +20,71 @@ Adrien Tétar <adri-from-59@hotmail.fr>
 Ahmed Charles <ahmedcharles@gmail.com>
 Aidan Cully <github@aidan.users.panix.com>
 Aidan Hobson Sayers <aidanhs@cantab.net>
+A.J. Gardner <mrhota@users.noreply.github.com>
 Akos Kiss <akiss@inf.u-szeged.hu>
+Akshay Chiwhane <achiwhane@gmail.com>
 Alan Andrade <alan.andradec@gmail.com>
 Alan Cutter <alancutter@chromium.org>
 Alan Williams <mralert@gmail.com>
 Aleksander Balicki <balicki.aleksander@gmail.com>
 Aleksandr Koshlo <sash7ko@gmail.com>
-Alex Crichton <alex@alexcrichton.com>
-Alex Gaynor <alex.gaynor@gmail.com>
-Alex Lyon <arcterus@mail.com>
-Alex Quach <alex@clinkle.com>
-Alex Rønne Petersen <alex@lycus.org>
-Alex Whitney <aw1209@ic.ac.uk>
+Alexander Artemenko <svetlyak.40wt@gmail.com>
 Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
 Alexander Campbell <alexanderhcampbell@gmail.com>
 Alexander Chernyakhovsky <achernya@mit.edu>
 Alexander Korolkov <alexander.korolkov@gmail.com>
 Alexander Light <allight@cs.brown.edu>
+Alexander Polakov <plhk@sdf.org>
 Alexander Stavonin <a.stavonin@gmail.com>
 Alexandre Gagnon <alxgnon@gmail.com>
 Alexandros Tasos <sdi1100085@di.uoa.gr>
+Alex Burka <durka42+github@gmail.com>
+Alex Crichton <alex@alexcrichton.com>
 Alexei Sholik <alcosholik@gmail.com>
+Alex Gaynor <alex.gaynor@gmail.com>
 Alexis Beingessner <a.beingessner@gmail.com>
+Alex Lyon <arcterus@mail.com>
+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>
-Ali Smesseim <smesseim.ali@gmail.com>
 Alisdair Owens <awo101@zepler.net>
+Ali Smesseim <smesseim.ali@gmail.com>
 Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
 Amol Mundayoor <amol.com@gmail.com>
 Amy Unger <amy.e.unger@gmail.com>
+Anatoly Ikorsky <aikorsky@gmail.com>
 Anders Kaseorg <andersk@mit.edu>
-Andre Arko <andre@arko.net>
 Andrea Canciani <ranma42@gmail.com>
+Andre Arko <andre@arko.net>
 Andreas Gal <gal@mozilla.com>
 Andreas Martens <andreasm@fastmail.fm>
 Andreas Neuhaus <zargony@zargony.com>
 Andreas Ots <andreasots@gmail.com>
 Andreas Tolfsen <ato@mozilla.com>
 Andrei Formiga <archimedes_siracusa@hotmail.com>
+Andrei Oprea <andrei.br92@gmail.com>
 Andrew Barchuk <raindev@icloud.com>
 Andrew Cann <shum@canndrew.org>
 Andrew Chin <achin@eminence32.net>
 Andrew Dunham <andrew@du.nham.ca>
+Andrew Foote <afoote97@gmail.com>
 Andrew Gallant <jamslam@gmail.com>
 Andrew Hobden <andrew@hoverbear.org>
+Andrew Kensler <andrew@eastfarthing.com>
 Andrew Paseltiner <apaseltiner@gmail.com>
 Andrew Poelstra <asp11@sfu.ca>
 Andrew Seidl <dev@aas.io>
+Andrew Straw <strawman@astraw.com>
 Andrew Wagner <drewm1980@gmail.com>
+Andrzej Janik <vosen@vosen.pl>
 Angus Lees <gus@inodes.org>
 Anthony Juckel <ajuckel@gmail.com>
 Anton Löfgren <anton.lofgren@gmail.com>
 Aram Visser <aramvisser@gmail.com>
-Areski Belaid <areski@gmail.com>
 Arcterus <Arcterus@mail.com>
+Areski Belaid <areski@gmail.com>
 Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
 Arjan Topolovec <arjan.top@gmail.com>
 Arkaitz Jimenez <arkaitzj@gmail.com>
@@ -81,29 +93,39 @@ Armin Ronacher <armin.ronacher@active-4.com>
 Arpad Borsos <arpad.borsos@googlemail.com>
 Artem <artemciy@gmail.com>
 Arthur Liao <arthurtw8@gmail.com>
+arturo <arturo@openframeworks.cc>
 Ashok Gautham <ScriptDevil@gmail.com>
 Augusto Hack <hack.augusto@gmail.com>
+auREAX <mark@xn--hwg34fba.ws>
 Austin Bonander <austin.bonander@gmail.com>
+Austin Hellyer <hello@austinhellyer.me>
 Austin King <shout@ozten.com>
 Austin Seipp <mad.one@gmail.com>
+Avdi Grimm <avdi@avdi.org>
+awlnx <alecweber1994@gmail.com>
 Axel Viala <axel.viala@darnuria.eu>
 Aydin Kim <ladinjin@hanmail.net>
+bachm <Ab@vapor.com>
 Barosl Lee <vcs@barosl.com>
+bcoopers <coopersmithbrian@gmail.com>
 Ben Alpert <ben@benalpert.com>
+benaryorg <binary@benary.org>
 Ben Ashford <ben@bcash.org>
 Ben Blum <bblum@andrew.cmu.edu>
+ben fleis <ben.fleis@gmail.com>
 Ben Foppa <benjamin.foppa@gmail.com>
 Ben Gamari <bgamari.foss@gmail.com>
+Ben Gesoff <ben.gesoff@gmail.com>
 Ben Harris <mail@bharr.is>
-Ben Kelly <ben@wanderview.com>
-Ben Noordhuis <info@bnoordhuis.nl>
-Ben Sago <ogham@users.noreply.github.com>
-Ben Striegel <ben.striegel@gmail.com>
 Benjamin Adamson <adamson.benjamin@gmail.com>
 Benjamin Herr <ben@0x539.de>
 Benjamin Jackman <ben@jackman.biz>
 Benjamin Kircher <benjamin.kircher@gmail.com>
 Benjamin Peterson <benjamin@python.org>
+Ben Kelly <ben@wanderview.com>
+Ben Noordhuis <info@bnoordhuis.nl>
+Ben Sago <ogham@users.noreply.github.com>
+Ben Striegel <ben.striegel@gmail.com>
 Bheesham Persaud <bheesham123@hotmail.com>
 Bilal Husain <bilal@bilalhusain.com>
 Bill Fallon <bill.fallon@robos.li>
@@ -111,8 +133,13 @@ Bill Myers <bill_myers@outlook.com>
 Bill Wendling <wendling@apple.com>
 Birunthan Mohanathas <birunthan@mohanathas.com>
 Björn Steinbrink <bsteinbr@gmail.com>
+blake2-ppc <ulrik.sverdrup@gmail.com>
+bluss <bluss>
+bluss <bluss@users.noreply.github.com>
 Boris Egorov <egorov@linux.com>
+bors <bors@rust-lang.org>
 Bouke van der Bijl <boukevanderbijl@gmail.com>
+Brad King <brad.king@kitware.com>
 Brandon Sanderson <singingboyo@gmail.com>
 Brandon Waskiewicz <brandon.waskiewicz@gmail.com>
 Branimir <branimir@volomp.com>
@@ -130,28 +157,31 @@ Brian J Brennan <brianloveswords@gmail.com>
 Brian J. Burg <burg@cs.washington.edu>
 Brian Koropoff <bkoropoff@gmail.com>
 Brian Leibig <brian@brianleibig.com>
+Brian Quinlan <brian@sweetapp.com>
 Bruno de Oliveira Abinader <bruno.d@partner.samsung.com>
 Bryan Dunsmore <dunsmoreb@gmail.com>
 Byron Williams <byron@112percent.com>
 Cadence Marseille <cadencemarseille@gmail.com>
 Caitlin Potter <snowball@defpixel.com>
-Cam Jackson <camjackson89@gmail.com>
 Cameron Zwarich <zwarich@mozilla.com>
 Camille Roussel <camille@rousselfamily.com>
 Camille TJHOA <camille.tjhoa@outlook.com>
-CarVac <c.lo.to.da.down.lo@gmail.com>
-Carl Lerche <me@carllerche.com>
+Cam Jackson <camjackson89@gmail.com>
 Carl-Anton Ingmarsson <mail@carlanton.se>
+Carl Lerche <me@carllerche.com>
 Carlos Galarza <carloslfu@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>
 Chase Southwood <chase.southwood@gmail.com>
 Ches Martin <ches@whiskeyandgrits.net>
+chitra
 Chloe <5paceToast@users.noreply.github.com>
 Chris Double <chris.double@double.co.nz>
+Chris Hellmuth <chellmuth@gmail.com>
 Chris Morgan <me@chrismorgan.info>
 Chris Nixon <chris.nixon@sigma.me.uk>
 Chris Peterson <cpeterson@mozilla.com>
@@ -159,28 +189,37 @@ Chris Pressey <cpressey@gmail.com>
 Chris Sainty <csainty@hotmail.com>
 Chris Shea <cmshea@gmail.com>
 Chris Thorn <chris@thorn.co>
-Chris Wong <lambda.fairy@gmail.com>
+Christian Stadelmann <dev@genodeftest.de>
 Christoph Burgdorf <christoph.burgdorf@bvsn.org>
 Christopher Bergqvist <spambox0@digitalpoetry.se>
 Christopher Chambers <chris.chambers@peanutcode.com>
 Christopher Kendell <ckendell@outlook.com>
+Chris Wong <lambda.fairy@gmail.com>
+chromatic <chromatic@wgz.org>
+Chuck Bassett <iamchuckb@gmail.com>
 Chuck Ries <chuck.ries@gmail.com>
 Clark Gaebel <cg.wowus.cg@gmail.com>
+clatour <chandler.latour@gmail.com>
 Clifford Caoile <piyo@users.sf.net>
 Clinton Ryan <clint.ryan3@gmail.com>
 Cody P Schafer <dev@codyps.com>
 Cody Schroeder <codys@cs.washington.edu>
 Cole Mickens <cole.mickens@gmail.com>
+Cole Reynolds <cpjreynolds@gmail.com>
 Colin Davidson <colrdavidson@gmail.com>
 Colin Sherratt <colin.sherratt@gmail.com>
+Colin Walters <walters@verbum.org>
+comex <comexk@gmail.com>
 Conrad Kleinespel <conradk@conradk.com>
 Corey Farwell <coreyf+rust@rwell.org>
 Corey Ford <corey@coreyford.name>
 Corey Richardson <corey@octayn.net>
-Cristi Burcă <scribu@gmail.com>
+Cornel Punga <cornel.punga@gmail.com>
+crhino <piraino.chris@gmail.com>
 Cristian Kubis <cristian.kubis@tsunix.de>
-DJUrsus <colinvh@divitu.com>
-David Ross <daboross@daboross.net>
+Cristi Burcă <scribu@gmail.com>
+critiqjo <john.ch.fr@gmail.com>
+Cruz Julian Bishop <cruzjbishop@gmail.com>
 Damian Gryski <damian@gryski.com>
 Damien Grassart <damien@grassart.com>
 Damien Radtke <dradtke@channeliq.com>
@@ -189,10 +228,6 @@ Dan Albert <danalbert@google.com>
 Dan Burkert <dan@danburkert.com>
 Dan Callahan <dan.callahan@gmail.com>
 Dan Connolly <dckc@madmode.com>
-Dan Luu <danluu@gmail.com>
-Dan Schatzberg <schatzberg.dan@gmail.com>
-Dan W. <1danwade@gmail.com>
-Dan Yang <dsyang@fb.com>
 Daniel Brooks <db48x@db48x.net>
 Daniel Fagnan <dnfagnan@gmail.com>
 Daniel Farina <daniel@fdr.io>
@@ -206,14 +241,21 @@ Daniel Micay <danielmicay@gmail.com>
 Daniel Patterson <dbp@riseup.net>
 Daniel Raloff <draloff@side2.com>
 Daniel Ralston <Wubbulous@gmail.com>
+Daniel Ramos <dan@daramos.com>
 Daniel Rosenwasser <DanielRosenwasser@gmail.com>
 Daniel Ursache Dogariu <contact@danniel.net>
 Daniil Smirnov <danslapman@gmail.com>
+Dan Luu <danluu@gmail.com>
+Dan Schatzberg <schatzberg.dan@gmail.com>
+Dan W. <1danwade@gmail.com>
+Dan Yang <dsyang@fb.com>
 Darin Morrison <darinmorrison+git@gmail.com>
+darkf <lw9k123@gmail.com>
 Darrell Hamilton <darrell.noice@gmail.com>
 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 Forsythe <dforsythe@gmail.com>
 David Halperin <halperin.dr@gmail.com>
@@ -222,31 +264,42 @@ David Klein <david.klein@baesystemsdetica.com>
 David Mally <djmally@gmail.com>
 David Manescu <david.manescu@gmail.com>
 David Rajchenbach-Teller <dteller@mozilla.com>
+David Reid <dreid@dreid.org>
 David Renshaw <dwrenshaw@gmail.com>
+David Ross <daboross@daboross.net>
+David Stygstra <david.stygstra@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>
 Derecho <derecho@sector5d.org>
 Derek Chiang <derekchiang93@gmail.com>
 Derek Guenther <dguenther9@gmail.com>
 Derek Harland <derek.harland@finq.co.nz>
+dgoon <dgoon@dgoon.net>
 Diego Giagio <diego@giagio.com>
 Diego Ongaro <ongaro@cs.stanford.edu>
 Diggory Blake <diggsey@googlemail.com>
 Diggory Hardy <diggory.hardy@gmail.com>
 Dimitri Krassovski <labria@startika.com>
 Dirk Gadsden <dirk@esherido.com>
-Dirk Leifeld <leifeld@posteo.de>
 Dirkjan Bussink <d.bussink@gmail.com>
+Dirk Leifeld <leifeld@posteo.de>
 Div Shekhar <div@pagerduty.com>
+diwic <diwic@users.noreply.github.com>
+DJUrsus <colinvh@divitu.com>
+dmgawel <dgkonik@gmail.com>
 Dmitry Ermolov <epdmitry@yandex.ru>
 Dmitry Promsky <dmitry@willworkforcookies.com>
 Dmitry Vasiliev <dima@hlabs.org>
-Do Nhat Minh <mrordinaire@gmail.com>
-Dominic van Berkel <dominic@baudvine.net>
 Dominick Allen <dominick.allen1989@gmail.com>
+Dominic van Berkel <dominic@baudvine.net>
 Dominik Inführ <dominik.infuehr@gmail.com>
+Do Nhat Minh <mrordinaire@gmail.com>
+donkopotamus <general@chocolate-fish.com>
 Donovan Preston <donovanpreston@gmail.com>
+Don Petersen <don@donpetersen.net>
 Douglas Young <rcxdude@gmail.com>
 Drew Crawford <drew@sealedabstract.com>
 Drew Willcoxon <adw@mozilla.com>
@@ -256,6 +309,7 @@ Dylan Braithwaite <dylanbraithwaite1@gmail.com>
 Dylan Ede <dylanede@googlemail.com>
 Dzmitry Malyshau <kvarkus@gmail.com>
 Earl St Sauver <estsauver@gmail.com>
+econoplas <econoplas@gmail.com>
 Eduard Bopp <eduard.bopp@aepsil0n.de>
 Eduard Burtescu <edy.burt@gmail.com>
 Eduardo Bautista <me@eduardobautista.com>
@@ -263,21 +317,29 @@ Edward Wang <edward.yu.wang@gmail.com>
 Edward Z. Yang <ezyang@cs.stanford.edu>
 Ehsanul Hoque <ehsanul@ehsanul.com>
 Elantsev Serj <elantsev@yandex-team.ru>
+Eli Friedman <eli.friedman@gmail.com>
+eliovir <eliovir@gmail.com>
 Elliott Slaughter <elliottslaughter@gmail.com>
 Elly Fong-Jones <elly@leptoquark.net>
+elszben <notgonna@tellyou>
+emanueLczirai <emanueLczirai@cryptoLab.net>
 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 Holk <eric.holk@gmail.com>
 Eric Holmes <eric@ejholmes.net>
 Eric Kidd <git@randomhacks.net>
+Erick Rivas <chemical.rivas@gmail.com>
+Erick Tryzelaar <erick.tryzelaar@gmail.com>
 Eric Martin <e.a.martin1337@gmail.com>
 Eric Platon <eric.platon@waku-waku.ne.jp>
 Eric Reed <ecreed@cs.washington.edu>
-Erick Rivas <chemical.rivas@gmail.com>
-Erick Tryzelaar <erick.tryzelaar@gmail.com>
+Eric Ye <me@ericye16.com>
 Erik Lyon <elyon001@local.fake>
+Erik Michaels-Ober <sferik@gmail.com>
 Erik Price <erik.price16@gmail.com>
 Erik Rose <erik@mozilla.com>
 Erwan <erwan.ricq@gmail.com>
@@ -295,53 +357,71 @@ Fedor Indutny <fedor.indutny@gmail.com>
 Felix Crux <felixc@felixcrux.com>
 Felix Raimundo <felix.raimundo@telecom-paristech.fr>
 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>
+flo-l <lacknerflo@gmail.com>
 Florian Gilcher <florian.gilcher@asquera.de>
 Florian Hahn <flo@fhahn.com>
 Florian Hartwig <florian.j.hartwig@gmail.com>
 Florian Wilkens <mrfloya_github@outlook.com>
 Florian Zeitz <florob@babelmonkeys.de>
+fort <e@mail.com>
 Francisco Souza <f@souza.cc>
+frankamp <frankamp@gmail.com>
 Franklin Chen <franklinchen@franklinchen.com>
+Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
+free-Runner <aali07@students.poly.edu>
 FuGangqiang <fu_gangqiang@163.com>
+funkill <funkill2@gmail.com>
+g3xzh <g3xzh@yahoo.com>
+Gábor Horváth <xazax.hun@gmail.com>
+Gábor Lehel <glaebhoerl@gmail.com>
 Gabriel <g2p.code@gmail.com>
+gamazeps <gamaz3ps@gmail.com>
 Gareth Daniel Smith <garethdanielsmith@gmail.com>
+gareth <gareth@gareth-N56VM.(none)>
+Garming Sam <garming_sam@outlook.com>
 Garrett Heel <garrettheel@gmail.com>
 Gary Linscott <glinscott@gmail.com>
 Gary M. Josack <gary@byoteki.com>
 Gavin Baker <gavinb@antonym.org>
+gentlefolk <cemacken@gmail.com>
 Geoff Hill <geoff@geoffhill.org>
 Geoffrey Thomas <geofft@ldpreload.com>
 Geoffroy Couprie <geo.couprie@gmail.com>
+Geoffry Song <goffrie@gmail.com>
 George Papanikolaou <g3orge.app@gmail.com>
 Georges Dubus <georges.dubus@gmail.com>
 Germano Gabbianelli <tyrion@users.noreply.github.com>
 Gil Cottle <rc@redtown.org>
 Gioele Barabucci <gioele@svario.it>
+github-monoculture <eocene@gmx.com>
 Gleb Kozyrev <gleb@gkoz.com>
 Glenn Willen <gwillen@nerdnet.org>
 Gonçalo Cabrita <_@gmcabrita.com>
-Graham Fawcett <graham.fawcett@gmail.com>
 Grahame Bowland <grahame@angrygoats.net>
+Graham Fawcett <graham.fawcett@gmail.com>
 Graydon Hoare <graydon@pobox.com>
 Greg Chapple <gregchapple1@gmail.com>
 Grigoriy <ohaistarlight@gmail.com>
 Guillaume Gomez <guillaume1.gomez@gmail.com>
 Guillaume Pinot <texitoi@texitoi.eu>
+Gulshan Singh <gsingh2011@gmail.com>
 Gyorgy Andrasek <jurily@gmail.com>
-Gábor Horváth <xazax.hun@gmail.com>
-Gábor Lehel <glaebhoerl@gmail.com>
 Haitao Li <lihaitao@gmail.com>
 Hajime Morrita <omo@dodgson.org>
 Hanno Braun <mail@hannobraun.de>
+hansjorg <hansjorg@gmail.com>
 Harry Marr <harry.marr@gmail.com>
 Heather <heather@cynede.net>
-Heejong Ahn <heejongahn@gmail.com
+Hech <tryctor@gmail.com>
+Heejong Ahn <heejongahn@gmail.com>
 Henrik Schopmans <h.schopmans@googlemail.com>
 Herman J. Radtke III <herman@hermanradtke.com>
 HeroesGrave <heroesgrave@gmail.com>
+Hika Hibariya <hibariya@gmail.com>
 Hong Chulju <ang0123dev@gmail.com>
 Honza Strnad <hanny.strnad@gmail.com>
 Huachao Huang <huachao.huang@gmail.com>
@@ -350,26 +430,24 @@ Hugo van der Wijst <hugo@wij.st>
 Huon Wilson <dbau.pp+github@gmail.com>
 Hyeon Kim <simnalamburt@gmail.com>
 Ian Connolly <iconnolly@mozilla.com>
-Ian D. Bollinger <ian.bollinger@gmail.com>
 Ian Daniher <it.daniher@gmail.com>
+Ian D. Bollinger <ian.bollinger@gmail.com>
 Ignacio Corderi <icorderi@msn.com>
 Igor Bukanov <igor@mir2.org>
 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>
 Isaac Aggrey <isaac.aggrey@gmail.com>
 Isaac Dupree <antispam@idupree.com>
+Isaac Ge <acgtyrant@gmail.com>
 Ivan Enderlin <ivan.enderlin@hoa-project.net>
+Ivano Coppola <rgbfirefox@gmail.com>
 Ivan Petkov <ivanppetkov@gmail.com>
 Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
 Ivan Ukhov <ivan.ukhov@gmail.com>
-Ivano Coppola <rgbfirefox@gmail.com>
-J. J. Weber <jjweber@gmail.com>
-J.C. Moyer <jmoyer1992@gmail.com>
-JONNALAGADDA Srinivas <js@ojuslabs.com>
-JP Sugarbroad <jpsugar@google.com>
-JP-Ellis <coujellis@gmail.com>
+Iven Hsu <ivenvd@gmail.com>
 Jack Heizer <jack.heizer@gmail.com>
 Jack Moffitt <jack@metajack.im>
 Jacob Edelman <edelman.jd@gmail.com>
@@ -379,23 +457,30 @@ Jacob Parker <j3parker@csclub.uwaterloo.ca>
 Jaemin Moon <jaemin.moon@samsung.com>
 Jag Talon <talon.jag@gmail.com>
 Jake Goulding <jake.goulding@gmail.com>
+Jake Hickey <empty@cqdr.es>
 Jake Kaufman <theevocater@gmail.com>
 Jake Kerr <kodafox@gmail.com>
 Jake Scott <jake.net@gmail.com>
 Jakub Bukaj <jakub@jakub.cc>
-Jakub Wieczorek <jakubw@jakubw.net>
 Jakub Vrána <jakub@vrana.cz>
+Jakub Wieczorek <jakubw@jakubw.net>
 James Deng <cnjamesdeng@gmail.com>
 James Hurst <jamesrhurst@users.noreply.github.com>
 James Lal <james@lightsofapollo.com>
 James Laverack <james@jameslaverack.com>
-James Miller <james@aatch.net>
+jamesluke <jamesluke@users.noreply.github.com>
+James Miller <bladeon@gmail.com>
+James Perry <james.austin.perry@gmail.com>
 James Rowe <jroweboy@gmail.com>
 James Sanders <sanderjd@gmail.com>
 James Tranovich <james@openhorizonlabs.com>
+Jan Andersson <jan.andersson@gmail.com>
+Jan Bujak <j@exia.io>
+Jan-Erik Rediger <janerik@fnordig.de>
 Jan Kobler <eng1@koblersystems.de>
 Jan Niklas Hasse <jhasse@gmail.com>
 Jannis Harder <jix@jixco.de>
+Jannis Redmann <mail@jannisr.de>
 Jared Roesch <roeschinc@gmail.com>
 Jarod Liu <liuyuanzhi@gmail.com>
 Jashank Jeremy <jashank@rulingia.com>
@@ -403,9 +488,14 @@ Jason Fager <jfager@gmail.com>
 Jason Orendorff <jorendorff@mozilla.com>
 Jason Thompson <jason@jthompson.ca>
 Jason Toffaletti <toffaletti@gmail.com>
+Jason Yeo <jasonyeo88@gmail.com>
+jatinn <jatinn@users.noreply.github.com>
 Jauhien Piatlicki <jauhien@gentoo.org>
 Jay Anderson <jayanderson0@gmail.com>
 Jay True <glacjay@gmail.com>
+J Bailey <jj2baile@uwaterloo.ca>
+jbranchaud <jbranchaud@gmail.com>
+J.C. Moyer <jmoyer1992@gmail.com>
 Jeaye <jeaye@arrownext.com>
 Jed Davis <jld@panix.com>
 Jed Estep <aje@jhu.edu>
@@ -419,28 +509,34 @@ Jelte Fennema <github-tech@jeltef.nl>
 Jens Nockert <jens@nockert.se>
 Jeong YunWon <jeong@youknowone.org>
 Jeremy Letang <letang.jeremy@gmail.com>
+Jeremy Schlatter <jeremy.schlatter@gmail.com>
 Jesse Jones <jesse9jones@gmail.com>
 Jesse Luehrs <doy@tozt.net>
 Jesse Ray <jesse@localhost.localdomain>
 Jesse Ruderman <jruderman@gmail.com>
 Jessy Diamond Exum <jessy.diamondman@gmail.com>
+Jexell <Jexell@users.noreply.github.com>
 Jihyeok Seo <me@limeburst.net>
 Jihyun Yu <j.yu@navercorp.com>
 Jim Apple <jbapple+rust@google.com>
 Jim Blandy <jimb@red-bean.com>
-Jim Radford <radford@blackbean.org>
 Jimmie Elvenmark <flugsio@gmail.com>
 Jimmy Lu <jimmy.lu.2011@gmail.com>
 Jimmy Zelinskie <jimmyzelinskie@gmail.com>
+Jim Radford <radford@blackbean.org>
 Jiří Stránský <jistr@jistr.com>
+J. J. Weber <jjweber@gmail.com>
+jmgrosen <jmgrosen@gmail.com>
+jmu303 <muj@bc.edu>
 João Oliveira <hello@jxs.pt>
 Joe Pletcher <joepletcher@gmail.com>
 Joe Schafer <joe@jschaf.com>
-Johann Hofmann <mail@johann-hofmann.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 Tuffe <tafia973@gmail.com>
 John Albietz <inthecloud247@gmail.com>
 John Barker <jebarker@gmail.com>
 John Clements <clements@racket-lang.org>
@@ -454,16 +550,21 @@ 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 Van Enk <vanenkj@gmail.com>
 John Zhang <john@zhang.io>
-Jon Haddad <jon@jonhaddad.com>
-Jon Morton <jonanin@gmail.com>
+joliv <joliv@users.noreply.github.com>
 Jonas Hietala <tradet.h@gmail.com>
 Jonathan Bailey <jbailey@mozilla.com>
 Jonathan Boyett <jonathan@failingservers.com>
 Jonathan Reem <jonathan.reem@gmail.com>
 Jonathan S <gereeter@gmail.com>
 Jonathan Sternberg <jonathansternberg@gmail.com>
+Jon Haddad <jon@jonhaddad.com>
+Jon Morton <jonanin@gmail.com>
+JONNALAGADDA Srinivas <js@ojuslabs.com>
+jooert <jooert@users.noreply.github.com>
 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>
@@ -478,8 +579,12 @@ Josh Matthews <josh@joshmatthews.net>
 Josh Stone <cuviper@gmail.com>
 Josh Triplett <josh@joshtriplett.org>
 Joshua Clark <joshua.clark@txstate.edu>
+Joshua Landau <joshua@landau.ws>
 Joshua Wise <joshua@joshuawise.com>
 Joshua Yanovski <pythonesque@gmail.com>
+JP-Ellis <coujellis@gmail.com>
+JP Sugarbroad <jpsugar@google.com>
+jrincayc <jrincayc@users.noreply.github.com>
 Julia Evans <julia@jvns.ca>
 Julian Orth <ju.orth@gmail.com>
 Julian Viereck <julian.viereck@gmail.com>
@@ -487,6 +592,8 @@ Junseok Lee <lee.junseok@berkeley.edu>
 Junyoung Cho <june0.cho@samsung.com>
 JustAPerson <jpriest8@ymail.com>
 Justin Noah <justinnoah@gmail.com>
+juxiliary <juxiliary@gmail.com>
+jxv <joevargas@hush.com>
 Jyun-Yan You <jyyou.tw@gmail.com>
 Kang Seonghoon <kang.seonghoon@mearie.org>
 Kasey Carrothers <kaseyc.808@gmail.com>
@@ -505,10 +612,18 @@ Kevin Murphy <kemurphy.cmu@gmail.com>
 Kevin Rauwolf <sweetpea-git@tentacle.net>
 Kevin Walter <kevin.walter.private@googlemail.com>
 Kevin Yap <me@kevinyap.ca>
+kgv <mail@kgv.name>
 Kiet Tran <ktt3ja@gmail.com>
 Kim Røen <kim@pam.no>
+kjpgit <kjpgit@users.noreply.github.com>
+klutzy <klutzytheklutzy@gmail.com>
 KokaKiwi <kokakiwi+rust@kokakiwi.net>
+korenchkin <korenchkin2@gmail.com>
 Kostas Karachalios <vrinek@me.com>
+Krzysztof Drewniak <krzysdrewniak@gmail.com>
+Kubilay Kocak <koobs@users.noreply.github.com>
+kulakowski <george.kulakowski@gmail.com>
+kwantam <kwantam@gmail.com>
 Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
 Lai Jiangshan <laijs@cn.fujitsu.com>
 Lars Bergstrom <lbergstrom@mozilla.com>
@@ -517,57 +632,74 @@ Laurent Bonnans <bonnans.l@gmail.com>
 Lauri Lehmijoki <lauri.lehmijoki@iki.fi>
 Lawrence Velázquez <larryv@alum.mit.edu>
 Leah Hanson <astrieanna@gmail.com>
+Lee Aronson <lee@libertad.ucsd.edu>
+Lee Jeffery <leejeffery@gmail.com>
 Lee Wondong <wdlee91@gmail.com>
 LemmingAvalanche <haugsbakk@yahoo.no>
 Lennart Kudling <github@kudling.de>
-Leo Testard <leo.testard@gmail.com>
+Leo Correa <lcorr005@gmail.com>
 Leonids Maslovs <leonids.maslovs@galeoconsulting.com>
+Leo Testard <leo.testard@gmail.com>
+leunggamciu <gamciuleung@gmail.com>
 Liam Monahan <liam@monahan.io>
 Liigo Zhuang <com.liigo@gmail.com>
 Lindsey Kuper <lindsey@composition.al>
 Lionel Flandrin <lionel.flandrin@parrot.com>
 Logan Chien <tzuhsiang.chien@gmail.com>
 Loïc Damien <loic.damien@dzamlo.ch>
+Lorenz <lorenzb@student.ethz.ch>
+lpy <pylaurent1314@gmail.com>
 Luca Bruno <lucab@debian.org>
+lucy <ne.tetewi@gmail.com>
 Luis de Bethencourt <luis@debethencourt.com>
+Łukasz Niemier <lukasz@niemier.pl>
 Luke Francl <look@recursion.org>
 Luke Gallagher <luke@hypergeometric.net>
 Luke Metz <luke.metz@students.olin.edu>
 Luke Steensen <luke.steensen@gmail.com>
+lummax <luogpg@googlemail.com>
 Luqman Aden <me@luqman.ca>
-Łukasz Niemier <lukasz@niemier.pl>
+lyuts <dioxinu@gmail.com>
+madmalik <matthias.tellen@googlemail.com>
 Magnus Auvinen <magnus.auvinen@gmail.com>
 Mahmut Bulut <mahmutbulut0@gmail.com>
+maikklein <maikklein@googlemail.com>
 Makoto Nakashima <makoto.nksm+github@gmail.com>
 Manish Goregaokar <manishsmail@gmail.com>
 Manuel Hoffmann <manuel@polythematik.de>
+marcell <marcell.pardavi@gmail.com>
+Marcel Müller <neikos@neikos.email>
 Marcel Rodrigues <marcelgmr@gmail.com>
+Marcus Klaas <mail@marcusklaas.nl>
 Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
 Marijn Haverbeke <marijnh@gmail.com>
+Marin Atanasov Nikolov <dnaeon@gmail.com>
+Mário Feroldi <thelost-t@live.com>
 Mark Lacey <641@rudkx.com>
 Mark Mossberg <mark.mossberg@gmail.com>
 Mark Rowe <mrowe@bdash.net.nz>
 Mark Sinclair <mark.edward.x@gmail.com>
-Mark Vian <mrv.caseus@gmail.com>
 Markus Siemens <siemens1993@gmail.com>
 Markus Unterwaditzer <markus@unterwaditzer.net>
-Marti Raudsepp <marti@juffo.org>
+Markus Westerlind <marwes91@gmail.com>
+Mark Vian <mrv.caseus@gmail.com>
 Martin DeMello <martindemello@gmail.com>
 Martin Olsson <martin@minimum.se>
 Martin Pool <mbp@sourcefrog.net>
+Marti Raudsepp <marti@juffo.org>
 Marvin Löbel <loebel.marvin@gmail.com>
+masklinn <github.com@masklinn.net>
 Matej Lach <matej.lach@gmail.com>
 Mateusz Czapliński <czapkofan@gmail.com>
+Mathieu David <mathieudavid@mathieudavid.org>
 Mathieu Poumeyrol <kali@zoy.org>
+Mathieu Rochette <mathieu@rochette.cc>
 Mathijs van de Nes <git@mathijs.vd-nes.nl>
 Matt Brubeck <mbrubeck@limpet.net>
 Matt Carberry <carberry.matt@gmail.com>
 Matt Coffin <mcoffin13@gmail.com>
 Matt Cox <mattcoxpdx@gmail.com>
-Matt McPherrin <git@mcpherrin.ca>
-Matt Murphy <matthew.john.murphy@gmail.com>
-Matt Roche <angst7@gmail.com>
-Matt Windsor <mattwindsor@btinternet.com>
+Matthew Astley <mca@sanger.ac.uk>
 Matthew Auld <matthew.auld@intel.com>
 Matthew Iselin <matthew@theiselins.net>
 Matthew McPherrin <matthew@mcpherrin.ca>
@@ -575,11 +707,19 @@ Matthew O'Connor <thegreendragon@gmail.com>
 Matthias Einwag <matthias.einwag@live.com>
 Matthijs Hofstra <thiezz@gmail.com>
 Matthijs van der Vleuten <git@zr40.nl>
-Max Penet <max.penet@gmail.com>
-Maxim Kolganov <kolganov.mv@gmail.com>
+Matt McPherrin <git@mcpherrin.ca>
+Matt Murphy <matthew.john.murphy@gmail.com>
+Matt Roche <angst7@gmail.com>
+Matt Windsor <mattwindsor@btinternet.com>
+Mátyás Mustoha <mmatyas@inf.u-szeged.hu>
 Maxime Quandalle <maxime@quandalle.com>
 Maximilian Haack <mxhaack@gmail.com>
+Maxim Kolganov <kolganov.mv@gmail.com>
+Max Jacobson <max@hardscrabble.net>
+Max Penet <max.penet@gmail.com>
 Maya Nitu <maya_nitu@yahoo.com>
+mchaput <matt@whoosh.ca>
+mdinger <mdinger.bugzilla@gmail.com>
 Meyer S. Jacobs <meyermagic@gmail.com>
 Micah Chalmer <micah@micahchalmer.net>
 Michael Alexander <beefsack@gmail.com>
@@ -591,55 +731,69 @@ Michael Darakananda <pongad@gmail.com>
 Michael Fairley <michaelfairley@gmail.com>
 Michael Gehring <mg@ebfe.org>
 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 Neumann <mneumann@ntecs.de>
 Michael Pankov <work@michaelpankov.com>
+Michael Park <mcypark@gmail.com>
 Michael Pratt <michael@pratt.im>
 Michael Reinhard <mcreinhard@users.noreply.github.com>
+Michael Rosenberg <42micro@gmail.com>
 Michael Sproul <micsproul@gmail.com>
 Michael Sullivan <sully@msully.net>
 Michael Williams <m.t.williams@live.com>
 Michael Woerister <michaelwoerister@posteo>
+Michael Wu <mwu@mozilla.com>
 Michael Zhou <moz@google.com>
 Michał Czardybon <mczard@poczta.onet.pl>
 Michał Krasnoborski <mkrdln@gmail.com>
-Mick Koch <kchmck@gmail.com>
 Mickaël Delahaye <mickael.delahaye@gmail.com>
 Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
 Mickaël Salaün <mic@digikod.net>
+Mick Koch <kchmck@gmail.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 Pedersen <noctune9@gmail.com>
 Mike Robinson <mikeprobinsonuk@gmail.com>
+Mike Sampson <mike@sambodata.com>
 Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 Mikko Perttunen <cyndis@kapsi.fi>
+mitchmindtree <mitchell.nordine@gmail.com>
+Mohammed Attia <skeuomorf@gmail.com>
+moonglum <moonglum@moonbeamlabs.com>
+mrec <mike.capp@gmail.com>
+mr.Shu <mr@shu.io>
 Ms2ger <ms2ger@gmail.com>
 Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
 Murarth <murarth@gmail.com>
-Mátyás Mustoha <mmatyas@inf.u-szeged.hu>
-NODA, Kai <nodakai@gmail.com>
+musitdev <philippe.delrieu@free.fr>
 Nafis <nhoss2@gmail.com>
+nathan dotz <nathan.dotz@gmail.com>
 Nathan Froyd <froydnj@gmail.com>
+Nathaniel Herman <nherman@post.harvard.edu>
+Nathaniel Theis <nttheis@gmail.com>
+Nathan Long <nathanmlong@gmail.com>
 Nathan Stoddard <nstodda@purdue.edu>
 Nathan Typanski <ntypanski@gmail.com>
 Nathan Wilson <wilnathan@gmail.com>
 Nathan Zadoks <nathan@nathan7.eu>
-Nathaniel Herman <nherman@post.harvard.edu>
-Nathaniel Theis <nttheis@gmail.com>
 Neil Pankey <npankey@gmail.com>
+Nelo Onyiah <nelo.onyiah@gmail.com>
 Nelson Chen <crazysim@gmail.com>
 NiccosSystem <niccossystem@gmail.com>
 Nicholas Bishop <nicholasbishop@gmail.com>
 Nicholas Mazzuca <npmazzuca@gmail.com>
 Nick Cameron <ncameron@mozilla.com>
 Nick Desaulniers <ndesaulniers@mozilla.com>
+Nick Fitzgerald <fitzgen@gmail.com>
 Nick Hamann <nick@wabbo.org>
 Nick Howell <howellnick@gmail.com>
-Nick Sarten <gen.battle@gmail.com>
 Nick Platt <platt.nicholas@gmail.com>
+Nick Sarten <gen.battle@gmail.com>
 Nicolas Silva <nical.silva@gmail.com>
 Niels Egberts <git@nielsegberts.nl>
 Niels langager Ellegaard <niels.ellegaard@gmail.com>
@@ -647,33 +801,49 @@ Nif Ward <nif.ward@gmail.com>
 Nikita Pekin <contact@nikitapek.in>
 Niklas Koep <niklas.koep@gmail.com>
 Niko Matsakis <niko@alum.mit.edu>
+Nils Liberg <nils@nilsliberg.se>
+Nils Winter <nils.winter@gmail.com>
+noam <noam@clusterfoo.com>
 Noam Yorav-Raphael <noamraph@gmail.com>
+NODA, Kai <nodakai@gmail.com>
 Noufal Ibrahim <noufal@nibrahim.net.in>
+novalis <novalis@novalis.org>
+nsf <no.smile.face@gmail.com>
+nwin <nwin@users.noreply.github.com>
 Oak <White-Oak@users.noreply.github.com>
-O S K Chaitanya <osk@medhas.org>
 OGINO Masanori <masanori.ogino@gmail.com>
+OlegTsyba <idethrone1@gmail.com>
+Oliver Schneider <git1984941651981@oli-obk.de>
 Oliver Schneider <github6541940@oli-obk.de>
 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>
-Or Neeman <oneeman@gmail.com>
 Oren Hazi <oren.hazi@gmail.com>
-Orpheus Lummis <o@orpheuslummis.com>
+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>
 Ožbolt Menegatti <ozbolt.menegatti@gmail.com>
 P1start <rewi-github@whanau.org>
 Pablo Brasero <pablo@pablobm.com>
 Palmer Cox <p@lmercox.com>
 Paolo Falabella <paolo.falabella@gmail.com>
+Parker Moore <parkrmoore@gmail.com>
 Pascal Hertleif <killercup@gmail.com>
 Patrick Reisert <kpreisert@gmail.com>
 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 Banks <banks@banksdesigns.co.uk>
 Paul Collier <paul@paulcollier.ca>
 Paul Collins <paul@ondioline.org>
 Paul Crowley <paulcrowley@google.com>
+Paul Faria <paul_faria@ultimatesoftware.com>
+Paul Oliver <puzza007@gmail.com>
 Paul Osborne <osbpau@gmail.com>
 Paul Quint <DrKwint@gmail.com>
 Paul Stansifer <paul.stansifer@gmail.com>
@@ -682,8 +852,10 @@ Pavel Panchekha <me@pavpanchekha.com>
 Pawel Olzacki <p.olzacki2@samsung.com>
 Pedro Larroy <pedro.larroy@here.com>
 Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com>
+peferron <pe.ferron@gmail.com>
+Pete Hunt <petehunt@users.noreply.github.com>
 Peter Atashian <retep998@gmail.com>
-Peter Elmers <peter.elmers@rice.edu>
+Peter Elmers <peter.elmers@yahoo.com>
 Peter Hull <peterhull90@gmail.com>
 Peter Marheine <peter@taricorp.net>
 Peter Minten <peter@pminten.nl>
@@ -691,23 +863,26 @@ Peter Schuller <peter.schuller@infidyne.com>
 Peter Williams <peter@newton.cx>
 Peter Zotov <whitequark@whitequark.org>
 Petter Remen <petter.remen@gmail.com>
+pez <james.austin.perry@gmail.com>
 Phil Dawes <phil@phildawes.net>
-Phil Ruffwind <rf@rufflewind.com>
 Philip Munksgaard <pmunksgaard@gmail.com>
 Philipp Brüschweiler <blei42@gmail.com>
 Philipp Gesang <phg42.2a@gmail.com>
+Phil Ruffwind <rf@rufflewind.com>
 Pierre Baillet <pierre@baillet.name>
 Piotr Czarnecki <pioczarn@gmail.com>
 Piotr Jawniak <sawyer47@gmail.com>
 Piotr Szotkowski <chastell@chastell.net>
 Piotr Zolnierek <pz@anixe.pl>
 Poga Po <poga.bahamut@gmail.com>
+posixphreak <posixphreak@gmail.com>
 Potpourri <pot_pourri@mail.ru>
 Prudhvi Krishna Surapaneni <me@prudhvi.net>
-Przemek Wesołek <jest@go.art.pl>
+Przemysław Wesołek <jest@go.art.pl>
 Pyfisch <pyfisch@gmail.com>
 Pyry Kontio <pyry.kontio@drasa.eu>
 Q.P.Liu <qpliu@yahoo.com>
+qwitwa <qwitwa@gmail.com>
 Rafael Ávila de Espíndola <respindola@mozilla.com>
 Rahul Horé <hore.rahul@gmail.com>
 Ralph Bodenner <rkbodenner+github@gmail.com>
@@ -719,48 +894,60 @@ Raphael Nestler <raphael.nestler@gmail.com>
 Raphael Speyer <rspeyer@gmail.com>
 Raul Gutierrez S <rgs@itevenworks.net>
 Ray Clanan <rclanan@utopianconcept.com>
+ray glover <ray@rayglover.net>
+reedlepee <reedlepee123@gmail.com>
 Reilly Watson <reillywatson@gmail.com>
+Rein Henrichs <reinh@reinh.com>
+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>
 Reuben Morais <reuben.morais@gmail.com>
-Ricardo M. Correia <rcorreia@wizy.org>
+reus <reusee@ymail.com>
 Ricardo Martins <ricardo@scarybox.net>
-Rich Lane <rlane@club.cc.cmu.edu>
+Ricardo M. Correia <rcorreia@wizy.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>
+rjz <rj@rjzaworski.com>
 Rob Arnold <robarnold@cs.cmu.edu>
-Rob Hoelz <rob@hoelz.ro>
 Robert Buonpastore <robert.buonpastore@gmail.com>
 Robert Clipsham <robert@octarineparrot.com>
-Robert Gawdzik <rgawdzik@hotmail.com>
 Robert Foss <dev@robertfoss.se>
+Robert Gawdzik <rgawdzik@hotmail.com>
 Robert Irelan <rirelan@gmail.com>
 Robert Knight <robertknight@gmail.com>
 Robert Millar <robert.millar@cantab.net>
+Rob Hoelz <rob@hoelz.ro>
 Robin Gloster <robin@loc-com.de>
 Robin Kruppe <robin.kruppe@gmail.com>
 Robin Stocker <robin@nibor.org>
+Rob Young <rob.young@digital.cabinet-office.gov.uk>
 Rohit Joshi <rohitjoshi@users.noreply.github.com>
 Roland Tanglao <roland@rolandtanglao.com>
 Rolf Timmermans <rolftimmermans@voormedia.com>
 Rolf van de Krol <info@rolfvandekrol.nl>
 Ron Dahlgren <ronald.dahlgren@gmail.com>
+Rory O’Kane <rory@roryokane.com>
 Roy Crihfield <rscrihf@gmail.com>
 Roy Frostig <rfrostig@mozilla.com>
+Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+rundrop1 <rundrop1@zoho.com>
 Russell Johnston <rpjohnst@gmail.com>
+Russell McClellan <russell.mcclellan@gmail.com>
 Ruud van Asseldonk <dev@veniogames.com>
 Ryan Levick <ryan@6wunderkinder.com>
 Ryan Mulligan <ryan@ryantm.com>
 Ryan Prichard <ryan.prichard@gmail.com>
 Ryan Riginding <marc.riginding@gmail.com>
 Ryan Scheel <ryan.havvy@gmail.com>
-Rüdiger Sonderfeld <ruediger@c-plusplus.de>
-S Pradeep Kumar <gohanpra@gmail.com>
+Ryman <haqkrs@gmail.com>
+らいどっと <ryogo.yoshimura@gmail.com>
 Sae-bom Kim <sae-bom.kim@samsung.com>
 Salem Talha <salem.a.talha@gmail.com>
+saml <saml@users.noreply.github.com>
 Samuel Chase <samebchase@gmail.com>
 Samuel Neves <sneves@dei.uc.pt>
 Sander Mathijs van Veen <smvv@kompiler.org>
@@ -786,26 +973,43 @@ Sebastian Gesemann <s.gesemann@gmail.com>
 Sebastian N. Fernandez <cachobot@gmail.com>
 Sebastian Rasmussen <sebras@gmail.com>
 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>
-Seo Sanghyeon <sanxiyn@gmail.com>
+Sébastien Paolacci <sebastien.paolacci@gmail.com>
 Seonghyun Kim <sh8281.kim@samsung.com>
+Seo Sanghyeon <sanxiyn@gmail.com>
 Sergio Benitez <sbenitez@mit.edu>
 Seth Faxon <seth.faxon@gmail.com>
 Seth Pink <sethpink@gmail.com>
 Seth Pollack <sethpollack@users.noreply.github.com>
+sevrak <sevrak@rediffmail.com>
 Shamir Khodzha <khodzha.sh@gmail.com>
+sheroze1123 <mss385@cornell.edu>
+Shmuale Mark <shm.mark@gmail.com>
 SiegeLord <slabode@aim.com>
+Simonas Kazlauskas <git@kazlauskas.me>
 Simon Barber-Dueck <sbarberdueck@gmail.com>
+Simon Kern <simon.kern@rwth-aachen.de>
 Simon Persson <simon@flaskpost.org>
-Simon Sapin <simon.sapin@exyr.org>
+Simon Sapin <simon@exyr.org>
 Simon Wollwage <mail.wollwage@gmail.com>
-Simonas Kazlauskas <git@kazlauskas.me>
+simplex <theemptystring@gmail.com>
+Sindre Johansen <sindre@sindrejohansen.no>
+sinkuu <sinkuupump@gmail.com>
+Skyler <skyler.lipthay@gmail.com>
+smenardpw <sebastien@knoglr.com>
 Son <leson.phung@gmail.com>
+sp3d <sp3d@github>
+S Pradeep Kumar <gohanpra@gmail.com>
 Squeaky <squeaky_pl@gmx.com>
+startling <tdixon51793@gmail.com>
 Stefan Bucur <stefan.bucur@epfl.ch>
 Stefan Plantikow <stefan.plantikow@googlemail.com>
 Stepan Koltsov <stepan.koltsov@gmail.com>
 Sterling Greene <sterling.greene@gmail.com>
+Steve Gury <steve.gury@gmail.com>
 Steve Klabnik <steve@steveklabnik.com>
 Steven Allen <steven@stebalien.com>
 Steven Crockett <crockett.j.steven@gmail.com>
@@ -813,26 +1017,32 @@ Steven De Coeyer <steven@banteng.be>
 Steven Fackler <sfackler@gmail.com>
 Steven Sheldon <steven@sasheldon.com>
 Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca>
+Steven Walter <stevenrwalter@gmail.com>
 Strahinja Val Markovic <val@markovic.io>
 Stuart Pernsteiner <stuart@pernsteiner.org>
 Subhash Bhushan <subhash.bhushan@kaybus.com>
+sumito3478 <sumito3478@gmail.com>
+Swaroop C H <swaroop@swaroopch.com>
 Sylvestre Ledru <sylvestre@debian.org>
-Sébastien Chauvel <eichi237@mailoo.org>
-Sébastien Crozet <developer@crozet.re>
-Sébastien Marie <semarie@users.noreply.github.com>
-Sébastien Paolacci <sebastien.paolacci@gmail.com>
+Tamir Duberstein <tamird@gmail.com>
 Tamir Duberstein <tamird@squareup.com>
 Taras Shpot <mrshpot@gmail.com>
+tav <tav@espians.com>
 Taylor Hutchison <seanthutchison@gmail.com>
 Ted Horst <ted.horst@earthlink.net>
 Tero Hänninen <lgvz@users.noreply.github.com>
+th0114nd <th0114nd@gmail.com>
 Thad Guidry <thadguidry@gmail.com>
 Theo Belaire <theo.belaire@gmail.com>
+theptrk <patrick.tran06@gmail.com>
 Thiago Carvalho <thiago.carvalho@westwing.de>
+thiagopnts <thiagopnts@gmail.com>
 Thiago Pontes <email@thiago.me>
 Thomas Backman <serenity@exscape.org>
 Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>
 Thomas Daede <daede003@umn.edu>
+Thomas Jespersen <laumann.thomas@gmail.com>
+Thomas Karpiniec <tk@1.21jiggawatts.net>
 Tiago Nobrega <tigarmo@gmail.com>
 Tibor Benke <ihrwein@gmail.com>
 Till Hoeppner <till@hoeppner.ws>
@@ -841,19 +1051,23 @@ Tim Chevalier <chevalier@alum.wellesley.edu>
 Tim Cuthbertson <tim@gfxmonk.net>
 Tim Joseph Dumol <tim@timdumol.com>
 Tim Kuehn <tkuehn@cmu.edu>
-Tim Parenti <timparenti@gmail.com>
-Tim Taubert <tim@timtaubert.de>
 Timon Rapp <timon@zaeda.net>
 Timothée Ravier <tim@siosm.fr>
+Tim Parenti <timparenti@gmail.com>
+Tim Ringenbach <tim.ringenbach@gmail.com>
+Tim Taubert <tim@timtaubert.de>
+tinaun <tinagma@gmail.com>
+Tincan <tincann@users.noreply.github.com>
+Ting-Yu Lin <aethanyc@gmail.com>
 Titouan Vervack <tivervac@gmail.com>
 Tobba <tobias.haegermarck@gmail.com>
 Tobias Bucher <tobiasbucher5991@gmail.com>
 Toby Scrace <toby.scrace@gmail.com>
 Tohava <tohava@tohava-laptop.(none)>
+Tomas Sedovic <tomas@sedovic.cz>
 Tom Chittenden <thchittenden@cmu.edu>
 Tom Jakubowski <tom@crystae.net>
 Tom Lee <github@tomlee.co>
-Tomas Sedovic <tomas@sedovic.cz>
 Tommy M. McGuire <mcguire@crsr.net>
 Tomoki Aonuma <uasi@99cm.org>
 Toni Cárdenas <toni@tcardenas.me>
@@ -864,12 +1078,14 @@ Trent Nadeau <tanadeau@gmail.com>
 Trent Ogren <tedwardo2@gmail.com>
 Trinick <slicksilver555@mac.com>
 Tristan Storch <tstorch@math.uni-bielefeld.de>
+tshakah <tshakah@gmail.com>
 Tshepang Lekhonkhobe <tshepang@gmail.com>
 Tuncer Ayaz <tuncer.ayaz@gmail.com>
-Ty Overby <ty@pre-alpha.com>
 Tycho Sci <tychosci@gmail.com>
 Tyler Bindon <martica@martica.org>
 Tyler Thrailkill <tylerbthrailkill@gmail.com>
+tynopex <tynopex@users.noreply.github.com>
+Ty Overby <ty@pre-alpha.com>
 Ulrik Sverdrup <root@localhost>
 Ulysse Carion <ulysse@ulysse.io>
 User Jyyou <jyyou@plaslab.cs.nctu.edu.tw>
@@ -884,9 +1100,11 @@ Victor van den Elzen <victor.vde@gmail.com>
 Victory <git@dfhu.org>
 Vijay Korapaty <rust@korapaty.com>
 Viktor Dahl <pazaconyoman@gmail.com>
+ville-h <ville3.14159@gmail.com>
 Vincent Belliard <vincent@famillebelliard.fr>
 Vinzent Steinberg <Vinzent.Steinberg@gmail.com>
 Virgile Andreani <virgile.andreani@anbuco.fr>
+visualfc <visualfc@gmail.com>
 Vitali Haravy <HumaneProgrammer@gmail.com>
 Vivek Galatage <vivekgalatage@gmail.com>
 Vladimir Matveev <vladimir.matweev@gmail.com>
@@ -897,121 +1115,45 @@ Volker Mische <volker.mische@gmail.com>
 Wade Mealing <wmealing@gmail.com>
 Wangshan Lu <wisagan@gmail.com>
 WebeWizard <webewizard@gmail.com>
+webmobster <webmobster@users.noreply.github.com>
+Wei-Ming Yang <rick68@users.noreply.github.com>
 Wendell Smith <wendell.smith@yale.edu>
 Wesley Wiser <wwiser@gmail.com>
-Will <will@glozer.net>
+whataloadofwhat <unusualmoniker@gmail.com>
+wickerwaka <martin.donlon@gmail.com>
+Wilfred Hughes <me@wilfred.me.uk>
+Will Andrews <will@firepipe.net>
+Will Engler <engler.will@gmail.com>
 Will Hipschman <whipsch@gmail.com>
 William Ting <io@williamting.com>
 Willson Mock <willson.mock@gmail.com>
+Will <will@glozer.net>
+Wojciech Ogrodowczyk <github@haikuco.de>
+wonyong kim <wonyong.kim@samsung.com>
+xales <xales@naveria.com>
+Xuefeng Wu <benewu@gmail.com>
+XuefengWu <benewu@gmail.com>
+Xuefeng Wu <xfwu@thoughtworks.com>
 Xue Fuqiao <xfq.free@gmail.com>
 Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
 YawarRaza7349 <YawarRaza7349@gmail.com>
 Yazhong Liu <yorkiefixer@gmail.com>
 Yehuda Katz <wycats@gmail.com>
+Yongqian Li <yongqli@kerrmetric.com>
 York Xiang <bombless@126.com>
 Young-il Choi <duddlf.choi@samsung.com>
 Youngmin Yoo <youngmin.yoo@samsung.com>
 Youngsoo Son <ysson83@gmail.com>
+Young Wu <doomsplayer@gmail.com>
 Yuri Albuquerque <yuridenommus@gmail.com>
 Yuri Kunde Schlesner <yuriks@yuriks.net>
+Z1 <MazinZ1@users.noreply.github.com>
 Zach Kamsler <smoo.master@gmail.com>
 Zach Pomerantz <zmp@umich.edu>
 Zack Corr <zack@z0w0.me>
 Zack Slayton <zack.slayton@gmail.com>
 Zbigniew Siciarz <zbigniew@siciarz.net>
 Ziad Hatahet <hatahet@gmail.com>
-Zooko Wilcox-O'Hearn <zooko@zooko.com>
-arturo <arturo@openframeworks.cc>
-auREAX <mark@xn--hwg34fba.ws>
-awlnx <alecweber1994@gmail.com>
-aydin.kim <aydin.kim@samsung.com>
-bachm <Ab@vapor.com>
-bcoopers <coopersmithbrian@gmail.com>
-Anatoly Ikorsky <aikorsky@gmail.com>
-blake2-ppc <ulrik.sverdrup@gmail.com>
-bluss <bluss>
-bors <bors@rust-lang.org>
-chitra
-chromatic <chromatic@wgz.org>
-comex <comexk@gmail.com>
-crhino <piraino.chris@gmail.com>
-Daniel Ramos <dan@daramos.com>
-darkf <lw9k123@gmail.com>
-defuz <defuz.net@gmail.com>
-dgoon <dgoon@dgoon.net>
-donkopotamus <general@chocolate-fish.com>
-eliovir <eliovir@gmail.com>
-elszben <notgonna@tellyou>
-emanueLczirai <emanueLczirai@cryptoLab.net>
-fenduru <fenduru@users.noreply.github.com>
-flo-l <lacknerflo@gmail.com>
-fort <e@mail.com>
-free-Runner <aali07@students.poly.edu>
-g3xzh <g3xzh@yahoo.com>
-gamazeps <gamaz3ps@gmail.com>
-gareth <gareth@gareth-N56VM.(none)>
-gentlefolk <cemacken@gmail.com>
-github-monoculture <eocene@gmx.com>
-hansjorg <hansjorg@gmail.com>
-jamesluke <jamesluke@users.noreply.github.com>
-jatinn <jatinn@users.noreply.github.com>
-jbranchaud <jbranchaud@gmail.com>
-jmgrosen <jmgrosen@gmail.com>
-jmu303 <muj@bc.edu>
-jrincayc <jrincayc@users.noreply.github.com>
-juxiliary <juxiliary@gmail.com>
-jxv <joevargas@hush.com>
-kgv <mail@kgv.name>
-kjpgit <kjpgit@users.noreply.github.com>
-klutzy <klutzytheklutzy@gmail.com>
-korenchkin <korenchkin2@gmail.com>
-kulakowski <george.kulakowski@gmail.com>
-kwantam <kwantam@gmail.com>
-lpy <pylaurent1314@gmail.com>
-lucy <ne.tetewi@gmail.com>
-lummax <luogpg@googlemail.com>
-lyuts <dioxinu@gmail.com>
-madmalik <matthias.tellen@googlemail.com>
-maikklein <maikklein@googlemail.com>
-masklinn <github.com@masklinn.net>
-mchaput <matt@whoosh.ca>
-mdinger <mdinger.bugzilla@gmail.com>
-mitchmindtree <mitchell.nordine@gmail.com>
-moonglum <moonglum@moonbeamlabs.com>
-mr.Shu <mr@shu.io>
-mrec <mike.capp@gmail.com>
-musitdev <philippe.delrieu@free.fr>
-nathan dotz <nathan.dotz@gmail.com>
-Nils Winter <nils.winter@gmail.com>
-noam <noam@clusterfoo.com>
-novalis <novalis@novalis.org>
-nsf <no.smile.face@gmail.com>
-olivren <o.renaud@gmx.fr>
-osa1 <omeragacan@gmail.com>
-pez <james.austin.perry@gmail.com>
-posixphreak <posixphreak@gmail.com>
-qwitwa <qwitwa@gmail.com>
-ray glover <ray@rayglover.net>
-reedlepee <reedlepee123@gmail.com>
-reus <reusee@ymail.com>
-rjz <rj@rjzaworski.com>
-rundrop1 <rundrop1@zoho.com>
-sevrak <sevrak@rediffmail.com>
-sheroze1123 <mss385@cornell.edu>
-smenardpw <sebastien@knoglr.com>
-sp3d <sp3d@github>
-startling <tdixon51793@gmail.com>
-tav <tav@espians.com>
-th0114nd <th0114nd@gmail.com>
-theptrk <patrick.tran06@gmail.com>
-thiagopnts <thiagopnts@gmail.com>
-tinaun <tinagma@gmail.com>
-tshakah <tshakah@gmail.com>
-ville-h <ville3.14159@gmail.com>
-visualfc <visualfc@gmail.com>
-whataloadofwhat <unusualmoniker@gmail.com>
-wickerwaka <martin.donlon@gmail.com>
-wonyong kim <wonyong.kim@samsung.com>
-xales <xales@naveria.com>
 zofrex <zofrex@gmail.com>
+Zooko Wilcox-O'Hearn <zooko@zooko.com>
 克雷 <geekcraik@users.noreply.github.com>
index 71b20cb0946c482b519edbe74ba93b8ae12ff00c..0bcb3219858c9199bf605b1170b1e3a6fdd632cc 100644 (file)
@@ -84,7 +84,8 @@ feature. We use the 'fork and pull' model described there.
 Please make pull requests against the `master` branch.
 
 All pull requests are reviewed by another person. We have a bot,
-@rust-highfive, that will automatically assign a random person to review your request.
+@rust-highfive, that will automatically assign a random person to review your
+request.
 
 If you want to request that a specific person reviews your pull request,
 you can add an `r?` to the message. For example, Steve usually reviews
@@ -124,6 +125,10 @@ 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]. 
+
+[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs
+
 ## Issue Triage
 
 Sometimes, an issue will stay open, even though the bug has been fixed. And
@@ -132,8 +137,40 @@ meantime.
 
 It can be helpful to go through older bug reports and make sure that they are
 still valid. Load up an older issue, double check that it's still true, and
-leave a comment letting us know if it is or is not. The [least recently updated sort][lru] is good for finding issues like this.
+leave a comment letting us know if it is or is not. The [least recently
+updated sort][lru] is good for finding issues like this.
+
+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. 
+
+* 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. 
+
+* Orange, **P**-prefixed labels indicate a bug's **priority**. These labels
+  are only assigned during triage meetings, and replace the [I-nominated][inom]
+  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 purple **metabug** label marks lists of bugs collected by other
+  categories.  
+
+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
 [lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
 
 ## Out-of-tree Contributions
index 8fc66a764da61727e5f611708b73a515f7a19639..d3bb5a541a47067e54e6838f70c687104dfa3e6b 100644 (file)
@@ -266,8 +266,3 @@ ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \
   CFG_INFO := $(info cfg: including ctags rules)
   include $(CFG_SRC_DIR)mk/ctags.mk
 endif
-
-# Find all of the .d files and include them to add information about
-# header file dependencies.
-ALL_DEP_FILES := $(ALL_OBJ_FILES:%.o=%.d)
--include $(ALL_DEP_FILES)
index da59629b049f349282da4eebc5191f33c8e1d39e..c8f00ba1acd8db3eed85f5c9415c71d8cfaded3e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,9 +1,13 @@
 # The Rust Programming Language
 
-This is a compiler for Rust, including standard libraries, tools and
-documentation. Rust is a systems programming language that is fast,
-memory safe and multithreaded, but does not employ a garbage collector
-or otherwise impose significant runtime overhead.
+Rust is a fast systems programming language that guarantees
+memory safety and offers painless concurrency ([no data races]).
+It does not employ a garbage collector and has minimal runtime overhead.
+
+This repo contains the code for `rustc`, the Rust compiler, as well
+as standard libraries, tools and documentation for Rust.
+
+[no data races]: http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html
 
 ## Quick Start
 
index 7053900056b34347f910518186a28eb3b15fb246..7cf5e50f7b84a2dcc1e63fefd25246a1ee916b3c 100644 (file)
@@ -1,3 +1,161 @@
+Version 1.2.0 (August 2015)
+===========================
+
+* ~1200 changes, numerous bugfixes
+
+Highlights
+----------
+
+* [Dynamically-sized-type coercions][dst] allow smart pointer types
+  like `Rc` to contain types without a fixed size, arrays and trait
+  objects, finally enabling use of `Rc<[T]>` and completing the
+  implementation of DST.
+* [Parallel codegen][parcodegen] is now working again, which can
+  substantially speed up large builds in debug mode; It also gets
+  another ~33% speedup when bootstrapping on a 4 core machine (using 8
+  jobs). It's not enabled by default, but will be "in the near
+  future". It can be activated with the `-C codegen-units=N` flag to
+  `rustc`.
+* This is the first release with [experimental support for linking
+  with the MSVC linker and lib C on Windows (instead of using the GNU
+  variants via MinGW)][win]. It is yet recommended only for the most
+  intrepid Rusticians.
+* Benchmark compilations are showing a 30% improvement in
+  bootstrapping over 1.1.
+
+Breaking Changes
+----------------
+
+* The [`to_uppercase`] and [`to_lowercase`] methods on `char` now do
+  unicode case mapping, which is a previously-planned change in
+  behavior and considered a bugfix.
+* [`mem::align_of`] now specifies [the *minimum alignment* for
+  T][align], which is usually the alignment programs are interested
+  in, and the same value reported by clang's
+  `alignof`. [`mem::min_align_of`] is deprecated. This is not known to
+  break real code.
+* [The `#[packed]` attribute is no longer silently accepted by the
+  compiler][packed]. This attribute did nothing and code that
+  mentioned it likely did not work as intended.
+* Associated type defaults are [now behind the
+  `associated_type_defaults` feature gate][ad]. In 1.1 associated type
+  defaults *did not work*, but could be mentioned syntactically. As
+  such this breakage has minimal impact.
+
+Language
+--------
+
+* Patterns with `ref mut` now correctly invoke [`DerefMut`] when
+  matching against dereferencable values.
+
+Libraries
+---------
+
+* The [`Extend`] trait, which grows a collection from an iterator, is
+  implemented over iterators of references, for `String`, `Vec`,
+  `LinkedList`, `VecDeque`, `EnumSet`, `BinaryHeap`, `VecMap`,
+  `BTreeSet` and `BTreeMap`. [RFC][extend-rfc].
+* The [`iter::once`] function returns an iterator that yields a single
+  element, and [`iter::empty`] returns an iterator that yields no
+  elements.
+* The [`matches`] and [`rmatches`] methods on `str` return iterators
+  over substring matches.
+* [`Cell`] and [`RefCell`] both implement `Eq`.
+* A number of methods for wrapping arithmetic are added to the
+  integral types, [`wrapping_div`], [`wrapping_rem`],
+  [`wrapping_neg`], [`wrapping_shl`], [`wrapping_shr`]. These are in
+  addition to the existing [`wrapping_add`], [`wrapping_sub`], and
+  [`wrapping_mul`] methods, and alternatives to the [`Wrapping`]
+  type.. It is illegal for the default arithmetic operations in Rust
+  to overflow; the desire to wrap must be explicit.
+* The `{:#?}` formatting specifier [displays the alternate,
+  pretty-printed][debugfmt] form of the `Debug` formatter. This
+  feature was actually introduced prior to 1.0 with little
+  fanfare.
+* [`fmt::Formatter`] implements [`fmt::Write`], a `fmt`-specific trait
+  for writing data to formatted strings, similar to [`io::Write`].
+* [`fmt::Formatter`] adds 'debug builder' methods, [`debug_struct`],
+  [`debug_tuple`], [`debug_list`], [`debug_set`], [`debug_map`]. These
+  are used by code generators to emit implementations of [`Debug`].
+* `str` has new [`to_uppercase`][strup] and [`to_lowercase`][strlow]
+  methods that convert case, following Unicode case mapping.
+* It is now easier to handle poisoned locks. The [`PoisonError`]
+  type, returned by failing lock operations, exposes `into_inner`,
+  `get_ref`, and `get_mut`, which all give access to the inner lock
+  guard, and allow the poisoned lock to continue to operate. The
+  `is_poisoned` method of [`RwLock`] and [`Mutex`] can poll for a
+  poisoned lock without attempting to take the lock.
+* On Unix the [`FromRawFd`] trait is implemented for [`Stdio`], and
+  [`AsRawFd`] for [`ChildStdin`], [`ChildStdout`], [`ChildStderr`].
+  On Windows the `FromRawHandle` trait is implemented for `Stdio`,
+  and `AsRawHandle` for `ChildStdin`, `ChildStdout`,
+  `ChildStderr`.
+* [`io::ErrorKind`] has a new variant, `InvalidData`, which indicates
+  malformed input.
+
+Misc
+----
+
+* `rustc` employs smarter heuristics for guessing at [typos].
+* `rustc` emits more efficient code for [no-op conversions between
+  unsafe pointers][nop].
+* Fat pointers are now [passed in pairs of immediate arguments][fat],
+  resulting in faster compile times and smaller code.
+
+[`Extend`]: http://doc.rust-lang.org/nightly/std/iter/trait.Extend.html
+[extend-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0839-embrace-extend-extinguish.md
+[`iter::once`]: http://doc.rust-lang.org/nightly/std/iter/fn.once.html
+[`iter::empty`]: http://doc.rust-lang.org/nightly/std/iter/fn.empty.html
+[`matches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.matches
+[`rmatches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatches
+[`Cell`]: http://doc.rust-lang.org/nightly/std/cell/struct.Cell.html
+[`RefCell`]: http://doc.rust-lang.org/nightly/std/cell/struct.RefCell.html
+[`wrapping_add`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_add
+[`wrapping_sub`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_sub
+[`wrapping_mul`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_mul
+[`wrapping_div`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_div
+[`wrapping_rem`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_rem
+[`wrapping_neg`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_neg
+[`wrapping_shl`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shl
+[`wrapping_shr`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shr
+[`Wrapping`]: http://doc.rust-lang.org/nightly/std/num/struct.Wrapping.html
+[`fmt::Formatter`]: http://doc.rust-lang.org/nightly/std/fmt/struct.Formatter.html
+[`fmt::Write`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Write.html
+[`io::Write`]: http://doc.rust-lang.org/nightly/std/io/trait.Write.html
+[`debug_struct`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_struct
+[`debug_tuple`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_tuple
+[`debug_list`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_list
+[`debug_set`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_set
+[`debug_map`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_map
+[`Debug`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Debug.html
+[strup]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_uppercase
+[strlow]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase
+[`to_uppercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_uppercase
+[`to_lowercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_lowercase
+[`PoisonError`]: http://doc.rust-lang.org/nightly/std/sync/struct.PoisonError.html
+[`RwLock`]: http://doc.rust-lang.org/nightly/std/sync/struct.RwLock.html
+[`Mutex`]: http://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html
+[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
+[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
+[`Stdio`]: http://doc.rust-lang.org/nightly/std/process/struct.Stdio.html
+[`ChildStdin`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdin.html
+[`ChildStdout`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdout.html
+[`ChildStderr`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStderr.html
+[`io::ErrorKind`]: http://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html
+[debugfmt]: https://www.reddit.com/r/rust/comments/3ceaui/psa_produces_prettyprinted_debug_output/
+[`DerefMut`]: http://doc.rust-lang.org/nightly/std/ops/trait.DerefMut.html
+[`mem::align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.align_of.html
+[align]: https://github.com/rust-lang/rust/pull/25646
+[`mem::min_align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.min_align_of.html
+[typos]: https://github.com/rust-lang/rust/pull/26087
+[nop]: https://github.com/rust-lang/rust/pull/26336
+[fat]: https://github.com/rust-lang/rust/pull/26411
+[dst]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
+[parcodegen]: https://github.com/rust-lang/rust/pull/26018
+[packed]: https://github.com/rust-lang/rust/pull/25541
+[ad]: https://github.com/rust-lang/rust/pull/27382
+[win]: https://github.com/rust-lang/rust/pull/25350
+
 Version 1.1.0 (June 2015)
 =========================
 
@@ -132,11 +290,11 @@ Language
 
 * Several [restrictions have been added to trait coherence][coh] in
   order to make it easier for upstream authors to change traits
-  without breaking downsteam code.
+  without breaking downstream code.
 * Digits of binary and octal literals are [lexed more eagerly][lex] to
   improve error messages and macro behavior. For example, `0b1234` is
   now lexed as `0b1234` instead of two tokens, `0b1` and `234`.
-* Trait bounds [are always invariant][inv], eleminating the need for
+* Trait bounds [are always invariant][inv], eliminating the need for
   the `PhantomFn` and `MarkerTrait` lang items, which have been
   removed.
 * ["-" is no longer a valid character in crate names][cr], the `extern crate
@@ -275,17 +433,17 @@ Misc
 
 
 Version 1.0.0-alpha.2 (February 2015)
--------------------------------------
+=====================================
 
 * ~1300 changes, numerous bugfixes
 
 * Highlights
 
     * The various I/O modules were [overhauled][io-rfc] to reduce
-      unncessary abstractions and provide better interoperation with
+      unnecessary abstractions and provide better interoperation with
       the underlying platform. The old `io` module remains temporarily
       at `std::old_io`.
-    * The standard library now [partipates in feature gating][feat],
+    * The standard library now [participates in feature gating][feat],
       so use of unstable libraries now requires a `#![feature(...)]`
       attribute. The impact of this change is [described on the
       forum][feat-forum]. [RFC][feat-rfc].
@@ -373,8 +531,9 @@ Version 1.0.0-alpha.2 (February 2015)
 [ufcs-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md
 [un]: https://github.com/rust-lang/rust/pull/22256
 
+
 Version 1.0.0-alpha (January 2015)
-----------------------------------
+==================================
 
   * ~2400 changes, numerous bugfixes
 
@@ -497,7 +656,7 @@ Version 1.0.0-alpha (January 2015)
       syscall when available.
     * The 'serialize' crate has been renamed 'rustc-serialize' and
       moved out of the distribution to Cargo. Although it is widely
-      used now, it is expected to be superceded in the near future.
+      used now, it is expected to be superseded in the near future.
     * The `Show` formatter, typically implemented with
       `#[derive(Show)]` is [now requested with the `{:?}`
       specifier][show] and is intended for use by all types, for uses
@@ -559,8 +718,9 @@ Version 1.0.0-alpha (January 2015)
 [trpl]: http://doc.rust-lang.org/book/index.html
 [rbe]: http://rustbyexample.com/
 
+
 Version 0.12.0 (October 2014)
------------------------------
+=============================
 
   * ~1900 changes, numerous bugfixes
 
@@ -681,8 +841,9 @@ Version 0.12.0 (October 2014)
     * Official Rust binaries on Linux are more compatible with older
       kernels and distributions, built on CentOS 5.10.
 
+
 Version 0.11.0 (July 2014)
--------------------------
+==========================
 
   * ~1700 changes, numerous bugfixes
 
@@ -813,8 +974,9 @@ Version 0.11.0 (July 2014)
     * Error message related to non-exhaustive match expressions have been
       greatly improved.
 
+
 Version 0.10 (April 2014)
--------------------------
+=========================
 
   * ~1500 changes, numerous bugfixes
 
@@ -979,8 +1141,9 @@ Version 0.10 (April 2014)
       * search works across crates that have been rendered to the same output
         directory.
 
+
 Version 0.9 (January 2014)
---------------------------
+==========================
 
    * ~1800 changes, numerous bugfixes
 
@@ -1144,8 +1307,9 @@ Version 0.9 (January 2014)
       * `rustc` adds a `--dep-info` flag for communicating dependencies to
         build tools.
 
+
 Version 0.8 (September 2013)
---------------------------
+============================
 
    * ~2200 changes, numerous bugfixes
 
@@ -1299,8 +1463,9 @@ Version 0.8 (September 2013)
       * A new documentation backend, rustdoc_ng, is available for use. It is
         still invoked through the normal `rustdoc` command.
 
+
 Version 0.7 (July 2013)
------------------------
+=======================
 
    * ~2000 changes, numerous bugfixes
 
@@ -1415,8 +1580,9 @@ Version 0.7 (July 2013)
       * Various improvements to rustdoc.
       * Improvements to rustpkg (see the detailed release notes).
 
+
 Version 0.6 (April 2013)
-------------------------
+========================
 
    * ~2100 changes, numerous bugfixes
 
@@ -1517,8 +1683,9 @@ Version 0.6 (April 2013)
       * Rust code may be embedded in foreign code under limited circumstances
       * Inline assembler supported by new asm!() syntax extension.
 
+
 Version 0.5 (December 2012)
----------------------------
+===========================
 
    * ~900 changes, numerous bugfixes
 
@@ -1573,8 +1740,9 @@ Version 0.5 (December 2012)
       * Added a preliminary REPL, `rusti`
       * License changed from MIT to dual MIT/APL2
 
+
 Version 0.4 (October 2012)
---------------------------
+==========================
 
    * ~2000 changes, numerous bugfixes
 
@@ -1628,8 +1796,9 @@ Version 0.4 (October 2012)
         Rust-based (visitor) code
       * All hash functions and tables converted to secure, randomized SipHash
 
+
 Version 0.3  (July 2012)
-------------------------
+========================
 
    * ~1900 changes, numerous bugfixes
 
@@ -1686,8 +1855,9 @@ Version 0.3  (July 2012)
    * Tool improvements
       * Cargo automatically resolves dependencies
 
+
 Version 0.2  (March 2012)
--------------------------
+=========================
 
    * >1500 changes, numerous bugfixes
 
@@ -1726,8 +1896,9 @@ Version 0.2  (March 2012)
       * Merged per-platform std::{os*, fs*} to core::{libc, os}
       * Extensive cleanup, regularization in libstd, libcore
 
+
 Version 0.1  (January 20, 2012)
--------------------------------
+===============================
 
    * Most language features work, including:
       * Unique pointers, unique closures, move semantics
index 5e02d0725b3180fb3be401c4009ee1c940c54d79..bfd279802243b54894d03ebe4521ca86dbdfb6b4 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 msg() {
-    echo "configure: $1"
+    echo "configure: $*"
 }
 
 step_msg() {
@@ -33,8 +33,8 @@ need_ok() {
 
 need_cmd() {
     if command -v $1 >/dev/null 2>&1
-    then msg "found program $1"
-    else err "need program $1"
+    then msg "found program '$1'"
+    else err "program '$1' is missing, please install it"
     fi
 }
 
@@ -521,6 +521,7 @@ fi
 DEFAULT_BUILD="${CFG_CPUTYPE}-${CFG_OSTYPE}"
 
 CFG_SRC_DIR="$(abs_path $(dirname $0))/"
+CFG_SRC_DIR_RELATIVE="$(dirname $0)/"
 CFG_BUILD_DIR="$(pwd)/"
 CFG_SELF="$0"
 CFG_CONFIGURE_ARGS="$@"
@@ -565,7 +566,7 @@ opt rpath 0 "build rpaths into rustc itself"
 # 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"
-opt llvm-version-check 1 "don't check if the LLVM version is supported, build anyway"
+opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
 
 # Optimization and debugging options. These may be overridden by the release channel, etc.
 opt_nosave optimize 1 "build optimized rust code"
@@ -582,6 +583,7 @@ valopt sysconfdir "/etc" "install system configuration files"
 valopt datadir "${CFG_PREFIX}/share" "install data"
 valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
 valopt llvm-root "" "set LLVM root"
+valopt python "" "set path to python"
 valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
 valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
 valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
@@ -611,7 +613,7 @@ CFG_TARGET=$(to_llvm_triple $CFG_TARGET)
 # there's no rpath. This is where the build system itself puts libraries;
 # --libdir is used to configure the installation directory.
 # FIXME: This needs to parameterized over target triples. Do it in platform.mk
-if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
+if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
 then
     CFG_LIBDIR_RELATIVE=bin
 else
@@ -629,7 +631,8 @@ esac
 
 CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-`
 
-if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] && [ "$CFG_LIBDIR_RELATIVE" != "bin" ]; then
+if ( [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ] ) \
+       && [ "$CFG_LIBDIR_RELATIVE" != "bin" ]; then
     err "libdir on windows should be set to 'bin'"
 fi
 
@@ -694,7 +697,9 @@ putvar CFG_BOOTSTRAP_KEY
 step_msg "looking for build programs"
 
 probe_need CFG_CURLORWGET  curl wget
-probe_need CFG_PYTHON      python2.7 python2.6 python2 python
+if [ -z "$CFG_PYTHON_PROVIDED" ]; then
+    probe_need CFG_PYTHON      python2.7 python2.6 python2 python
+fi
 
 python_version=$($CFG_PYTHON -V 2>&1)
 if [ $(echo $python_version | grep -c '^Python 2\.[4567]') -ne 1 ]; then
@@ -717,10 +722,10 @@ probe CFG_MD5              md5
 probe CFG_MD5SUM           md5sum
 if [ -n "$CFG_MD5" ]
 then
-    CFG_HASH_COMMAND="$CFG_MD5 -q | head -c 8"
+    CFG_HASH_COMMAND="$CFG_MD5 -q | cut -c 1-8"
 elif [ -n "$CFG_MD5SUM" ]
 then
-    CFG_HASH_COMMAND="$CFG_MD5SUM | head -c 8"
+    CFG_HASH_COMMAND="$CFG_MD5SUM | cut -c 1-8"
 else
     err 'could not find one of: md5 md5sum'
 fi
@@ -818,7 +823,7 @@ then
 fi
 
 BIN_SUF=
-if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
+if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
 then
     BIN_SUF=.exe
 fi
@@ -848,13 +853,6 @@ then
     putvar CFG_LOCAL_RUST_ROOT
 fi
 
-# Force freebsd to build with clang; gcc doesn't like us there
-if [ $CFG_OSTYPE = unknown-freebsd ]
-then
-    step_msg "on FreeBSD, forcing use of clang"
-    CFG_ENABLE_CLANG=1
-fi
-
 # Force bitrig to build with clang; gcc doesn't like us there
 if [ $CFG_OSTYPE = unknown-bitrig ]
 then
@@ -863,11 +861,6 @@ then
     CFG_DISABLE_JEMALLOC=1
 fi
 
-if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
-then
-    err "either clang or gcc is required"
-fi
-
 # OS X 10.9, gcc is actually clang. This can cause some confusion in the build
 # system, so if we find that gcc is clang, we should just use clang directly.
 if [ $CFG_OSTYPE = apple-darwin -a -z "$CFG_ENABLE_CLANG" ]
@@ -977,30 +970,47 @@ fi
 
 if [ ! -z "$CFG_ENABLE_CLANG" ]
 then
-    if [ -z "$CC" ] || [[ $CC == *clang ]]
-    then
-        CFG_CLANG_VERSION=$($CFG_CC \
-            --version \
-            | grep version \
-            | sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \
-            | cut -d ' ' -f 2)
-
-        case $CFG_CLANG_VERSION in
-            (3.2* | 3.3* | 3.4* | 3.5* | 3.6*)
-            step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
-            if [ -z "$CC" ]
-            then
-                CFG_CC="clang"
-                CFG_CXX="clang++"
-            fi
-            ;;
-            (*)
-            err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
-            ;;
-        esac
-    else
-        msg "skipping CFG_ENABLE_CLANG version check; provided CC=$CC"
-    fi
+    case "$CC" in
+        (''|*clang)
+        CFG_CLANG_REPORTED_VERSION=$($CFG_CC --version | grep version)
+
+        if [[ $CFG_CLANG_REPORTED_VERSION == *"(based on LLVM "* ]]
+        then
+            CFG_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*(based on LLVM \(.*\))/\1/')
+        elif [[ $CFG_CLANG_REPORTED_VERSION == "Apple LLVM"* ]]
+        then
+            CFG_OSX_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*version \(.*\) .*/\1/')
+        else
+            CFG_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*version \(.*\) .*/\1/')
+        fi
+
+        if [ ! -z "$CFG_OSX_CLANG_VERSION" ]
+        then
+            case $CFG_OSX_CLANG_VERSION in
+                (7.0*)
+                step_msg "found ok version of APPLE CLANG: $CFG_OSX_CLANG_VERSION"
+                ;;
+                (*)
+                err "bad APPLE CLANG version: $CFG_OSX_CLANG_VERSION, need >=7.0"
+                ;;
+            esac
+        else
+            case $CFG_CLANG_VERSION in
+                (3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7*)
+                step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
+                ;;
+                (*)
+                err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
+                ;;
+            esac
+        fi
+
+        if [ -z "$CC" ]
+        then
+            CFG_CC="clang"
+            CFG_CXX="clang++"
+        fi
+    esac
 fi
 
 if [ ! -z "$CFG_ENABLE_CCACHE" ]
@@ -1098,6 +1108,65 @@ do
                 err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
             fi
             ;;
+
+        x86_64-*-msvc)
+            # Currently the build system is not configured to build jemalloc
+            # with MSVC, so we omit this optional dependency.
+            step_msg "targeting MSVC, disabling jemalloc"
+            CFG_DISABLE_JEMALLOC=1
+            putvar CFG_DISABLE_JEMALLOC
+
+            # There are some MSYS python builds which will auto-translate
+            # windows-style paths to MSYS-style paths in Python itself.
+            # Unfortunately this breaks LLVM's build system as somewhere along
+            # the line LLVM prints a path into a file from Python and then CMake
+            # later tries to interpret that path. If Python prints a MSYS path
+            # and CMake tries to use it as a Windows path, you're gonna have a
+            # Bad Time.
+            #
+            # Consequently here we try to detect when that happens and print an
+            # error if it does.
+            if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/'
+            then
+                err "python is silently translating windows paths to MSYS paths \
+                     and the build will fail if this python is used.\n\n \
+                     Either an official python install must be used or an \
+                     alternative python package in MinGW must be used."
+            fi
+
+            # MSVC requires cmake because that's how we're going to build LLVM
+            probe_need CFG_CMAKE cmake
+
+            # Use the REG program to figure out where VS is installed
+            # We need to figure out where cl.exe and link.exe are, so we do some
+            # munging and some probing here. We also look for the default
+            # INCLUDE and LIB variables for MSVC so we can set those in the
+            # build system as well.
+            install=$(reg QUERY \
+                       'HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0' \
+                       -v InstallDir)
+            need_ok "couldn't find visual studio install root"
+            CFG_MSVC_ROOT=$(echo "$install" | grep InstallDir | sed 's/.*REG_SZ[ ]*//')
+            CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
+            CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
+            CFG_MSVC_CL="${CFG_MSVC_ROOT}/VC/bin/amd64/cl.exe"
+            CFG_MSVC_LIB="${CFG_MSVC_ROOT}/VC/bin/amd64/lib.exe"
+            CFG_MSVC_LINK="${CFG_MSVC_ROOT}/VC/bin/amd64/link.exe"
+
+            vcvarsall="${CFG_MSVC_ROOT}/VC/vcvarsall.bat"
+            CFG_MSVC_INCLUDE_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %INCLUDE%")
+            need_ok "failed to learn about MSVC's INCLUDE"
+            CFG_MSVC_LIB_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %LIB%")
+            need_ok "failed to learn about MSVC's LIB"
+
+            putvar CFG_MSVC_ROOT
+            putvar CFG_MSVC_CL
+            putvar CFG_MSVC_LIB
+            putvar CFG_MSVC_LINK
+            putvar CFG_MSVC_INCLUDE_PATH
+            putvar CFG_MSVC_LIB_PATH
+            ;;
+
         *)
             ;;
     esac
@@ -1139,6 +1208,7 @@ do
   do
     make_dir $t/rt/stage$s
     make_dir $t/rt/jemalloc
+    make_dir $t/rt/compiler-rt
     for i in                                          \
       isaac sync test \
       arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips arch/powerpc
@@ -1253,6 +1323,12 @@ CFG_LLVM_SRC_DIR=${CFG_SRC_DIR}src/llvm/
 for t in $CFG_HOST
 do
     do_reconfigure=1
+    is_msvc=0
+    case "$t" in
+        (*-msvc)
+        is_msvc=1
+        ;;
+    esac
 
     if [ -z $CFG_LLVM_ROOT ]
     then
@@ -1272,7 +1348,13 @@ do
             LLVM_ASSERTION_OPTS="--disable-assertions"
         else
             LLVM_ASSERTION_OPTS="--enable-assertions"
-            LLVM_INST_DIR=${LLVM_INST_DIR}+Asserts
+
+            # Apparently even if we request assertions be enabled for MSVC,
+            # LLVM's CMake build system ignore this and outputs in `Release`
+            # anyway.
+            if [ ${is_msvc} -eq 0 ]; then
+                LLVM_INST_DIR=${LLVM_INST_DIR}+Asserts
+            fi
         fi
     else
         msg "not reconfiguring LLVM, external LLVM root"
@@ -1302,7 +1384,32 @@ do
         done
     fi
 
-    if [ ${do_reconfigure} -ne 0 ]
+    if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -ne 0 ]
+    then
+        msg "configuring LLVM for $t with cmake"
+
+        CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF"
+        if [ ! -z "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then
+            CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug"
+        else
+            CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release"
+        fi
+        if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ]
+        then
+            CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF"
+        else
+            CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
+        fi
+
+        msg "configuring LLVM with:"
+        msg "$CMAKE_ARGS"
+        (cd $LLVM_BUILD_DIR && "$CFG_CMAKE" $CFG_LLVM_SRC_DIR \
+                                            -G "Visual Studio 12 2013 Win64" \
+                                            $CMAKE_ARGS)
+        need_ok "LLVM cmake configure failed"
+    fi
+
+    if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -eq 0 ]
     then
         # LLVM's configure doesn't recognize the new Windows triples yet
         gnu_t=$(to_gnu_triple $t)
@@ -1326,7 +1433,7 @@ do
         # (llvm's configure tries to find pthread first, so we have to disable it explicitly.)
         # Also note that pthreads works badly on mingw-w64 systems: #8996
         case "$CFG_BUILD" in
-            (*-windows-*)
+            (*-windows-gnu)
             LLVM_OPTS="$LLVM_OPTS --disable-pthreads"
             ;;
         esac
@@ -1467,6 +1574,7 @@ done
 step_msg "writing configuration"
 
 putvar CFG_SRC_DIR
+putvar CFG_SRC_DIR_RELATIVE
 putvar CFG_BUILD_DIR
 putvar CFG_OSTYPE
 putvar CFG_CPUTYPE
@@ -1510,11 +1618,6 @@ do
     putvar $CFG_LLVM_INST_DIR
 done
 
-# Munge any paths that appear in config.mk back to posix-y
-cp config.tmp config.tmp.bak
-sed -e 's@ \([a-zA-Z]\):[/\\]@ /\1/@g;' <config.tmp.bak >config.tmp
-rm -f config.tmp.bak
-
 msg
 copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile
 move_if_changed config.tmp config.mk
index 48c6f30f5e9eccb7cf84be8e2c351ad7437aa1bd..0cb1c5dc32b8ecfbad0f93d490bd163d006f45ba 100644 (file)
@@ -1,4 +1,4 @@
-.TH RUSTC "1" "June 2015" "rustc 1.1.0" "User Commands"
+.TH RUSTC "1" "August 2015" "rustc 1.2.0" "User Commands"
 .SH NAME
 rustc \- The Rust compiler
 .SH SYNOPSIS
index 571dc7656b20b08107f23ba75e700963fff33e75..b710c2c3a25607725906c5b6f478ff089048e6a0 100644 (file)
@@ -1,4 +1,4 @@
-.TH RUSTDOC "1" "June 2015" "rustdoc 1.1.0" "User Commands"
+.TH RUSTDOC "1" "August 2015" "rustdoc 1.2.0" "User Commands"
 .SH NAME
 rustdoc \- generate documentation from Rust source code
 .SH SYNOPSIS
index 7767129a5e21821e60e477205e0ec446b15b3237..8cd09fa9043c8136d1e2d4878f2a1dd304ae8011 100644 (file)
@@ -5,6 +5,7 @@ ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
 CFG_IOS_SDK_aarch64-apple-ios := $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
 CFG_IOS_SDK_FLAGS_aarch64-apple-ios := -target aarch64-apple-darwin -isysroot $(CFG_IOS_SDK_aarch64-apple-ios) -mios-version-min=7.0 -arch arm64
 CC_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
+LINK_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
 CXX_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
 CPP_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
 AR_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
diff --git a/mk/cfg/x86_64-pc-windows-msvc.mk b/mk/cfg/x86_64-pc-windows-msvc.mk
new file mode 100644 (file)
index 0000000..69a26c0
--- /dev/null
@@ -0,0 +1,87 @@
+# x86_64-pc-windows-msvc configuration
+CC_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
+LINK_x86_64-pc-windows-msvc="$(CFG_MSVC_LINK)" -nologo
+CXX_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
+CPP_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
+AR_x86_64-pc-windows-msvc="$(CFG_MSVC_LIB)" -nologo
+CFG_LIB_NAME_x86_64-pc-windows-msvc=$(1).dll
+CFG_STATIC_LIB_NAME_x86_64-pc-windows-msvc=$(1).lib
+CFG_LIB_GLOB_x86_64-pc-windows-msvc=$(1)-*.{dll,lib}
+CFG_LIB_DSYM_GLOB_x86_64-pc-windows-msvc=$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-msvc :=
+CFG_GCCISH_CFLAGS_x86_64-pc-windows-msvc := -MD
+CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-msvc := -MD
+CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-msvc :=
+CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-msvc :=
+CFG_LLC_FLAGS_x86_64-pc-windows-msvc :=
+CFG_INSTALL_NAME_x86_64-pc-windows-msvc =
+CFG_EXE_SUFFIX_x86_64-pc-windows-msvc := .exe
+CFG_WINDOWSY_x86_64-pc-windows-msvc := 1
+CFG_UNIXY_x86_64-pc-windows-msvc :=
+CFG_LDPATH_x86_64-pc-windows-msvc :=
+CFG_RUN_x86_64-pc-windows-msvc=$(2)
+CFG_RUN_TARG_x86_64-pc-windows-msvc=$(call CFG_RUN_x86_64-pc-windows-msvc,,$(2))
+CFG_GNU_TRIPLE_x86_64-pc-windows-msvc := x86_64-pc-win32
+
+# These two environment variables are scraped by the `./configure` script and
+# are necessary for `cl.exe` to find standard headers (the INCLUDE variable) and
+# for `link.exe` to find standard libraries (the LIB variable).
+ifdef CFG_MSVC_INCLUDE_PATH
+export INCLUDE := $(CFG_MSVC_INCLUDE_PATH)
+endif
+ifdef CFG_MSVC_LIB_PATH
+export LIB := $(CFG_MSVC_LIB_PATH)
+endif
+
+# Unfortunately `link.exe` is also a program in `/usr/bin` on MinGW installs,
+# but it's not the one that we want. As a result we make sure that our detected
+# `link.exe` shows up in PATH first.
+ifdef CFG_MSVC_LINK
+export PATH := $(CFG_MSVC_ROOT)/VC/bin/amd64:$(PATH)
+endif
+
+# There are more comments about this available in the target specification for
+# Windows MSVC in the compiler, but the gist of it is that we use `llvm-ar.exe`
+# instead of `lib.exe` for assembling archives, so we need to inject this custom
+# dependency here.
+NATIVE_TOOL_DEPS_core_T_x86_64-pc-windows-msvc += llvm-ar.exe
+INSTALLED_BINS_x86_64-pc-windows-msvc += llvm-ar.exe
+
+# When working with MSVC on windows, each DLL needs to explicitly declare its
+# interface to the outside world through some means. The options for doing so
+# include:
+#
+# 1. A custom attribute on each function itself
+# 2. A linker argument saying what to export
+# 3. A file which lists all symbols that need to be exported
+#
+# The Rust compiler takes care (1) for us for all Rust code by annotating all
+# public-facing functions with dllexport, but we have a few native dependencies
+# which need to cross the DLL boundary. The most important of these dependencies
+# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
+# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
+# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
+#
+# Unfortunately, at this time, LLVM does not handle this sort of exportation on
+# Windows for us, so we're forced to do it ourselves if we want it (which seems
+# like the path of least resistance right now). To do this we generate a `.DEF`
+# file [1] which we then custom-pass to the linker when building the rustc_llvm
+# crate. This DEF file list all symbols that are exported from
+# `src/librustc_llvm/lib.rs` and is generated by a small python script.
+#
+# Fun times!
+#
+# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
+RUSTFLAGS_rustc_llvm_T_x86_64-pc-windows-msvc += \
+       -C link-args="-DEF:x86_64-pc-windows-msvc/rt/rustc_llvm.def"
+CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
+       x86_64-pc-windows-msvc/rt/rustc_llvm.def
+
+x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
+                       $(S)src/librustc_llvm/lib.rs
+       $(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)
+
+# All windows nightiles are currently a GNU triple, so this MSVC triple is not
+# bootstrapping from itself. This is relevant during stage0, and other parts of
+# the build system take this into account.
+BOOTSTRAP_FROM_x86_64-pc-windows-msvc := x86_64-pc-windows-gnu
index b3dea6f97cbc11a05ea751c9fb809e66c792c6ff..960dabdcf9f182cc123513133d6c6cfd8353d792 100644 (file)
@@ -3,6 +3,7 @@ CC_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc
 CXX_x86_64-unknown-linux-musl=notaprogram
 CPP_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E
 AR_x86_64-unknown-linux-musl=$(AR)
+CFG_INSTALL_ONLY_RLIB_x86_64-unknown-linux-musl = 1
 CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
index 5b90d41ceeceb85c5e1ed457f054032149d39bc1..c04ef89ebc58a658a9629d51670d618459901538 100644 (file)
@@ -118,16 +118,3 @@ $(foreach host, $(CFG_HOST), \
  $(eval $(foreach target, $(CFG_TARGET), \
   $(eval $(foreach stage, 0 1 2 3, \
    $(eval $(call CLEAN_TARGET_STAGE_N,$(stage),$(target),$(host))))))))
-
-define DEF_CLEAN_LLVM_HOST
-ifeq ($(CFG_LLVM_ROOT),)
-clean-llvm$(1):
-       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) clean
-else
-clean-llvm$(1): ;
-
-endif
-endef
-
-$(foreach host, $(CFG_HOST), \
- $(eval $(call DEF_CLEAN_LLVM_HOST,$(host))))
index ebc28e2966ddadd1eb9a5096d29a9227f034e9fc..165079e2e624966ed0d5b7c8ac254798df37f15f 100644 (file)
@@ -125,9 +125,6 @@ ONLY_RLIB_rustc_bitflags := 1
 # Documented-by-default crates
 DOC_CRATES := std alloc collections core libc rustc_unicode
 
-# Installed objects/libraries by default
-INSTALLED_OBJECTS := libmorestack.a libcompiler-rt.a
-
 ################################################################################
 # You should not need to edit below this line
 ################################################################################
@@ -137,7 +134,7 @@ INSTALLED_OBJECTS := libmorestack.a libcompiler-rt.a
 #
 # $(1) is the crate to generate variables for
 define RUST_CRATE
-CRATEFILE_$(1) := $$(S)src/lib$(1)/lib.rs
+CRATEFILE_$(1) := $$(SREL)src/lib$(1)/lib.rs
 RSINPUTS_$(1) := $$(call rwildcard,$(S)src/lib$(1)/,*.rs)
 RUST_DEPS_$(1) := $$(filter-out native:%,$$(DEPS_$(1)))
 NATIVE_DEPS_$(1) := $$(patsubst native:%,%,$$(filter native:%,$$(DEPS_$(1))))
index e6a2174f84a82dab0104b0520535561d298aa692..aa7b62e13b86c77b76d8e3504a1e3c18641f9bbb 100644 (file)
@@ -15,7 +15,8 @@
 
 ## GDB ##
 DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB=gdb_load_rust_pretty_printers.py \
-                                 gdb_rust_pretty_printing.py
+                                 gdb_rust_pretty_printing.py \
+                                 debugger_pretty_printers_common.py
 DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS=\
     $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB), \
         $(CFG_SRC_DIR)src/etc/$(script))
@@ -27,7 +28,8 @@ DEBUGGER_BIN_SCRIPTS_GDB_ABS=\
 
 
 ## LLDB ##
-DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py \
+                                  debugger_pretty_printers_common.py
 DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS=\
     $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB), \
         $(CFG_SRC_DIR)src/etc/$(script))
index 75c6219c5f04f17ed9fa72b4ac2f01fe991acaff..0fc9100b85b92873aae0269ed816d3c9c1d595a8 100644 (file)
@@ -123,7 +123,7 @@ 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 compiler-docs
+dist-install-dir-$(1): prepare-base-dir-$(1) 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
@@ -144,9 +144,11 @@ dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) prepare-overlay-$(1)
        @$(call E, build: $$@)
 # Copy essential gcc components into installer
 ifdef CFG_WINDOWSY_$(1)
+ifeq ($$(findstring gnu,$(1)),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/
+endif
 endif
        $$(Q)$$(S)src/rust-installer/gen-installer.sh \
                --product-name=Rust \
@@ -161,7 +163,7 @@ endif
                --legacy-manifest-dirs=rustlib,cargo
        $$(Q)rm -R tmp/dist/$$(PKG_NAME)-$(1)-image
 
-dist-doc-install-dir-$(1): docs compiler-docs
+dist-doc-install-dir-$(1): docs
        $$(Q)mkdir -p tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust
        $$(Q)cp -r doc tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust/html
 
@@ -213,7 +215,14 @@ endif
 dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
 
 ifdef CFG_WINDOWSY_$(CFG_BUILD)
-MAYBE_MINGW_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(MINGW_PKG_NAME)-$(host).tar.gz)
+define BUILD_MINGW_TARBALL
+ifeq ($$(findstring gnu,$(1)),gnu)
+MAYBE_MINGW_TARBALLS += dist/$(MINGW_PKG_NAME)-$(1).tar.gz
+endif
+endef
+
+$(foreach host,$(CFG_HOST),\
+  $(eval $(call BUILD_MINGW_TARBALL,$(host))))
 endif
 
 ifeq ($(CFG_DISABLE_DOCS),)
@@ -242,7 +251,7 @@ distcheck-tar-bins: dist-tar-bins
 
 # Just copy the docs to a folder under dist with the appropriate name
 # for uploading to S3
-dist-docs: docs compiler-docs
+dist-docs: docs
        $(Q) rm -Rf dist/doc
        $(Q) mkdir -p dist/doc/
        $(Q) cp -r doc dist/doc/$(CFG_PACKAGE_VERS)
index 39eb30a5b8dd56afbc57ab468ba7455958dccb65..617c3ddf8dec1eb94fe49751d886d59102e9a730 100644 (file)
@@ -168,6 +168,7 @@ DOC_TARGETS += doc/not_found.html
 doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
        @$(call E, rustdoc: $@)
        $(Q)$(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) \
+               --markdown-no-toc \
                --markdown-css http://doc.rust-lang.org/rust.css $<
 
 define DEF_DOC
@@ -264,7 +265,7 @@ endef
 $(foreach crate,$(CRATES),$(eval $(call DEF_LIB_DOC,$(crate))))
 
 COMPILER_DOC_TARGETS := $(CRATES:%=doc/%/index.html)
-ifdef CFG_COMPILER_DOCS
+ifdef CFG_ENABLE_COMPILER_DOCS
   DOC_TARGETS += $(COMPILER_DOC_TARGETS)
 else
   DOC_TARGETS += $(DOC_CRATES:%=doc/%/index.html)
index 1861dd313ce71c02e81b5d2893ca3ec02e3f8000..d5b608e88daf85852291ca4ced7c14ec4f45513e 100644 (file)
@@ -19,6 +19,12 @@ LLVM_DEPS_INC=$(call rwildcard,$(CFG_LLVM_SRC_DIR)include,*cpp *hpp)
 LLVM_DEPS=$(LLVM_DEPS_SRC) $(LLVM_DEPS_INC)
 endif
 
+ifdef CFG_DISABLE_OPTIMIZE_LLVM
+LLVM_BUILD_CONFIG_MODE := Debug
+else
+LLVM_BUILD_CONFIG_MODE := Release
+endif
+
 define DEF_LLVM_RULES
 
 # If CFG_LLVM_ROOT is defined then we don't build LLVM ourselves
@@ -26,12 +32,34 @@ ifeq ($(CFG_LLVM_ROOT),)
 
 LLVM_STAMP_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-auto-clean-stamp
 
+ifeq ($$(findstring msvc,$(1)),msvc)
+
+$$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS) $$(LLVM_STAMP_$(1))
+       @$$(call E, cmake: llvm)
+       $$(Q)$$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \
+               --config $$(LLVM_BUILD_CONFIG_MODE)
+       $$(Q)touch $$(LLVM_CONFIG_$(1))
+
+clean-llvm$(1):
+
+else
+
 $$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS) $$(LLVM_STAMP_$(1))
        @$$(call E, make: llvm)
        $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) $$(CFG_LLVM_BUILD_ENV_$(1)) ONLY_TOOLS="$$(LLVM_TOOLS)"
        $$(Q)touch $$(LLVM_CONFIG_$(1))
+
+clean-llvm$(1):
+       $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) clean
+
 endif
 
+else
+clean-llvm$(1):
+endif
+
+$$(LLVM_AR_$(1)): $$(LLVM_CONFIG_$(1))
+
 # This is used to independently force an LLVM clean rebuild
 # when we changed something not otherwise captured by builtin
 # dependencies. In these cases, commit a change that touches
@@ -66,7 +94,7 @@ $(foreach host,$(CFG_HOST), \
 
 # This can't be done in target.mk because it's included before this file.
 define LLVM_LINKAGE_DEPS
-$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(3))
+$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(2))
 endef
 
 $(foreach source,$(CFG_HOST), \
index 4aa8d7fd785fba9c50ad6024012f7868ad130f63..8983a63e1d13d6674df6bc55709606a32aa43285 100644 (file)
 ######################################################################
 
 # The version number
-CFG_RELEASE_NUM=1.1.0
+CFG_RELEASE_NUM=1.2.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=.5
+CFG_PRERELEASE_VERSION=.6
 
 # Append a version-dependent hash to each library, so we can install different
 # versions in the same place
@@ -84,10 +84,6 @@ CFG_INFO := $(info cfg: version $(CFG_VERSION))
 # More configuration
 ######################################################################
 
-# We track all of the object files we might build so that we can find
-# and include all of the .d files in one fell swoop.
-ALL_OBJ_FILES :=
-
 MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*)
 MKFILES_FOR_TARBALL:=$(MKFILE_DEPS)
 ifneq ($(NO_MKFILE_DEPS),)
@@ -131,9 +127,7 @@ CFG_JEMALLOC_FLAGS += $(JEMALLOC_FLAGS)
 
 ifdef CFG_ENABLE_DEBUG_ASSERTIONS
   $(info cfg: enabling debug assertions (CFG_ENABLE_DEBUG_ASSERTIONS))
-  CFG_RUSTC_FLAGS += --cfg debug -C debug-assertions=on
-else
-  CFG_RUSTC_FLAGS += --cfg ndebug
+  CFG_RUSTC_FLAGS += -C debug-assertions=on
 endif
 
 ifdef CFG_ENABLE_DEBUGINFO
@@ -295,6 +289,7 @@ endif
 # Any rules that depend on LLVM should depend on LLVM_CONFIG
 LLVM_CONFIG_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-config$$(X_$(1))
 LLVM_MC_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-mc$$(X_$(1))
+LLVM_AR_$(1):=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-ar$$(X_$(1))
 LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version)
 LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir)
 LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir)
@@ -302,9 +297,13 @@ LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir)
 LLVM_LIBDIR_RUSTFLAGS_$(1)=-L "$$(LLVM_LIBDIR_$(1))"
 LLVM_LIBS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libs $$(LLVM_COMPONENTS))
 LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags)
+ifeq ($$(findstring freebsd,$(1)),freebsd)
 # On FreeBSD, it may search wrong headers (that are for pre-installed LLVM),
 # so we replace -I with -iquote to ensure that it searches bundled LLVM first.
 LLVM_CXXFLAGS_$(1)=$$(subst -I, -iquote , $$(shell "$$(LLVM_CONFIG_$(1))" --cxxflags))
+else
+LLVM_CXXFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --cxxflags)
+endif
 LLVM_HOST_TRIPLE_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --host-target)
 
 LLVM_AS_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-as$$(X_$(1))
@@ -323,6 +322,7 @@ $(foreach host,$(CFG_HOST), \
 # exported
 
 export CFG_SRC_DIR
+export CFG_SRC_DIR_RELATIVE
 export CFG_BUILD_DIR
 ifdef CFG_VER_DATE
 export CFG_VER_DATE
@@ -398,8 +398,6 @@ endif
 # Prerequisites for using the stageN compiler to build target artifacts
 TSREQ$(1)_T_$(2)_H_$(3) = \
        $$(HSREQ$(1)_H_$(3)) \
-       $$(foreach obj,$$(INSTALLED_OBJECTS),\
-               $$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj)) \
        $$(foreach obj,$$(INSTALLED_OBJECTS_$(2)),\
                $$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj))
 
index 9545a1fb52d9e6242d812ceceaf90481d7df3446..8a5e58c46f676ef726b59410fe7d321700301327 100644 (file)
@@ -90,10 +90,6 @@ ifneq ($(findstring linux,$(CFG_OSTYPE)),)
   endif
 endif
 
-# These flags will cause the compiler to produce a .d file
-# next to the .o file that lists header deps.
-CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d)
-
 AR := ar
 
 define SET_FROM_CFG
@@ -116,6 +112,23 @@ CFG_RLIB_GLOB=lib$(1)-*.rlib
 
 include $(wildcard $(CFG_SRC_DIR)mk/cfg/*.mk)
 
+define ADD_INSTALLED_OBJECTS
+  INSTALLED_OBJECTS_$(1) += $$(call CFG_STATIC_LIB_NAME_$(1),morestack) \
+                            $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
+endef
+
+$(foreach target,$(CFG_TARGET), \
+  $(eval $(call ADD_INSTALLED_OBJECTS,$(target))))
+
+define DEFINE_LINKER
+  ifndef LINK_$(1)
+    LINK_$(1) := $$(CC_$(1))
+  endif
+endef
+
+$(foreach target,$(CFG_TARGET), \
+  $(eval $(call DEFINE_LINKER,$(target))))
+
 # The -Qunused-arguments sidesteps spurious warnings from clang
 define FILTER_FLAGS
   ifeq ($$(CFG_USING_CLANG),1)
@@ -129,6 +142,21 @@ endef
 $(foreach target,$(CFG_TARGET), \
   $(eval $(call FILTER_FLAGS,$(target))))
 
+# Configure various macros to pass gcc or cl.exe style arguments
+define CC_MACROS
+  CFG_CC_INCLUDE_$(1)=-I $$(1)
+  ifeq ($$(findstring msvc,$(1)),msvc)
+    CFG_CC_OUTPUT_$(1)=-Fo:$$(1)
+    CFG_CREATE_ARCHIVE_$(1)=$$(AR_$(1)) -OUT:$$(1)
+  else
+    CFG_CC_OUTPUT_$(1)=-o $$(1)
+    CFG_CREATE_ARCHIVE_$(1)=$$(AR_$(1)) crus $$(1)
+  endif
+endef
+
+$(foreach target,$(CFG_TARGET), \
+  $(eval $(call CC_MACROS,$(target))))
+
 
 ifeq ($(CFG_CCACHE_CPP2),1)
   CCACHE_CPP2=1
@@ -145,21 +173,23 @@ FIND_COMPILER = $(word 1,$(1:ccache=))
 define CFG_MAKE_TOOLCHAIN
   # Prepend the tools with their prefix if cross compiling
   ifneq ($(CFG_BUILD),$(1))
+    ifneq ($$(findstring msvc,$(1)),msvc)
        CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1))
        CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1))
        CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1))
        AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
-       RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \
+       LINK_$(1)=$(CROSS_PREFIX_$(1))$(LINK_$(1))
+       RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(LINK_$(1))) \
            -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))
 
        RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
+    endif
   endif
 
   CFG_COMPILE_C_$(1) = $$(CC_$(1)) \
         $$(CFG_GCCISH_CFLAGS) \
         $$(CFG_GCCISH_CFLAGS_$(1)) \
-        $$(CFG_DEPEND_FLAGS) \
-        -c -o $$(1) $$(2)
+        -c $$(call CFG_CC_OUTPUT_$(1),$$(1)) $$(2)
   CFG_LINK_C_$(1) = $$(CC_$(1)) \
         $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
         $$(CFG_GCCISH_LINK_FLAGS_$(1)) \
@@ -170,8 +200,7 @@ define CFG_MAKE_TOOLCHAIN
         $$(CFG_GCCISH_CXXFLAGS) \
         $$(CFG_GCCISH_CFLAGS_$(1)) \
         $$(CFG_GCCISH_CXXFLAGS_$(1)) \
-        $$(CFG_DEPEND_FLAGS) \
-        -c -o $$(1) $$(2)
+        -c $$(call CFG_CC_OUTPUT_$(1),$$(1)) $$(2)
   CFG_LINK_CXX_$(1) = $$(CXX_$(1)) \
         $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
         $$(CFG_GCCISH_LINK_FLAGS_$(1)) \
@@ -189,7 +218,7 @@ define CFG_MAKE_TOOLCHAIN
 
   # We're using llvm-mc as our assembler because it supports
   # .cfi pseudo-ops on mac
-  CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(CFG_DEPEND_FLAGS) $$(2) | \
+  CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
                     $$(LLVM_MC_$$(CFG_BUILD)) \
                     -assemble \
                     -relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
@@ -201,7 +230,7 @@ define CFG_MAKE_TOOLCHAIN
   # For the ARM, AARCH64, MIPS and POWER crosses, use the toolchain assembler
   # FIXME: We should be able to use the LLVM assembler
   CFG_ASSEMBLE_$(1)=$$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
-                   $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1)
+                   $$(2) -c -o $$(1)
 
   endif
 
index 1ae6a61c95a8c250e8cf397738f6a4052a370bfe..fe619cc7caec76f3d8f4dfcda82a0621c21efee3 100644 (file)
@@ -29,27 +29,34 @@ DEFAULT_PREPARE_MAN_CMD = install -m644
 
 # Create a directory
 # $(1) is the directory
+#
+# XXX: These defines are called to generate make steps.
+# Adding blank lines means two steps from different defines will not end up on
+# the same line.
 define PREPARE_DIR
-       @$(Q)$(call E, prepare: $(1))
+
+       @$(call E, prepare: $(1))
        $(Q)$(PREPARE_DIR_CMD) $(1)
+
 endef
 
 # Copy an executable
 # $(1) is the filename/libname-glob
+#
+# See above for an explanation on the surrounding blank lines
 define PREPARE_BIN
+
        @$(call E, prepare: $(PREPARE_DEST_BIN_DIR)/$(1))
        $(Q)$(PREPARE_BIN_CMD) $(PREPARE_SOURCE_BIN_DIR)/$(1) $(PREPARE_DEST_BIN_DIR)/$(1)
+
 endef
 
 # Copy a dylib or rlib
 # $(1) is the filename/libname-glob
 #
-# XXX: Don't remove the $(nop) command below!
-# Yeah, that's right, it's voodoo. Something in the way this macro is being expanded
-# causes it to parse incorrectly. Throwing in that empty command seems to fix the
-# problem. I'm sorry, just don't remove the $(nop), alright?
+# See above for an explanation on the surrounding blank lines
 define PREPARE_LIB
-       $(nop)
+
        @$(call E, prepare: $(PREPARE_WORKING_DEST_LIB_DIR)/$(1))
        $(Q)LIB_NAME="$(notdir $(lastword $(wildcard $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1))))"; \
        MATCHES="$(filter-out %$(notdir $(lastword $(wildcard $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1)))), \
@@ -60,14 +67,19 @@ define PREPARE_LIB
          echo "  at destination $(PREPARE_WORKING_DEST_LIB_DIR):"      && \
          echo $$MATCHES ; \
        fi
-       $(Q)$(PREPARE_LIB_CMD) `ls -drt1 $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1) | tail -1` $(PREPARE_WORKING_DEST_LIB_DIR)/
+       $(Q)$(PREPARE_LIB_CMD) `ls -drt1 $(PREPARE_WORKING_SOURCE_LIB_DIR)/$(1)` $(PREPARE_WORKING_DEST_LIB_DIR)/
+
 endef
 
 # Copy a man page
 # $(1) - source dir
+#
+# See above for an explanation on the surrounding blank lines
 define PREPARE_MAN
+
        @$(call E, prepare: $(PREPARE_DEST_MAN_DIR)/$(1))
        $(Q)$(PREPARE_MAN_CMD) $(PREPARE_SOURCE_MAN_DIR)/$(1) $(PREPARE_DEST_MAN_DIR)/$(1)
+
 endef
 
 PREPARE_TOOLS = $(filter-out compiletest rustbook error-index-generator, $(TOOLS))
@@ -119,6 +131,8 @@ define DEF_PREPARE_TARGET_N
 # Rebind PREPARE_*_LIB_DIR to point to rustlib, then install the libs for the targets
 prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_WORKING_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_LIB_DIR)/rustlib/$(2)/lib
 prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_WORKING_DEST_LIB_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(2)/lib
+prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_LIB_DIR)/rustlib/$(3)/bin
+prepare-target-$(2)-host-$(3)-$(1)-$(4): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_LIB_DIR)/rustlib/$(3)/bin
 prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
         $$(foreach crate,$$(TARGET_CRATES), \
           $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(crate)) \
@@ -133,6 +147,7 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
       $$(if $$(findstring $(2), $$(PREPARE_TARGETS)), \
         $$(if $$(findstring $(3), $$(PREPARE_HOST)), \
           $$(call PREPARE_DIR,$$(PREPARE_WORKING_DEST_LIB_DIR)) \
+          $$(call PREPARE_DIR,$$(PREPARE_DEST_BIN_DIR)) \
           $$(foreach crate,$$(TARGET_CRATES), \
            $$(if $$(or $$(findstring 1, $$(ONLY_RLIB_$$(crate))),$$(findstring 1,$$(CFG_INSTALL_ONLY_RLIB_$(2)))),, \
               $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))) \
@@ -140,8 +155,11 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
           $$(if $$(findstring $(2),$$(CFG_HOST)), \
             $$(foreach crate,$$(HOST_CRATES), \
               $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))),) \
-         $$(foreach object,$$(INSTALLED_OBJECTS) $$(INSTALLED_OBJECTS_$(2)),\
-           $$(call PREPARE_LIB,$$(object))),),),)
+         $$(foreach object,$$(INSTALLED_OBJECTS_$(2)),\
+           $$(call PREPARE_LIB,$$(object))) \
+         $$(foreach bin,$$(INSTALLED_BINS_$(3)),\
+           $$(call PREPARE_BIN,$$(bin))) \
+       ,),),)
 endef
 
 define INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS
index 6c14a885b91467b36d3c0a4f866bb43936dcf0e2..1a3a1774384d84d897675c9f67a4ee797b3927fa 100644 (file)
@@ -32,6 +32,12 @@ endif
 
 Makefile config.mk: config.stamp
 
+ifeq ($(SREL),)
+SREL_ROOT := ./
+else
+SREL_ROOT := $(SREL)
+endif
+
 config.stamp: $(S)configure $(S)Makefile.in $(S)src/snapshots.txt
        @$(call E, cfg: reconfiguring)
-       $(S)configure $(CFG_CONFIGURE_ARGS)
+       $(SREL_ROOT)configure $(CFG_CONFIGURE_ARGS)
index bd6578d3b724b9baeffaab93ac7d40fa81215747..777a2a0fd3b4bfceee113033a8d78a4ea468b336 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -81,8 +81,8 @@ $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
        @mkdir -p $$(@D)
        @$$(call E, compile: $$@)
        $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
-               -I $$(S)src/rt/hoedown/src \
-               -I $$(S)src/rt \
+               $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rt/hoedown/src) \
+               $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rt) \
                  $$(RUNTIME_CFLAGS_$(1))) $$<
 
 $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.S $$(MKFILE_DEPS) \
@@ -109,12 +109,7 @@ OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.S=.o)
 NATIVE_$(2)_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$(2))
 $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
        @$$(call E, link: $$@)
-       $$(Q)$$(AR_$(1)) rcs $$@ $$^
-
-ifeq ($$(findstring windows,$(1)),windows)
-$$(RT_OUTPUT_DIR_$(1))/lib$(2).a: $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1))
-       $$(Q)cp $$^ $$@
-endif
+       $$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
 
 endef
 
@@ -227,22 +222,36 @@ COMPRT_DEPS := $(wildcard \
               $(S)src/compiler-rt/*/*/*/*)
 endif
 
-COMPRT_NAME_$(1) := libcompiler-rt.a
+COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
 COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
 COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
 
+# Note that on MSVC-targeting builds we hardwire CC/AR to gcc/ar even though
+# we're targeting MSVC. This is because although compiler-rt has a CMake build
+# config I can't actually figure out how to use it, so I'm not sure how to use
+# cl.exe to build the objects. Additionally, the compiler-rt library when built
+# with gcc has the same ABI as cl.exe, so they're largely compatible
+COMPRT_CC_$(1) := $$(CC_$(1))
+COMPRT_AR_$(1) := $$(AR_$(1))
+COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1))
+ifeq ($$(findstring msvc,$(1)),msvc)
+COMPRT_CC_$(1) := gcc
+COMPRT_AR_$(1) := ar
+COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m64
+endif
+
 $$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
        @$$(call E, make: compiler-rt)
        $$(Q)$$(MAKE) -C "$(S)src/compiler-rt" \
                ProjSrcRoot="$(S)src/compiler-rt" \
                ProjObjRoot="$$(abspath $$(COMPRT_BUILD_DIR_$(1)))" \
-               CC="$$(CC_$(1))" \
-               AR="$$(AR_$(1))" \
-               RANLIB="$$(AR_$(1)) s" \
-               CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1))" \
+               CC='$$(COMPRT_CC_$(1))' \
+               AR='$$(COMPRT_AR_$(1))' \
+               RANLIB='$$(COMPRT_AR_$(1)) s' \
+               CFLAGS="$$(COMPRT_CFLAGS_$(1))" \
                TargetTriple=$(1) \
                triple-builtins
-       $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$(COMPRT_LIB_$(1))
+       $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$@
 
 ################################################################################
 # libbacktrace
index 363022e8781d08bfd28ef2ca213374409a8e4010..50d993701421e896a18a0be34baf5c923c161e47 100644 (file)
@@ -18,27 +18,41 @@ define DEF_RUSTLLVM_TARGETS
 # to find the llvm includes (probably because we're not actually installing
 # llvm, but using it straight out of the build directory)
 ifdef CFG_WINDOWSY_$(1)
-LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \
-                         -iquote $$(CFG_LLVM_BUILD_DIR_$(1))/include
+LLVM_EXTRA_INCDIRS_$(1)= $$(call CFG_CC_INCLUDE_$(1),$(S)src/llvm/include) \
+                         $$(call CFG_CC_INCLUDE_$(1),\
+                          $$(CFG_LLVM_BUILD_DIR_$(1))/include)
 endif
 
 RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
        ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp)
 
 RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
-                     -iquote $$(LLVM_INCDIR_$(1)) \
-                     -iquote $$(S)src/rustllvm/include
+                     $$(call CFG_CC_INCLUDE_$(1),$$(LLVM_INCDIR_$(1))) \
+                     $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include)
 RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o)
-ALL_OBJ_FILES += $$(RUSTLLVM_OBJS_OBJS_$(1))
+
+# Note that we appease `cl.exe` and its need for some sort of exception
+# handling flag with the `EHsc` argument here as well.
+ifeq ($$(findstring msvc,$(1)),msvc)
+EXTRA_RUSTLLVM_CXXFLAGS_$(1) := //EHsc
+endif
 
 $$(RT_OUTPUT_DIR_$(1))/$$(call CFG_STATIC_LIB_NAME_$(1),rustllvm): \
            $$(RUSTLLVM_OBJS_OBJS_$(1))
        @$$(call E, link: $$@)
-       $$(Q)$$(AR_$(1)) rcs $$@ $$(RUSTLLVM_OBJS_OBJS_$(1))
+       $$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
 
+# On MSVC we need to double-escape arguments that llvm-config printed which
+# start with a '/'. The shell we're running in will auto-translate the argument
+# `/foo` to `C:/msys64/foo` but we really want it to be passed through as `/foo`
+# so the argument passed to our shell must be `//foo`.
 $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1))
        @$$(call E, compile: $$@)
-       $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(LLVM_CXXFLAGS_$(1)) $$(RUSTLLVM_INCS_$(1))) $$<
+       $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \
+               $$(subst  /,//,$$(LLVM_CXXFLAGS_$(1))) \
+               $$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \
+               $$(RUSTLLVM_INCS_$(1)) \
+               $$<
 endef
 
 # Instantiate template for all stages
index 319f44fd35b77c1058c4627b77640cf913ffc09f..3c274dc4fd5f2863a4b257ef117ef89d05ffa8b1 100644 (file)
@@ -37,7 +37,10 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
                $$(foreach dep,$$(NATIVE_DEPS_$(4)), \
                  $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep))) \
                $$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
-                 $$(RT_OUTPUT_DIR_$(2))/$$(dep))
+                 $$(RT_OUTPUT_DIR_$(2))/$$(dep)) \
+               $$(foreach dep,$$(NATIVE_TOOL_DEPS_$(4)_T_$(2)), \
+                 $$(TBIN$(1)_T_$(3)_H_$(3))/$$(dep)) \
+               $$(CUSTOM_DEPS_$(4)_T_$(2))
 endef
 
 $(foreach host,$(CFG_HOST), \
@@ -83,13 +86,14 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
            $$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4)))
        $$(call REMOVE_ALL_OLD_GLOB_MATCHES, \
            $$(dir $$@)$$(call CFG_RLIB_GLOB,$(4)))
-       $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \
+       $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(2)) \
            $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) \
                $$(RUST_LIB_FLAGS_ST$(1)) \
                -L "$$(RT_OUTPUT_DIR_$(2))" \
                $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \
                $$(LLVM_STDCPP_RUSTFLAGS_$(2)) \
                $$(RUSTFLAGS_$(4)) \
+               $$(RUSTFLAGS_$(4)_T_$(2)) \
                --out-dir $$(@D) \
                -C extra-filename=-$$(CFG_FILENAME_EXTRA) \
                $$<
@@ -149,6 +153,11 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/%: $$(RT_OUTPUT_DIR_$(2))/% \
            | $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
        @$$(call E, cp: $$@)
        $$(Q)cp $$< $$@
+
+$$(TBIN$(1)_T_$(2)_H_$(3))/%: $$(CFG_LLVM_INST_DIR_$(2))/bin/% \
+           | $$(TBIN$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
+       @$$(call E, cp: $$@)
+       $$(Q)cp $$< $$@
 endef
 
 $(foreach source,$(CFG_HOST), \
@@ -172,3 +181,42 @@ $(foreach host,$(CFG_HOST), \
   $(foreach stage,$(STAGES), \
    $(foreach tool,$(TOOLS), \
     $(eval $(call TARGET_TOOL,$(stage),$(target),$(host),$(tool)))))))
+
+# We have some triples which are bootstrapped from other triples, and this means
+# that we need to fixup some of the native tools that a triple depends on.
+#
+# For example, MSVC requires the llvm-ar.exe executable to manage archives, but
+# it bootstraps from the GNU Windows triple. This means that the compiler will
+# add this directory to PATH when executing new processes:
+#
+#      $SYSROOT/rustlib/x86_64-pc-windows-gnu/bin
+#
+# Unfortunately, however, the GNU triple is not known about in stage0, so the
+# tools are actually located in:
+#
+#      $SYSROOT/rustlib/x86_64-pc-windows-msvc/bin
+#
+# To remedy this problem, the rules below copy all native tool dependencies into
+# the bootstrap triple's location in stage 0 so the bootstrap compiler can find
+# the right sets of tools. Later stages (1+) will have the right host triple for
+# the compiler, so there's no need to worry there.
+#
+# $(1) - stage
+# $(2) - triple that's being used as host/target
+# $(3) - triple snapshot is built for
+# $(4) - crate
+# $(5) - tool
+define MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR
+ifneq (,$(3))
+$$(TLIB$(1)_T_$(2)_H_$(2))/stamp.$(4): $$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5)
+
+$$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5): $$(TBIN$(1)_T_$(2)_H_$(2))/$(5)
+       mkdir -p $$(@D)
+       cp $$< $$@
+endif
+endef
+
+$(foreach target,$(CFG_TARGET), \
+ $(foreach crate,$(CRATES), \
+  $(foreach tool,$(NATIVE_TOOL_DEPS_$(crate)_T_$(target)), \
+   $(eval $(call MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR,0,$(target),$(BOOTSTRAP_FROM_$(target)),$(crate),$(tool))))))
index f391d8555fc2bff578a2a6c329b79cf71aa84542..185cc9b2f4c581d0ec4ba0b8a334f0250c1e943a 100644 (file)
@@ -172,23 +172,24 @@ check: check-sanitycheck cleantmptestlogs cleantestlibs all check-stage2 tidy
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # As above but don't bother running tidy.
-check-notidy: cleantmptestlogs cleantestlibs all check-stage2
+check-notidy: check-sanitycheck cleantmptestlogs cleantestlibs all check-stage2
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # A slightly smaller set of tests for smoke testing.
-check-lite: cleantestlibs cleantmptestlogs \
+check-lite: check-sanitycheck cleantestlibs cleantmptestlogs \
        $(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
        check-stage2-rpass check-stage2-rpass-valgrind \
        check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Only check the 'reference' tests: rpass/cfail/rfail/rmake.
-check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass check-stage2-rpass-valgrind \
-       check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
+check-ref: check-sanitycheck cleantestlibs cleantmptestlogs check-stage2-rpass \
+       check-stage2-rpass-valgrind check-stage2-rfail check-stage2-cfail check-stage2-pfail \
+       check-stage2-rmake
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Only check the docs.
-check-docs: cleantestlibs cleantmptestlogs check-stage2-docs
+check-docs: check-sanitycheck cleantestlibs cleantmptestlogs check-stage2-docs
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Some less critical tests that are not prone to breakage.
@@ -382,7 +383,7 @@ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \
                $$(CRATEFILE_$(4)) \
                $$(TESTDEP_$(1)_$(2)_$(3)_$(4))
        @$$(call E, rustc: $$@)
-       $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \
+       $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(2)) \
            $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) -o $$@ $$< --test \
                -L "$$(RT_OUTPUT_DIR_$(2))" \
                $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \
@@ -581,10 +582,6 @@ ifeq ($(CFG_LLDB),)
 CTEST_DISABLE_debuginfo-lldb = "no lldb found"
 endif
 
-ifeq ($(CFG_CLANG),)
-CTEST_DISABLE_codegen = "no clang found"
-endif
-
 ifneq ($(CFG_OSTYPE),apple-darwin)
 CTEST_DISABLE_debuginfo-lldb = "lldb tests are only run on darwin"
 endif
@@ -645,7 +642,6 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
         --run-lib-path $$(TLIB$(1)_T_$(2)_H_$(3)) \
         --rustc-path $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
         --rustdoc-path $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
-        --clang-path $(if $(CFG_CLANG),$(CFG_CLANG),clang) \
         --llvm-bin-path $(CFG_LLVM_INST_DIR_$(CFG_BUILD))/bin \
         --aux-base $$(S)src/test/auxiliary/ \
         --stage-id stage$(1)-$(2) \
@@ -894,7 +890,7 @@ ifeq ($(2),$$(CFG_BUILD))
 $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-crate-$(4)): $$(CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4))
        @$$(call E, run doc-crate-$(4) [$(2)])
        $$(Q)touch $$@.start_time
-       $$(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \
+       $$(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(2)) \
            $$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test --cfg dox \
                $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && \
                touch -r $$@.start_time $$@ && rm $$@.start_time
index 3664236eabdd8cb8dcb7e5c44780493c43f5dd30..918484ac463522865db3dbacefacc5a651933f42 100644 (file)
@@ -20,3 +20,4 @@ print-%:
        @echo $*=$($*)
 
 S := $(CFG_SRC_DIR)
+SREL := $(CFG_SRC_DIR_RELATIVE)
index dcac32ccb8a40564eb2217cca1c409f0ccdc7f3f..eb6c29eefbe78c33459e67972fe1f83a3513ecc7 100644 (file)
@@ -80,9 +80,6 @@ pub struct Config {
     // The python executable
     pub python: String,
 
-    // The clang executable
-    pub clang_path: Option<PathBuf>,
-
     // The llvm binaries path
     pub llvm_bin_path: Option<PathBuf>,
 
@@ -127,9 +124,6 @@ pub struct Config {
     // Flags to pass to the compiler when building for the target
     pub target_rustcflags: Option<String>,
 
-    // Run tests using the JIT
-    pub jit: bool,
-
     // Target system to be tested
     pub target: String,
 
index 3ff7f3cc70adae0e3d01f7479c81cd1b9c58dd94..92a94d23f0842afe1412f48626b7f3f4da18e642 100644 (file)
 #![crate_type = "bin"]
 
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(rustc_private)]
-#![feature(std_misc)]
-#![feature(test)]
+#![feature(dynamic_lib)]
+#![feature(libc)]
 #![feature(path_ext)]
+#![feature(rustc_private)]
+#![feature(slice_extras)]
 #![feature(str_char)]
-#![feature(libc)]
+#![feature(test)]
+#![feature(vec_push_all)]
 
 #![deny(warnings)]
 
@@ -33,7 +34,7 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use getopts::{optopt, optflag, reqopt};
 use common::Config;
-use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen};
+use common::{Pretty, DebugInfoGdb, DebugInfoLldb};
 use util::logv;
 
 pub mod procsrv;
@@ -63,7 +64,6 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"),
           reqopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH"),
           reqopt("", "python", "path to python to use for doc tests", "PATH"),
-          optopt("", "clang-path", "path to  executable for codegen tests", "PATH"),
           optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM"),
           optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind"),
           optopt("", "llvm-bin-path", "path to directory holding llvm binaries", "DIR"),
@@ -80,7 +80,6 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"),
           optflag("", "verbose", "run tests verbosely, showing all output"),
           optopt("", "logfile", "file to log test execution to", "FILE"),
-          optflag("", "jit", "run tests under the JIT"),
           optopt("", "target", "the target to build for", "TARGET"),
           optopt("", "host", "the host to build for", "HOST"),
           optopt("", "gdb-version", "the version of GDB used", "VERSION STRING"),
@@ -133,7 +132,6 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         rustc_path: opt_path(matches, "rustc-path"),
         rustdoc_path: opt_path(matches, "rustdoc-path"),
         python: matches.opt_str("python").unwrap(),
-        clang_path: matches.opt_str("clang-path").map(|s| PathBuf::from(&s)),
         valgrind_path: matches.opt_str("valgrind-path"),
         force_valgrind: matches.opt_present("force-valgrind"),
         llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| PathBuf::from(&s)),
@@ -148,7 +146,6 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         runtool: matches.opt_str("runtool"),
         host_rustcflags: matches.opt_str("host-rustcflags"),
         target_rustcflags: matches.opt_str("target-rustcflags"),
-        jit: matches.opt_present("jit"),
         target: opt_str2(matches.opt_str("target")),
         host: opt_str2(matches.opt_str("host")),
         gdb_version: extract_gdb_version(matches.opt_str("gdb-version")),
@@ -188,7 +185,6 @@ pub fn log_config(config: &Config) {
                     opt_str(&config.host_rustcflags)));
     logv(c, format!("target-rustcflags: {}",
                     opt_str(&config.target_rustcflags)));
-    logv(c, format!("jit: {}", config.jit));
     logv(c, format!("target: {}", config.target));
     logv(c, format!("host: {}", config.host));
     logv(c, format!("android-cross-path: {:?}",
@@ -284,13 +280,7 @@ pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
         let file = file.unwrap().path();
         debug!("inspecting file {:?}", file.display());
         if is_test(config, &file) {
-            let t = make_test(config, &file, || {
-                match config.mode {
-                    Codegen => make_metrics_test_closure(config, &file),
-                    _ => make_test_closure(config, &file)
-                }
-            });
-            tests.push(t)
+            tests.push(make_test(config, &file))
         }
     }
     tests
@@ -323,8 +313,7 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool {
     return valid;
 }
 
-pub fn make_test<F>(config: &Config, testfile: &Path, f: F) -> test::TestDescAndFn where
-    F: FnOnce() -> test::TestFn,
+pub fn make_test(config: &Config, testfile: &Path) -> test::TestDescAndFn
 {
     test::TestDescAndFn {
         desc: test::TestDesc {
@@ -332,7 +321,7 @@ pub fn make_test<F>(config: &Config, testfile: &Path, f: F) -> test::TestDescAnd
             ignore: header::is_test_ignored(config, testfile),
             should_panic: test::ShouldPanic::No,
         },
-        testfn: f(),
+        testfn: make_test_closure(config, &testfile),
     }
 }
 
@@ -357,14 +346,6 @@ pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
     }))
 }
 
-pub fn make_metrics_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
-    let config = (*config).clone();
-    let testfile = testfile.to_path_buf();
-    test::DynMetricFn(box move |mm: &mut test::MetricMap| {
-        runtest::run_metrics(config, &testfile, mm)
-    })
-}
-
 fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
     match full_version_line {
         Some(ref full_version_line)
index 33d4f761eea841ee7730abd6f3b98bd02f9a523a..5a076b8437e2694695d9f2528a4c4c716deb1f33 100644 (file)
@@ -24,12 +24,9 @@ use std::fmt;
 use std::fs::{self, File};
 use std::io::BufReader;
 use std::io::prelude::*;
-use std::iter::repeat;
 use std::net::TcpStream;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Output, ExitStatus};
-use std::str;
-use test::MetricMap;
 
 pub fn run(config: Config, testfile: &Path) {
     match &*config.target {
@@ -43,11 +40,6 @@ pub fn run(config: Config, testfile: &Path) {
         _=> { }
     }
 
-    let mut _mm = MetricMap::new();
-    run_metrics(config, testfile, &mut _mm);
-}
-
-pub fn run_metrics(config: Config, testfile: &Path, mm: &mut MetricMap) {
     if config.verbose {
         // We're going to be dumping a lot of info. Start on a new line.
         print!("\n\n");
@@ -64,7 +56,7 @@ pub fn run_metrics(config: Config, testfile: &Path, mm: &mut MetricMap) {
         Pretty => run_pretty_test(&config, &props, &testfile),
         DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testfile),
         DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
-        Codegen => run_codegen_test(&config, &props, &testfile, mm),
+        Codegen => run_codegen_test(&config, &props, &testfile),
         Rustdoc => run_rustdoc_test(&config, &props, &testfile),
     }
 }
@@ -106,17 +98,13 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
 }
 
 fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let proc_res = if !config.jit {
-        let proc_res = compile_test(config, props, testfile);
+    let proc_res = compile_test(config, props, testfile);
 
-        if !proc_res.status.success() {
-            fatal_proc_rec("compilation failed!", &proc_res);
-        }
+    if !proc_res.status.success() {
+        fatal_proc_rec("compilation failed!", &proc_res);
+    }
 
-        exec_compiled_test(config, props, testfile)
-    } else {
-        jit_test(config, props, testfile)
-    };
+    let proc_res = exec_compiled_test(config, props, testfile);
 
     // The value our Makefile configures valgrind to return on failure
     const VALGRIND_ERR: i32 = 100;
@@ -141,24 +129,16 @@ fn check_correct_failure_status(proc_res: &ProcRes) {
 }
 
 fn run_rpass_test(config: &Config, props: &TestProps, testfile: &Path) {
-    if !config.jit {
-        let mut proc_res = compile_test(config, props, testfile);
+    let proc_res = compile_test(config, props, testfile);
 
-        if !proc_res.status.success() {
-            fatal_proc_rec("compilation failed!", &proc_res);
-        }
+    if !proc_res.status.success() {
+        fatal_proc_rec("compilation failed!", &proc_res);
+    }
 
-        proc_res = exec_compiled_test(config, props, testfile);
+    let proc_res = exec_compiled_test(config, props, testfile);
 
-        if !proc_res.status.success() {
-            fatal_proc_rec("test run failed!", &proc_res);
-        }
-    } else {
-        let proc_res = jit_test(config, props, testfile);
-
-        if !proc_res.status.success() {
-            fatal_proc_rec("jit failed!", &proc_res);
-        }
+    if !proc_res.status.success() {
+        fatal_proc_rec("test run failed!", &proc_res);
     }
 }
 
@@ -293,8 +273,8 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
                             format!("--target={}", config.target),
                             "-L".to_string(),
                             aux_dir.to_str().unwrap().to_string());
-        args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
-        args.extend(split_maybe_args(&props.compile_flags).into_iter());
+        args.extend(split_maybe_args(&config.target_rustcflags));
+        args.extend(split_maybe_args(&props.compile_flags));
         return ProcArgs {
             prog: config.rustc_path.to_str().unwrap().to_string(),
             args: args,
@@ -341,8 +321,8 @@ actual:\n\
                             config.build_base.to_str().unwrap().to_string(),
                             "-L".to_string(),
                             aux_dir.to_str().unwrap().to_string());
-        args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
-        args.extend(split_maybe_args(&props.compile_flags).into_iter());
+        args.extend(split_maybe_args(&config.target_rustcflags));
+        args.extend(split_maybe_args(&props.compile_flags));
         // FIXME (#9639): This needs to handle non-utf8 paths
         return ProcArgs {
             prog: config.rustc_path.to_str().unwrap().to_string(),
@@ -388,7 +368,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             script_str.push_str(&format!("set solib-search-path \
                                          ./{}/stage2/lib/rustlib/{}/lib/\n",
                                          config.host, config.target));
-            for line in breakpoint_lines.iter() {
+            for line in &breakpoint_lines {
                 script_str.push_str(&format!("break {:?}:{}\n",
                                              testfile.file_name().unwrap()
                                                      .to_string_lossy(),
@@ -659,7 +639,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
 
     // Write debugger script:
     // We don't want to hang when calling `quit` while the process is still running
-    let mut script_str = String::from_str("settings set auto-confirm true\n");
+    let mut script_str = String::from("settings set auto-confirm true\n");
 
     // Make LLDB emit its version, so we have it documented in the test output
     script_str.push_str("version\n");
@@ -935,12 +915,12 @@ fn check_forbid_output(props: &TestProps,
     }
 }
 
-fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
+fn check_expected_errors(expected_errors: Vec<errors::ExpectedError>,
                          testfile: &Path,
                          proc_res: &ProcRes) {
 
     // true if we found the error in question
-    let mut found_flags: Vec<_> = repeat(false).take(expected_errors.len()).collect();
+    let mut found_flags = vec![false; expected_errors.len()];
 
     if proc_res.status.success() {
         fatal("process did not return an error status");
@@ -961,14 +941,10 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
         }
     }
 
-    // A multi-line error will have followup lines which will always
-    // start with one of these strings.
+    // A multi-line error will have followup lines which start with a space
+    // or open paren.
     fn continuation( line: &str) -> bool {
-        line.starts_with(" expected") ||
-        line.starts_with("    found") ||
-        //                1234
-        // Should have 4 spaces: see issue 18946
-        line.starts_with("(")
+        line.starts_with(" ") || line.starts_with("(")
     }
 
     // Scan and extract our error/warning messages,
@@ -1153,10 +1129,6 @@ fn compile_test(config: &Config, props: &TestProps,
     compile_test_(config, props, testfile, &[])
 }
 
-fn jit_test(config: &Config, props: &TestProps, testfile: &Path) -> ProcRes {
-    compile_test_(config, props, testfile, &["--jit".to_string()])
-}
-
 fn compile_test_(config: &Config, props: &TestProps,
                  testfile: &Path, extra_args: &[String]) -> ProcRes {
     let aux_dir = aux_output_dir_name(config, testfile);
@@ -1183,7 +1155,7 @@ fn document(config: &Config, props: &TestProps,
                         out_dir.to_str().unwrap().to_string(),
                         testfile.to_str().unwrap().to_string()];
     args.extend(extra_args.iter().cloned());
-    args.extend(split_maybe_args(&props.compile_flags).into_iter());
+    args.extend(split_maybe_args(&props.compile_flags));
     let args = ProcArgs {
         prog: config.rustdoc_path.to_str().unwrap().to_string(),
         args: args,
@@ -1248,7 +1220,7 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
                 vec!("--crate-type=dylib".to_string())
             }
         };
-        crate_type.extend(extra_link_args.clone().into_iter());
+        crate_type.extend(extra_link_args.clone());
         let aux_args =
             make_compile_args(config,
                               &aux_props,
@@ -1346,11 +1318,11 @@ fn make_compile_args<F>(config: &Config,
     };
     args.push(path.to_str().unwrap().to_string());
     if props.force_host {
-        args.extend(split_maybe_args(&config.host_rustcflags).into_iter());
+        args.extend(split_maybe_args(&config.host_rustcflags));
     } else {
-        args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
+        args.extend(split_maybe_args(&config.target_rustcflags));
     }
-    args.extend(split_maybe_args(&props.compile_flags).into_iter());
+    args.extend(split_maybe_args(&props.compile_flags));
     return ProcArgs {
         prog: config.rustc_path.to_str().unwrap().to_string(),
         args: args,
@@ -1385,7 +1357,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path)
     args.push(exe_file.to_str().unwrap().to_string());
 
     // Add the arguments in the run_flags directive
-    args.extend(split_maybe_args(&props.run_flags).into_iter());
+    args.extend(split_maybe_args(&props.run_flags));
 
     let prog = args.remove(0);
     return ProcArgs {
@@ -1685,28 +1657,17 @@ fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
     }
 }
 
-// codegen tests (vs. clang)
+// codegen tests (using FileCheck)
 
-fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf {
-    if suffix.is_empty() {
-        p.to_path_buf()
-    } else {
-        let mut stem = p.file_stem().unwrap().to_os_string();
-        stem.push("-");
-        stem.push(suffix);
-        p.with_file_name(&stem)
-    }
-}
-
-fn compile_test_and_save_bitcode(config: &Config, props: &TestProps,
+fn compile_test_and_save_ir(config: &Config, props: &TestProps,
                                  testfile: &Path) -> ProcRes {
     let aux_dir = aux_output_dir_name(config, testfile);
     // FIXME (#9639): This needs to handle non-utf8 paths
     let mut link_args = vec!("-L".to_string(),
                              aux_dir.to_str().unwrap().to_string());
-    let llvm_args = vec!("--emit=llvm-bc,obj".to_string(),
+    let llvm_args = vec!("--emit=llvm-ir".to_string(),
                          "--crate-type=lib".to_string());
-    link_args.extend(llvm_args.into_iter());
+    link_args.extend(llvm_args);
     let args = make_compile_args(config,
                                  props,
                                  link_args,
@@ -1717,121 +1678,34 @@ fn compile_test_and_save_bitcode(config: &Config, props: &TestProps,
     compose_and_run_compiler(config, props, testfile, args, None)
 }
 
-fn compile_cc_with_clang_and_save_bitcode(config: &Config, _props: &TestProps,
-                                          testfile: &Path) -> ProcRes {
-    let bitcodefile = output_base_name(config, testfile).with_extension("bc");
-    let bitcodefile = append_suffix_to_stem(&bitcodefile, "clang");
-    let testcc = testfile.with_extension("cc");
-    let proc_args = ProcArgs {
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        prog: config.clang_path.as_ref().unwrap().to_str().unwrap().to_string(),
-        args: vec!("-c".to_string(),
-                   "-emit-llvm".to_string(),
-                   "-o".to_string(),
-                   bitcodefile.to_str().unwrap().to_string(),
-                   testcc.to_str().unwrap().to_string())
-    };
-    compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
-}
-
-fn extract_function_from_bitcode(config: &Config, _props: &TestProps,
-                                 fname: &str, testfile: &Path,
-                                 suffix: &str) -> ProcRes {
-    let bitcodefile = output_base_name(config, testfile).with_extension("bc");
-    let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
-    let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
-    let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-extract");
-    let proc_args = ProcArgs {
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        prog: prog.to_str().unwrap().to_string(),
-        args: vec!(format!("-func={}", fname),
-                   format!("-o={}", extracted_bc.to_str().unwrap()),
-                   bitcodefile.to_str().unwrap().to_string())
-    };
-    compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
-}
-
-fn disassemble_extract(config: &Config, _props: &TestProps,
-                       testfile: &Path, suffix: &str) -> ProcRes {
-    let bitcodefile = output_base_name(config, testfile).with_extension("bc");
-    let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
-    let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
-    let extracted_ll = extracted_bc.with_extension("ll");
-    let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-dis");
+fn check_ir_with_filecheck(config: &Config, testfile: &Path) -> ProcRes {
+    let irfile = output_base_name(config, testfile).with_extension("ll");
+    let prog = config.llvm_bin_path.as_ref().unwrap().join("FileCheck");
     let proc_args = ProcArgs {
         // FIXME (#9639): This needs to handle non-utf8 paths
         prog: prog.to_str().unwrap().to_string(),
-        args: vec!(format!("-o={}", extracted_ll.to_str().unwrap()),
-                   extracted_bc.to_str().unwrap().to_string())
+        args: vec!(format!("-input-file={}", irfile.to_str().unwrap()),
+                   testfile.to_str().unwrap().to_string())
     };
     compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
 }
 
-
-fn count_extracted_lines(p: &Path) -> usize {
-    let mut x = Vec::new();
-    File::open(&p.with_extension("ll")).unwrap().read_to_end(&mut x).unwrap();
-    let x = str::from_utf8(&x).unwrap();
-    x.lines().count()
-}
-
-
-fn run_codegen_test(config: &Config, props: &TestProps,
-                    testfile: &Path, mm: &mut MetricMap) {
+fn run_codegen_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     if config.llvm_bin_path.is_none() {
         fatal("missing --llvm-bin-path");
     }
 
-    if config.clang_path.is_none() {
-        fatal("missing --clang-path");
-    }
-
-    let mut proc_res = compile_test_and_save_bitcode(config, props, testfile);
-    if !proc_res.status.success() {
-        fatal_proc_rec("compilation failed!", &proc_res);
-    }
-
-    proc_res = extract_function_from_bitcode(config, props, "test", testfile, "");
-    if !proc_res.status.success() {
-        fatal_proc_rec("extracting 'test' function failed",
-                      &proc_res);
-    }
-
-    proc_res = disassemble_extract(config, props, testfile, "");
-    if !proc_res.status.success() {
-        fatal_proc_rec("disassembling extract failed", &proc_res);
-    }
-
-
-    let mut proc_res = compile_cc_with_clang_and_save_bitcode(config, props, testfile);
+    let mut proc_res = compile_test_and_save_ir(config, props, testfile);
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
     }
 
-    proc_res = extract_function_from_bitcode(config, props, "test", testfile, "clang");
+    proc_res = check_ir_with_filecheck(config, testfile);
     if !proc_res.status.success() {
-        fatal_proc_rec("extracting 'test' function failed",
+        fatal_proc_rec("verification with 'FileCheck' failed",
                       &proc_res);
     }
-
-    proc_res = disassemble_extract(config, props, testfile, "clang");
-    if !proc_res.status.success() {
-        fatal_proc_rec("disassembling extract failed", &proc_res);
-    }
-
-    let base = output_base_name(config, testfile);
-    let base_extract = append_suffix_to_stem(&base, "extract");
-
-    let base_clang = append_suffix_to_stem(&base, "clang");
-    let base_clang_extract = append_suffix_to_stem(&base_clang, "extract");
-
-    let base_lines = count_extracted_lines(&base_extract);
-    let clang_lines = count_extracted_lines(&base_clang_extract);
-
-    mm.insert_metric("clang-codegen-ratio",
-                     (base_lines as f64) / (clang_lines as f64),
-                     0.001);
 }
 
 fn charset() -> &'static str {
index fb157c65d957b2cd4ee727ec28dcd2b666a7e91f..e887ed0cc5297042cf6dd712b6ddaf97e5415b1b 100644 (file)
@@ -79,7 +79,7 @@ feature.
 A nice replacement is the [lazy constructor macro][lcm] by [Marvin
 Löbel][kim].
 
-[fqa]: https://mail.mozilla.org/pipermail/rust-dev/2013-April/003815.html
+[fqa]: http://yosefk.com/c++fqa/ctors.html#fqa-10.12
 [elp]: http://ericlippert.com/2013/02/06/static-constructors-part-one/
 [lcm]: https://gist.github.com/Kimundi/8782487
 [kim]: https://github.com/Kimundi
@@ -160,7 +160,7 @@ that all delimiters be balanced.
 ## `->` for function return type
 
 This is to make the language easier to parse for humans, especially in the face
-of higher-order functions. `fn foo<T>(f: fn(int): int, fn(T): U): U` is not
+of higher-order functions. `fn foo<T>(f: fn(i32): i32, fn(T): U): U` is not
 particularly easy to read.
 
 ## Why is `let` used to introduce variables?
index e51e7d414a89161c63bb8b0046c216a477df3c3a..8b9467589c6541da4a0b34aceaba02c9cffb69ab 100644 (file)
@@ -5,8 +5,8 @@
 There aren't many large programs yet. The Rust [compiler][rustc], 60,000+ lines at the time of writing, is written in Rust. As the oldest body of Rust code it has gone through many iterations of the language, and some parts are nicer to look at than others. It may not be the best code to learn from, but [borrowck] and [resolve] were written recently.
 
 [rustc]: https://github.com/rust-lang/rust/tree/master/src/librustc
-[resolve]: https://github.com/rust-lang/rust/blob/master/src/librustc/middle/resolve.rs
-[borrowck]: https://github.com/rust-lang/rust/blob/master/src/librustc/middle/borrowck/
+[resolve]: https://github.com/rust-lang/rust/tree/master/src/librustc_resolve
+[borrowck]: https://github.com/rust-lang/rust/tree/master/src/librustc_borrowck/borrowck
 
 A research browser engine called [Servo][servo], currently 30,000+ lines across more than a dozen crates, will be exercising a lot of Rust's distinctive type-system and concurrency features, and integrating many native libraries.
 
@@ -20,8 +20,8 @@ Some examples that demonstrate different aspects of the language:
 * The standard library's [json] module. Enums and pattern matching
 
 [sprocketnes]: https://github.com/pcwalton/sprocketnes
-[hash]: https://github.com/rust-lang/rust/blob/master/src/libstd/hash/mod.rs
-[HashMap]: https://github.com/rust-lang/rust/blob/master/src/libcollections/hashmap.rs
+[hash]: https://github.com/rust-lang/rust/tree/master/src/libcore/hash
+[HashMap]: https://github.com/rust-lang/rust/tree/master/src/libstd/collections/hash
 [json]: https://github.com/rust-lang/rust/blob/master/src/libserialize/json.rs
 
 You may also be interested in browsing [trending Rust repositories][github-rust] on GitHub.
@@ -30,15 +30,14 @@ You may also be interested in browsing [trending Rust repositories][github-rust]
 
 ## Is anyone using Rust in production?
 
-Currently, Rust is still pre-1.0, and so we don't recommend that you use Rust
-in production unless you know exactly what you're getting into.
-
-That said, there are two production deployments of Rust that we're aware of:
+Yes. For example (incomplete):
 
 * [OpenDNS](http://labs.opendns.com/2013/10/04/zeromq-helping-us-block-malicious-domains/)
 * [Skylight](http://skylight.io)
-
-Let the fact that this is an easily countable number be a warning.
+* [wit.ai](https://github.com/wit-ai/witd)
+* [Codius](https://codius.org/blog/codius-rust/)
+* [MaidSafe](http://maidsafe.net/)
+* [Terminal.com](https://terminal.com)
 
 ## Does it run on Windows?
 
index f32f2fd443f8e71bff708a5d6d349e461ac1375b..b5eb589eb53983ed9a5134021f1e6e6fbc97b761 100644 (file)
@@ -5,5 +5,4 @@ or the <a href="http://opensource.org/licenses/MIT">MIT license</a>, at your opt
 </p><p>
 This file may not be copied, modified, or distributed except according to those terms.
 </p></footer>
-<script type="text/javascript" src="jquery.js"></script>
 <script type="text/javascript" src="playpen.js"></script>
index fb7562e7bdf8b28b8ebcb3537d66016d120efe5c..3aa89cba0314afde570499f2571eb7bbf31ec4ed 100644 (file)
@@ -281,7 +281,8 @@ type_path_tail : '<' type_expr [ ',' type_expr ] + '>'
 ## Macros
 
 ```antlr
-expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ;
+expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ';' 
+                 | "macro_rules" '!' ident '{' macro_rule * '}' ;
 macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ;
 matcher : '(' matcher * ')' | '[' matcher * ']'
         | '{' matcher * '}' | '$' ident ':' ident
index c4725c26e46bd14fd634dafb8ac5aeb8c627d808..fba919b711586ad91e83cad19ace6cf7bfb5c344 100644 (file)
@@ -25,7 +25,7 @@ series of small examples.
 If you need help with something, or just want to talk about Rust with others,
 there are a few places you can do that:
 
-The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the
+The Rust IRC channels on [irc.mozilla.org](irc://irc.mozilla.org/) are the
 fastest way to get help.
 [`#rust`](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) is
 the general discussion channel, and you'll find people willing to help you with
@@ -40,15 +40,15 @@ There's also
 [`#rust-internals`](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals), which is for discussion of the development of Rust itself.
 
 You can also get help on [Stack
-Overflow](http://stackoverflow.com/questions/tagged/rust). Searching for your
+Overflow](https://stackoverflow.com/questions/tagged/rust). Searching for your
 problem might reveal someone who has asked it before!
 
-There is an active [subreddit](http://reddit.com/r/rust) with lots of
+There is an active [subreddit](https://reddit.com/r/rust) with lots of
 discussion and news about Rust.
 
-There is also a [user forum](http://users.rust-lang.org), for all
-user-oriented discussion, and a [developer
-forum](http://internals.rust-lang.org/), where the development of Rust
+There is also a [user forum](https://users.rust-lang.org), for all
+user-oriented discussion, and a [developer 
+forum](https://internals.rust-lang.org/), where the development of Rust
 itself is discussed.
 
 # Specification
@@ -61,7 +61,7 @@ the language in as much detail as possible is in [the reference](reference.html)
 Rust is still a young language, so there isn't a ton of tooling yet, but the
 tools we have are really nice.
 
-[Cargo](http://crates.io) is Rust's package manager, and its website contains
+[Cargo](https://crates.io) is Rust's package manager, and its website contains
 lots of good documentation.
 
 [`rustdoc`](book/documentation.html) is used to generate documentation for Rust code.
@@ -86,3 +86,14 @@ something if you know its name.
 
 If you encounter an error while compiling your code you may be able to look it
 up in the [Rust Compiler Error Index](error-index.html).
+
+# Community Translations
+
+Several projects have been started to translate the documentation into other
+languages:
+
+- [Russian](https://github.com/kgv/rust_book_ru)
+- [Korean](https://github.com/rust-kr/doc.rust-kr.org)
+- [Chinese](https://github.com/KaiserY/rust-book-chinese)
+- [Spanish](https://github.com/goyox86/elpr)
+
index e740bf3c223aef1a34278be7c5811df77d63ff78..0efdf45c640cba9307c1f99cff0539c66b8ebb0c 100644 (file)
@@ -11,7 +11,7 @@ Looks like you've taken a wrong turn.
 
 Some things that might be helpful to you though:
 
-## Search
+# Search
 
 * <form action="https://duckduckgo.com/">
     <input type="text" id="site-search" name="q" size="80"></input>
@@ -19,12 +19,12 @@ Some things that might be helpful to you though:
 </form>
 * Rust doc search: <span id="core-search"></span>
 
-## Reference
+# Reference
 
 * [The Rust official site](http://rust-lang.org)
 * [The Rust reference](http://doc.rust-lang.org/reference.html)
 
-## Docs
+# Docs
 
 * [The standard library](http://doc.rust-lang.org/std/)
 
index 21e9be59ebbdf372c6b194a8bbf521de567f306b..a3e13acccae28acf9c5cb5de71ceea4f55099528 100644 (file)
@@ -638,7 +638,7 @@ apply to the crate as a whole.
 ```
 
 A crate that contains a `main` function can be compiled to an executable. If a
-`main` function is present, its return type must be [`unit`](#primitive-types)
+`main` function is present, its return type must be [`unit`](#tuple-types)
 and it must take no arguments.
 
 # Items and attributes
@@ -928,26 +928,36 @@ A _generic function_ allows one or more _parameterized types_ to appear in its
 signature. Each type parameter must be explicitly declared, in an
 angle-bracket-enclosed, comma-separated list following the function name.
 
-```{.ignore}
-fn iter<T, F>(seq: &[T], f: F) where T: Copy, F: Fn(T) {
-    for elt in seq { f(*elt); }
-}
-fn map<T, U, F>(seq: &[T], f: F) -> Vec<U> where T: Copy, U: Copy, F: Fn(T) -> U {
-    let mut acc = vec![];
-    for elt in seq { acc.push(f(*elt)); }
-    acc
-}
+```rust,ignore
+// foo is generic over A and B
+
+fn foo<A, B>(x: A, y: B) {
 ```
 
 Inside the function signature and body, the name of the type parameter can be
 used as a type name. [Trait](#traits) bounds can be specified for type parameters
 to allow methods with that trait to be called on values of that type. This is
-specified using the `where` syntax, as in the above example.
+specified using the `where` syntax:
+
+```rust,ignore
+fn foo<T>(x: T) where T: Debug {
+```
 
 When a generic function is referenced, its type is instantiated based on the
-context of the reference. For example, calling the `iter` function defined
-above on `[1, 2]` will instantiate type parameter `T` with `i32`, and require
-the closure parameter to have type `Fn(i32)`.
+context of the reference. For example, calling the `foo` function here:
+
+```
+use std::fmt::Debug;
+
+fn foo<T>(x: &[T]) where T: Debug {
+    // details elided
+    # ()
+}
+
+foo(&[1, 2]);
+```
+
+will instantiate type parameter `T` with `i32`.
 
 The type parameters can also be explicitly supplied in a trailing
 [path](#paths) component after the function name. This might be necessary if
@@ -1038,7 +1048,7 @@ be undesired.
 
 * Deadlocks
 * Reading data from private fields (`std::repr`)
-* Leaks due to reference count cycles, even in the global heap
+* Leaks of memory and other resources
 * Exiting without calling destructors
 * Sending signals
 * Accessing/modifying the file system
@@ -1111,7 +1121,7 @@ extern fn new_i32() -> i32 { 0 }
 extern "stdcall" fn new_i32_stdcall() -> i32 { 0 }
 ```
 
-Unlike normal functions, extern fns have an `extern "ABI" fn()`. This is the
+Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the
 same type as the functions declared in an extern block.
 
 ```
@@ -1367,7 +1377,6 @@ Traits can include default implementations of methods, as in:
 ```
 trait Foo {
     fn bar(&self);
-
     fn baz(&self) { println!("We called baz."); }
 }
 ```
@@ -1418,9 +1427,13 @@ impl<T> Container for Vec<T> {
 ```
 
 Generic functions may use traits as _bounds_ on their type parameters. This
-will have two effects: only types that have the trait may instantiate the
-parameter, and within the generic function, the methods of the trait can be
-called on values that have the parameter's type. For example:
+will have two effects:
+
+- Only types that have the trait may instantiate the parameter.
+- Within the generic function, the methods of the trait can be
+  called on values that have the parameter's type.
+
+For example:
 
 ```
 # type Surface = i32;
@@ -1547,7 +1560,7 @@ methods in such an implementation can only be used as direct calls on the
 values of the type that the implementation targets. In such an implementation,
 the trait type and `for` after `impl` are omitted. Such implementations are
 limited to nominal types (enums, structs), and the implementation must appear
-in the same module or a sub-module as the `self` type:
+in the same crate as the `self` type:
 
 ```
 struct Point {x: i32, y: i32}
@@ -1943,9 +1956,6 @@ 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.
-- `static_assert` - on statics whose type is `bool`, terminates compilation
-  with an error if it is not initialized to `true`. To use this, the `static_assert`
-  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
@@ -2003,6 +2013,10 @@ arbitrarily complex configurations through nesting.
 
 The following configurations must be defined by the implementation:
 
+* `debug_assertions`. Enabled by default when compiling without optimizations.
+  This can be used to enable extra debugging code in development but not in
+  production.  For example, it controls the behavior of the standard library's
+  `debug_assert!` macro.
 * `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
   `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
 * `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
@@ -2297,12 +2311,6 @@ The currently implemented features of the reference compiler are:
                  crate. Stability markers are also attributes: `#[stable]`,
                  `#[unstable]`, and `#[deprecated]` are the three levels.
 
-* `static_assert` - The `#[static_assert]` functionality is experimental and
-                    unstable. The attribute can be attached to a `static` of
-                    type `bool` and the compiler will error if the `bool` is
-                    `false` at compile time. This version of this functionality
-                    is unintuitive and suboptimal.
-
 * `start` - Allows use of the `#[start]` attribute, which changes the entry point
             into a Rust program. This capability, especially the signature for the
             annotated function, is subject to change.
@@ -2771,22 +2779,24 @@ meaning of the operators on standard types is given here.
 Like the [arithmetic operators](#arithmetic-operators), bitwise operators are
 syntactic sugar for calls to methods of built-in traits. This means that
 bitwise operators can be overridden for user-defined types. The default
-meaning of the operators on standard types is given here.
+meaning of the operators on standard types is given here. Bitwise `&`, `|` and
+`^` applied to boolean arguments are equivalent to logical `&&`, `||` and `!=`
+evaluated in non-lazy fashion.
 
 * `&`
-  : And.
+  : Bitwise AND.
     Calls the `bitand` method of the `std::ops::BitAnd` trait.
 * `|`
-  : Inclusive or.
+  : Bitwise inclusive OR.
     Calls the `bitor` method of the `std::ops::BitOr` trait.
 * `^`
-  : Exclusive or.
+  : Bitwise exclusive OR.
     Calls the `bitxor` method of the `std::ops::BitXor` trait.
 * `<<`
   : Left shift.
     Calls the `shl` method of the `std::ops::Shl` trait.
 * `>>`
-  : Right shift.
+  : Right shift (arithmetic).
     Calls the `shr` method of the `std::ops::Shr` trait.
 
 #### Lazy boolean operators
@@ -2836,13 +2846,13 @@ on the right-hand side.
 An example of an `as` expression:
 
 ```
-# fn sum(v: &[f64]) -> f64 { 0.0 }
-# fn len(v: &[f64]) -> i32 { 0 }
+# fn sum(values: &[f64]) -> f64 { 0.0 }
+# fn len(values: &[f64]) -> i32 { 0 }
 
-fn avg(v: &[f64]) -> f64 {
-  let sum: f64 = sum(v);
-  let sz: f64 = len(v) as f64;
-  return sum / sz;
+fn average(values: &[f64]) -> f64 {
+  let sum: f64 = sum(values);
+  let size: f64 = len(values) as f64;
+  sum / size
 }
 ```
 
@@ -2876,7 +2886,7 @@ The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be
 composed with the `=` operator. The expression `lval OP= val` is equivalent to
 `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`.
 
-Any such expression always has the [`unit`](#primitive-types) type.
+Any such expression always has the [`unit`](#tuple-types) type.
 
 #### Operator precedence
 
@@ -3251,8 +3261,8 @@ User-defined types have limited capabilities.
 The primitive types are the following:
 
 * The boolean type `bool` with values `true` and `false`.
-* The machine types.
-* The machine-dependent integer and floating-point types.
+* The machine types (integer and floating-point).
+* The machine-dependent integer types.
 
 #### Machine types
 
@@ -3318,6 +3328,9 @@ assert!(b != "world");
 assert!(p.0 == 10);
 ```
 
+For historical reasons and convenience, the tuple type with no elements (`()`)
+is often called ‘unit’ or ‘the unit type’.
+
 ### Array, and Slice types
 
 Rust has two different types for a list of items:
@@ -3604,6 +3617,147 @@ The notation `&self` is a shorthand for `self: &Self`. In this case,
 in the impl, `Self` refers to the value of type `String` that is the
 receiver for a call to the method `make_string`.
 
+## Subtyping
+
+Subtyping is implicit and can occur at any stage in type checking or
+inference. Subtyping in Rust is very restricted and occurs only due to
+variance with respect to lifetimes and between types with higher ranked
+lifetimes. If we were to erase lifetimes from types, then the only subtyping
+would be due to type equality.
+
+Consider the following example: string literals always have `'static`
+lifetime. Nevertheless, we can assign `s` to `t`:
+
+```
+fn bar<'a>() {
+    let s: &'static str = "hi";
+    let t: &'a str = s;
+}
+```
+Since `'static` "lives longer" than `'a`, `&'static str` is a subtype of
+`&'a str`.
+
+## Type coercions
+
+Coercions are defined in [RFC401]. A coercion is implicit and has no syntax.
+
+[RFC401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+
+### Coercion sites
+
+A coercion can only occur at certain coercion sites in a program; these are
+typically places where the desired type is explicit or can be dervied by
+propagation from explicit types (without type inference). Possible coercion
+sites are:
+
+* `let` statements where an explicit type is given.
+
+    In `let _: U = e;`, `e` is coerced to have type `U`.
+
+* `static` and `const` statements (similar to `let` statements).
+
+* arguments for function calls.
+
+    The value being coerced is the
+    actual parameter and it is coerced to the type of the formal parameter. For
+    example, let `foo` be defined as `fn foo(x: U) { ... }` and call it as
+    `foo(e);`. Then `e` is coerced to have type `U`;
+
+* instantiations of struct or variant fields.
+
+    Assume we have a `struct
+    Foo { x: U }` and instantiate it as `Foo { x: e }`. Then `e` is coerced to
+    have type `U`.
+
+* function results (either the final line of a block if it is not semicolon
+terminated or any expression in a `return` statement).
+
+    In `fn foo() -> U { e }`, `e` is coerced to to have type `U`.
+
+If the expression in one of these coercion sites is a coercion-propagating
+expression, then the relevant sub-expressions in that expression are also
+coercion sites. Propagation recurses from these new coercion sites.
+Propagating expressions and their relevant sub-expressions are:
+
+* array literals, where the array has type `[U; n]`. Each sub-expression in
+the array literal is a coercion site for coercion to type `U`.
+
+* array literals with repeating syntax, where the array has type `[U; n]`. The
+repeated sub-expression is a coercion site for coercion to type `U`.
+
+* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
+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
+the sub-expression is a coercion site to `U`.
+
+* blocks. If a block has type `U`, then the last expression in the block (if
+it is not semicolon-terminated) is a coercion site to `U`. This includes
+blocks which are part of control flow statements, such as `if`/`else`, if
+the block has a known type.
+
+### Coercion types
+
+Coercion is allowed between the following types:
+
+* `T` to `U` if `T` is a subtype of `U` (*reflexive case*).
+
+* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
+(*transitive case*).
+
+    Note that this is not fully supported yet
+
+* `&mut T` to `&T`.
+
+* `*mut T` to `*const T`.
+
+* `&T` to `*const T`.
+
+* `&mut T` to `*mut T`.
+
+* `&T` to `&U` if `T` implements `Deref<Target = U>`. For example:
+
+```rust
+use std::ops::Deref;
+
+struct CharContainer {
+    value: char
+}
+
+impl Deref for CharContainer {
+    type Target = char;
+
+    fn deref<'a>(&'a self) -> &'a char {
+        &self.value
+    }
+}
+
+fn foo(arg: &char) {}
+
+fn main() {
+    let x = &mut CharContainer { value: 'y' };
+    foo(x); //&mut CharContainer is coerced to &char.
+}
+```
+* `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`.
+
+* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of
+    - `&T`
+    - `&mut T`
+    - `*const T`
+    - `*mut T`
+    - `Box<T>`
+
+    and where
+    - coerce_inner(`[T, ..n]`) = `[T]`
+    - coerce_inner(`T`) = `U` where `T` is a concrete type which implements the
+    trait `U`.
+
+    In the future, coerce_inner will be recursively extended to tuples and
+    structs. In addition, coercions from sub-traits to super-traits will be
+    added. See [RFC401] for more details.
+
 # Special traits
 
 Several traits define special evaluation behavior.
@@ -3622,6 +3776,14 @@ The `Sized` trait indicates that the size of this type is known at compile-time.
 The `Drop` trait provides a destructor, to be run whenever a value of this type
 is to be destroyed.
 
+## The `Deref` trait
+
+The `Deref<Target = U>` trait allows a type to implicitly implement all the methods
+of the type `U`. When attempting to resolve a method call, the compiler will search
+the top-level type for the implementation of the called method. If no such method is
+found, `.deref()` is called and the compiler continues to search for the method
+implementation in the returned type `U`.
+
 # Memory model
 
 A Rust program's memory consists of a static set of *items* and a *heap*.
index d2fcf27e93cdf540627bf9e2c2e1255183493882..f2e23963e106c8fbd5c8a28a8bdd0619c441f02e 100644 (file)
@@ -14,8 +14,8 @@ use std::io::{File, Open, Write, IoError};
 
 struct Info {
     name: String,
-    age: int,
-    rating: int
+    age: i32,
+    rating: i32
 }
 
 fn write_info(info: &Info) -> Result<(), IoError> {
@@ -36,8 +36,8 @@ use std::io::{File, Open, Write, IoError};
 
 struct Info {
     name: String,
-    age: int,
-    rating: int
+    age: i32,
+    rating: i32
 }
 
 fn write_info(info: &Info) -> Result<(), IoError> {
@@ -63,4 +63,4 @@ for more details.
 ### The `Result`-`impl` pattern [FIXME]
 
 > **[FIXME]** Document the way that the `io` module uses trait impls
-> on `IoResult` to painlessly propagate errors.
+> on `std::io::Result` to painlessly propagate errors.
index 2dcfc382d0baf43c7a3657a31719114436dfb7e4..611cd564ccac7224ceda954abe8dcaca542083b6 100644 (file)
@@ -20,6 +20,7 @@ for any operation that is clearly associated with a particular
 type.
 
 Methods have numerous advantages over functions:
+
 * They do not need to be imported or qualified to be used: all you
   need is a value of the appropriate type.
 * Their invocation performs autoborrowing (including mutable borrows).
index b0912ea0203dc0f50f802d15d2d75f16053f0f5b..072021194c13e5676a281cf404dbbfa46442c1ae 100644 (file)
@@ -57,15 +57,15 @@ it becomes.
 Prefer
 
 ```rust
-fn foo<T: Iterator<int>>(c: T) { ... }
+fn foo<T: Iterator<i32>>(c: T) { ... }
 ```
 
 over any of
 
 ```rust
-fn foo(c: &[int]) { ... }
-fn foo(c: &Vec<int>) { ... }
-fn foo(c: &SomeOtherCollection<int>) { ... }
+fn foo(c: &[i32]) { ... }
+fn foo(c: &Vec<i32>) { ... }
+fn foo(c: &SomeOtherCollection<i32>) { ... }
 ```
 
 if the function only needs to iterate over the data.
@@ -121,7 +121,7 @@ The primary exception: sometimes a function is meant to modify data
 that the caller already owns, for example to re-use a buffer:
 
 ```rust
-fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>
+fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>
 ```
 
 (From the [Reader trait](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html#tymethod.read).)
@@ -159,7 +159,7 @@ fn foo(a: u8) { ... }
 Note that
 [`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
 is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
-[newtype patterns]() for more details on creating typesafe wrappers.
+[newtype patterns](../types/newtype.md) for more details on creating typesafe wrappers.
 
 Static enforcement usually comes at little run-time cost: it pushes the
 costs to the boundaries (e.g. when a `u8` is first converted into an
index a83e2b76bcb7f457c71c8ef2247ae0713675490a..3e43d1e416d7696759d37a7dae545655fb951810 100644 (file)
@@ -19,7 +19,7 @@ Prefer
 ```rust
 struct SearchResult {
     found: bool,          // item in container?
-    expected_index: uint  // what would the item's index be?
+    expected_index: usize // what would the item's index be?
 }
 
 fn binary_search(&self, k: Key) -> SearchResult
@@ -27,7 +27,7 @@ fn binary_search(&self, k: Key) -> SearchResult
 or
 
 ```rust
-fn binary_search(&self, k: Key) -> (bool, uint)
+fn binary_search(&self, k: Key) -> (bool, usize)
 ```
 
 over
index 87117a20d7a4957392497b1dbec79978748a5e55..01dff3dcceaf18f23e31252fef41d837fba35ba4 100644 (file)
@@ -5,7 +5,7 @@
 Prefer
 
 ```rust
-fn use_mutex(m: sync::mutex::Mutex<int>) {
+fn use_mutex(m: sync::mutex::Mutex<i32>) {
     let guard = m.lock();
     do_work(guard);
     drop(guard); // unlock the lock
@@ -16,7 +16,7 @@ fn use_mutex(m: sync::mutex::Mutex<int>) {
 over
 
 ```rust
-fn use_mutex(m: sync::mutex::Mutex<int>) {
+fn use_mutex(m: sync::mutex::Mutex<i32>) {
     do_work(m.lock());
     // do other work
 }
@@ -34,7 +34,7 @@ Prefer
 
 ```rust
 let foo = match bar {
-    Baz  => 0,
+    Baz => 0,
     Quux => 1
 };
 ```
@@ -44,7 +44,7 @@ over
 ```rust
 let foo;
 match bar {
-    Baz  => {
+    Baz => {
         foo = 0;
     }
     Quux => {
@@ -61,8 +61,8 @@ conditional expression.
 Prefer
 
 ```rust
-s.iter().map(|x| x * 2)
-        .collect::<Vec<_>>()
+let v = s.iter().map(|x| x * 2)
+                .collect::<Vec<_>>();
 ```
 
 over
index ab4f9cb1579611fdfc951e06856e8c637c557a6f..371420431e708145e9fb4d432faf3fbed3df999e 100644 (file)
@@ -8,7 +8,7 @@ yielding items of type `A` to produce a collection of `A`:
 fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
 ```
 
-Here, the `Iterator` trait is specifies an interface that a type `T` must
+Here, the `Iterator` trait specifies an interface that a type `T` must
 explicitly implement to be used by this generic function.
 
 **Pros**:
index 6735023ae680098dd9223ddb6583221961c83c28..61f8db87cde8983fc068c154614f24fef95324e4 100644 (file)
@@ -15,7 +15,7 @@ trait Printable {
     fn print(&self) { println!("{:?}", *self) }
 }
 
-impl Printable for int {}
+impl Printable for i32 {}
 
 impl Printable for String {
     fn print(&self) { println!("{}", *self) }
index 60c17fc2a52e2985277387b609bbfb74409a919e..e69aa3b83bfa4ecf08367516beec54986db65551 100644 (file)
@@ -43,12 +43,12 @@ promises to the client.
 
 For example, consider a function `my_transform` that returns a compound iterator
 type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
-client, so that the client's view of the return type is roughly `Iterator<(uint,
+client, so that the client's view of the return type is roughly `Iterator<(usize,
 T)>`. We can do so using the newtype pattern:
 
 ```rust
 struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
-impl<T> Iterator<(uint, T)> for MyTransformResult<T> { ... }
+impl<T> Iterator<(usize, T)> for MyTransformResult<T> { ... }
 
 fn my_transform<T, Iter: Iterator<T>>(iter: Iter) -> MyTransformResult<T> {
     ...
index 8f721a9767672fa5439a9668dfb619ab36f470ac..348be516e374d7aea536f22625aab9a8aecb86e9 100644 (file)
@@ -16,7 +16,7 @@ If `T` is such a data structure, consider introducing a `T` _builder_:
    value. When possible, choose a better name: e.g. `Command` is the builder for
    `Process`.
 2. The builder constructor should take as parameters only the data _required_ to
-   to make a `T`.
+   make a `T`.
 3. The builder should offer a suite of convenient methods for configuration,
    including setting up compound inputs (like slices) incrementally.
    These methods should return `self` to allow chaining.
@@ -75,7 +75,7 @@ impl Command {
     }
 
     /// Executes the command as a child process, which is returned.
-    pub fn spawn(&self) -> IoResult<Process> {
+    pub fn spawn(&self) -> std::io::Result<Process> {
         ...
     }
 }
index f73517c2b9c3b6ce1d9853103d12eda07311d0fd..b5d0b484ccda5ad4819fb8d174f29a3a19e16aa5 100644 (file)
@@ -3,7 +3,7 @@
 Terminate `return` statements with semicolons:
 
 ``` rust
-fn foo(bar: int) -> Option<int> {
+fn foo(bar: i32) -> Option<i32> {
     if some_condition() {
         return None;
     }
index 207a3fd7f8d165d81d58740d97f5368ea4f0a7f4..cf3fd4163a26e6b16ed8ab584ae93f466128ae27 100644 (file)
@@ -44,7 +44,7 @@ For example:
 use option::Option;
 use mem;
 
-let i: int = mem::transmute(Option(0));
+let i: isize = mem::transmute(Option(0));
 ```
 
 > **[FIXME]** Add rationale.
index b21b280dff0d7feb6651af866de507234b6d5a97..c28a723209563c1c7aeb663e8ebe74c4d17db1d7 100644 (file)
@@ -10,7 +10,7 @@
 
 ``` rust
 #[deprecated = "Use `bar` instead."]
-fn foo(a: uint, b: uint) -> uint {
+fn foo(a: usize, b: usize) -> usize {
     a + b
 }
 ```
index 9ca5de2b50a4d6898e4bde1ab7e69e3e2af55853..12384b00b43bce47c03c221756b3c524e42a585d 100644 (file)
@@ -15,7 +15,7 @@ language would.
 
 [rust]: http://rust-lang.org
 
-“The Rust Programming Language” is split into seven sections. This introduction
+“The Rust Programming Language” is split into eight sections. This introduction
 is the first. After this:
 
 * [Getting started][gs] - Set up your computer for Rust development.
@@ -150,8 +150,8 @@ 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
 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 three elements.
-Adding a fourth would mean allocating a new chunk of memory for all those elements,
+when we create the vector, we may have only allocated space for two elements.
+Adding a third would mean allocating a new chunk of memory for all those elements,
 copying the old values over, and updating the internal pointer to that memory.
 That all works just fine. The problem is that `y` wouldn’t get updated, and so
 we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in
index 584f24b54ada504aa7b873fe70c86b03005dae30..ca3381ffba465d61a0da1f6742f4b2ce2ee7fdf4 100644 (file)
@@ -7,7 +7,7 @@
 * [Learn Rust](learn-rust.md)
     * [Guessing Game](guessing-game.md)
     * [Dining Philosophers](dining-philosophers.md)
-    * [Rust inside other languages](rust-inside-other-languages.md)
+    * [Rust Inside Other Languages](rust-inside-other-languages.md)
 * [Effective Rust](effective-rust.md)
     * [The Stack and the Heap](the-stack-and-the-heap.md)
     * [Testing](testing.md)
index 55e2787cc2591032f349e564f06f9bd84e88779f..fe4f27b9d954cb6e3b341c148f3e8b259cf445e2 100644 (file)
@@ -43,7 +43,7 @@ trait Graph {
 Now, our clients can be abstract over a given `Graph`:
 
 ```rust,ignore
-fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
+fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 { ... }
 ```
 
 No need to deal with the `E`dge type here!
index 887965375932b3fe4953179a96d4dd54ec23c32e..797ec94774d7d7c893f36313718959c6bcad4f48 100644 (file)
@@ -3,7 +3,7 @@
 Rust supports benchmark tests, which can test the performance of your
 code. Let's make our `src/lib.rs` look like this (comments elided):
 
-```{rust,ignore}
+```rust,ignore
 #![feature(test)]
 
 extern crate test;
@@ -77,7 +77,7 @@ the benchmark is no longer benchmarking what one expects. For example, the
 compiler might recognize that some calculation has no external effects and
 remove it entirely.
 
-```{rust,ignore}
+```rust,ignore
 #![feature(test)]
 
 extern crate test;
index f5f314f1c21d6ee9d3bc719134a7ad013b23698f..1cfeb2620bd08d6fc16b5ae1a7779af4f4366822 100644 (file)
@@ -47,11 +47,11 @@ This is because the standard library has `impl Borrow<str> for String`.
 
 For most types, when you want to take an owned or borrowed type, a `&T` is
 enough. But one area where `Borrow` is effective is when there’s more than one
-kind of borrowed value. Slices are an area where this is especially true: you
-can have both an `&[T]` or a `&mut [T]`. If we wanted to accept both of these
-types, `Borrow` is up for it:
+kind of borrowed value. This is especially true of references and slices: you
+can have both an `&T` or a `&mut T`. If we wanted to accept both of these types,
+`Borrow` is up for it:
 
-```
+```rust
 use std::borrow::Borrow;
 use std::fmt::Display;
 
index 839f07d9843226560fd27d2165e113f51905f84f..8d83b64d68313441c4a704e438de8eab5ff4f296 100644 (file)
@@ -5,7 +5,7 @@ Also it is not possible in stable Rust to destructure a `Box` in a match
 pattern. The unstable `box` keyword can be used to both create and destructure
 a `Box`. An example usage would be:
 
-```
+```rust
 #![feature(box_syntax, box_patterns)]
 
 fn main() {
@@ -34,7 +34,7 @@ because the syntax may still change in the future.
 In many languages with pointers, you'd return a pointer from a function
 so as to avoid copying a large data structure. For example:
 
-```{rust}
+```rust
 struct BigStruct {
     one: i32,
     two: i32,
@@ -58,7 +58,7 @@ fn main() {
 ```
 
 The idea is that by passing around a box, you're only copying a pointer, rather
-than the hundred `int`s that make up the `BigStruct`.
+than the hundred `i32`s that make up the `BigStruct`.
 
 This is an antipattern in Rust. Instead, write this:
 
index d7fa84761e5271e770d29d671b46c23f555e0ac5..ce52ea5d690ccaee1eddc805ad3f23a1f14e8c8c 100644 (file)
@@ -33,8 +33,8 @@ let plus_two = |x| {
 assert_eq!(4, plus_two(2));
 ```
 
-You’ll notice a few things about closures that are a bit different than regular
-functions defined with `fn`. The first of which is that we did not need to
+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
 annotate the types of arguments the closure takes or the values it returns. We
 can:
 
@@ -48,18 +48,18 @@ But we don’t have to. Why is this? Basically, it was chosen for ergonomic reas
 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
-that inferring named function types can.
+problems that inferring named function types can.
 
 The second is that the syntax is similar, but a bit different. I’ve added spaces
-here to make them look a little closer:
+here for easier comparison:
 
 ```rust
-fn  plus_one_v1   (x: i32 ) -> i32 { x + 1 }
-let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
-let plus_one_v3 = |x: i32 |          x + 1  ;
+fn  plus_one_v1   (x: i32) -> i32 { x + 1 }
+let plus_one_v2 = |x: i32| -> i32 { x + 1 };
+let plus_one_v3 = |x: i32|          x + 1  ;
 ```
 
-Small differences, but they’re similar in ways.
+Small differences, but they’re similar.
 
 # Closures and their environment
 
@@ -99,7 +99,7 @@ note: previous borrow ends here
 fn main() {
     let mut num = 5;
     let plus_num = |x| x + num;
-    
+
     let y = &mut num;
 }
 ^
@@ -120,7 +120,7 @@ let y = &mut num;
 ```
 
 If your closure requires it, however, Rust will take ownership and move
-the environment instead:
+the environment instead. This doesn’t work:
 
 ```rust,ignore
 let nums = vec![1, 2, 3];
@@ -130,13 +130,13 @@ let takes_nums = || nums;
 println!("{:?}", nums);
 ```
 
-This gives us:
+We get this error:
 
 ```text
 note: `nums` moved into closure environment here because it has type
   `[closure(()) -> collections::vec::Vec<i32>]`, which is non-copyable
 let takes_nums = || nums;
-                    ^~~~~~~
+                 ^~~~~~~
 ```
 
 `Vec<T>` has ownership over its contents, and therefore, when we refer to it
@@ -161,7 +161,7 @@ of `num`. So what’s the difference?
 ```rust
 let mut num = 5;
 
-{ 
+{
     let mut add_num = |x: i32| num += x;
 
     add_num(5);
@@ -180,7 +180,7 @@ If we change to a `move` closure, it’s different:
 ```rust
 let mut num = 5;
 
-{ 
+{
     let mut add_num = move |x: i32| num += x;
 
     add_num(5);
@@ -324,37 +324,34 @@ first, it may seem strange, but we’ll figure it out. Here’s how you’d prob
 try to return a closure from a function:
 
 ```rust,ignore
-fn factory() -> (Fn(i32) -> Vec<i32>) {
-    let vec = vec![1, 2, 3];
+fn factory() -> (Fn(i32) -> i32) {
+    let num = 5;
 
-    |n| vec.push(n)
+    |x| x + num
 }
 
 let f = factory();
 
-let answer = f(4);
-assert_eq!(vec![1, 2, 3, 4], answer);
+let answer = f(1);
+assert_eq!(6, answer);
 ```
 
 This gives us these long, related errors:
 
 ```text
 error: the trait `core::marker::Sized` is not implemented for the type
-`core::ops::Fn(i32) -> collections::vec::Vec<i32>` [E0277]
-f = factory();
-^
-note: `core::ops::Fn(i32) -> collections::vec::Vec<i32>` does not have a
-constant size known at compile-time
-f = factory();
-^
-error: the trait `core::marker::Sized` is not implemented for the type
-`core::ops::Fn(i32) -> collections::vec::Vec<i32>` [E0277]
-factory() -> (Fn(i32) -> Vec<i32>) {
-             ^~~~~~~~~~~~~~~~~~~~~
-note: `core::ops::Fn(i32) -> collections::vec::Vec<i32>` does not have a constant size known at compile-time
-fa ctory() -> (Fn(i32) -> Vec<i32>) {
-              ^~~~~~~~~~~~~~~~~~~~~
-
+`core::ops::Fn(i32) -> i32` [E0277]
+fn factory() -> (Fn(i32) -> i32) {
+                ^~~~~~~~~~~~~~~~
+note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
+fn factory() -> (Fn(i32) -> i32) {
+                ^~~~~~~~~~~~~~~~
+error: the trait `core::marker::Sized` is not implemented for the type `core::ops::Fn(i32) -> i32` [E0277]
+let f = factory();
+    ^
+note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
+let f = factory();
+    ^
 ```
 
 In order to return something from a function, Rust needs to know what
@@ -364,16 +361,16 @@ way to give something a size is to take a reference to it, as references
 have a known size. So we’d write this:
 
 ```rust,ignore
-fn factory() -> &(Fn(i32) -> Vec<i32>) {
-    let vec = vec![1, 2, 3];
+fn factory() -> &(Fn(i32) -> i32) {
+    let num = 5;
 
-    |n| vec.push(n)
+    |x| x + num
 }
 
 let f = factory();
 
-let answer = f(4);
-assert_eq!(vec![1, 2, 3, 4], answer);
+let answer = f(1);
+assert_eq!(6, answer);
 ```
 
 But we get another error:
@@ -448,7 +445,8 @@ assert_eq!(6, answer);
 We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:
 
 ```text
-error: `num` does not live long enough
+error: closure may outlive the current function, but it borrows `num`,
+which is owned by the current function [E0373]
 Box::new(|x| x + num)
          ^~~~~~~~~~~
 ```
index fa27d1c226cc494cdf06bc9ce24b2a71d7d1d3fc..7687d2a57da9238de0900ee3e2ffda6f1d95cf25 100644 (file)
@@ -29,6 +29,9 @@ The other kind of comment is a doc comment. Doc comments use `///` instead of
 /// let five = 5;
 ///
 /// assert_eq!(6, add_one(5));
+/// # fn add_one(x: i32) -> i32 {
+/// #     x + 1
+/// # }
 /// ```
 fn add_one(x: i32) -> i32 {
     x + 1
index 3c64e0b14de42e1b2758b729510b2470b2467dcd..ccd769089d2519b60218ed8a346f251d72b7f66b 100644 (file)
@@ -59,7 +59,7 @@ place!
 Rust's standard library provides a library for threads, which allow you to
 run Rust code in parallel. Here's a basic example of using `std::thread`:
 
-```
+```rust
 use std::thread;
 
 fn main() {
@@ -73,7 +73,7 @@ The `thread::spawn()` method accepts a closure, which is executed in a
 new thread. It returns a handle to the thread, that can be used to
 wait for the child thread to finish and extract its result:
 
-```
+```rust
 use std::thread;
 
 fn main() {
@@ -189,7 +189,7 @@ guard across thread boundaries, which gives us our error.
 
 We can use `Arc<T>` to fix this. Here's the working version:
 
-```
+```rust
 use std::sync::{Arc, Mutex};
 use std::thread;
 
@@ -248,7 +248,7 @@ threads with each other. Let's talk about one of them: channels.
 Here's a version of our code that uses channels for synchronization, rather
 than waiting for a specific time:
 
-```
+```rust
 use std::sync::{Arc, Mutex};
 use std::thread;
 use std::sync::mpsc;
@@ -281,7 +281,7 @@ a simple `()` down the channel, and then wait for ten of them to come back.
 While this channel is just sending a generic signal, we can send any data that
 is `Send` over the channel!
 
-```
+```rust
 use std::thread;
 use std::sync::mpsc;
 
@@ -311,7 +311,7 @@ the answer, and then it `send()`s us the answer over the channel.
 A `panic!` will crash the currently executing thread. You can use Rust's
 threads as a simple isolation mechanism:
 
-```
+```rust
 use std::thread;
 
 let result = thread::spawn(move || {
index 73eb0101692afb9eec313d7202f69c93489fbf76..a944b852d249fcc46f84658f9977d7b30e68861b 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-[features]-section
+[features]: http://doc.crates.io/manifest.html#the-%5Bfeatures%5D-section
 
 ```toml
 [features]
index be0c87319b37cb22c2cbac081bbcdeff2a90095f..7d555b52a986df0329f7f1d42877ddc85aa15089 100644 (file)
@@ -31,10 +31,8 @@ static N: i32 = 5;
 
 Unlike [`let`][let] bindings, you must annotate the type of a `static`.
 
-[let]: variable-bindings.html
-
 Statics live for the entire lifetime of a program, and therefore any
-reference stored in a constant has a [`static` lifetime][lifetimes]:
+reference stored in a constant has a [`'static` lifetime][lifetimes]:
 
 ```rust
 static NAME: &'static str = "Steve";
@@ -66,7 +64,10 @@ unsafe {
 
 [unsafe]: unsafe.html
 
-Furthermore, any type stored in a `static` must be `Sync`.
+Furthermore, any type stored in a `static` must be `Sync`, and may not have
+a [`Drop`][drop] implementation.
+
+[drop]: drop.html
 
 # Initializing
 
@@ -80,7 +81,3 @@ Almost always, if you can choose between the two, choose `const`. It’s pretty
 rare that you actually want a memory location associated with your constant,
 and using a const allows for optimizations like constant propagation not only
 in your crate but downstream crates.
-
-A const can be thought of as a `#define` in C: it has metadata overhead but it
-has no runtime overhead. “Should I use a #define or a static in C,” is largely
-the same question as whether you should use a const or a static in Rust.
index 3ab3401e61264d046ddb81a3b8449d796a43e8da..63fdef0760febf66cc5ef05a79341136b67ac3d1 100644 (file)
@@ -75,7 +75,7 @@ above.
 To define each of our modules, we use the `mod` keyword. Let’s make our
 `src/lib.rs` look like this:
 
-```
+```rust
 mod english {
     mod greetings {
     }
@@ -126,7 +126,7 @@ ways.
 
 Instead of declaring a module like this:
 
-```{rust,ignore}
+```rust,ignore
 mod english {
     // contents of our module go here
 }
@@ -134,7 +134,7 @@ mod english {
 
 We can instead declare our module like this:
 
-```{rust,ignore}
+```rust,ignore
 mod english;
 ```
 
@@ -173,7 +173,7 @@ $ tree .
 
 `src/lib.rs` is our crate root, and looks like this:
 
-```{rust,ignore}
+```rust,ignore
 mod english;
 mod japanese;
 ```
@@ -184,7 +184,7 @@ on our preference. In this case, because our modules have sub-modules, we’ve
 chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
 like this:
 
-```{rust,ignore}
+```rust,ignore
 mod greetings;
 mod farewells;
 ```
@@ -297,7 +297,7 @@ public, and so private is the default. To make things public, you use the `pub`
 keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs`
 to just this:
 
-```{rust,ignore}
+```rust,ignore
 extern crate phrases;
 
 fn main() {
@@ -308,21 +308,21 @@ fn main() {
 
 In our `src/lib.rs`, let’s add `pub` to the `english` module declaration:
 
-```{rust,ignore}
+```rust,ignore
 pub mod english;
 mod japanese;
 ```
 
 And in our `src/english/mod.rs`, let’s make both `pub`:
 
-```{rust,ignore}
+```rust,ignore
 pub mod greetings;
 pub mod farewells;
 ```
 
 In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration:
 
-```{rust,ignore}
+```rust,ignore
 pub fn hello() -> String {
     "Hello!".to_string()
 }
@@ -330,7 +330,7 @@ pub fn hello() -> String {
 
 And also in `src/english/farewells.rs`:
 
-```{rust,ignore}
+```rust,ignore
 pub fn goodbye() -> String {
     "Goodbye.".to_string()
 }
@@ -365,7 +365,7 @@ refer to them with shorter names. Let’s talk about `use`.
 Rust has a `use` keyword, which allows us to import names into our local scope.
 Let’s change our `src/main.rs` to look like this:
 
-```{rust,ignore}
+```rust,ignore
 extern crate phrases;
 
 use phrases::english::greetings;
@@ -382,7 +382,7 @@ the functions by a much shorter name. By convention, when importing functions, i
 considered best practice to import the module, rather than the function directly. In
 other words, you _can_ do this:
 
-```{rust,ignore}
+```rust,ignore
 extern crate phrases;
 
 use phrases::english::greetings::hello;
@@ -400,7 +400,7 @@ becomes a problem. If we have conflicting names, Rust will give a compilation
 error. For example, if we made the `japanese` functions public, and tried to do
 this:
 
-```{rust,ignore}
+```rust,ignore
 extern crate phrases;
 
 use phrases::english::greetings::hello;
@@ -426,14 +426,14 @@ Could not compile `phrases`.
 If we’re importing multiple names from the same module, we don’t have to type it out
 twice. Instead of this:
 
-```{rust,ignore}
+```rust,ignore
 use phrases::english::greetings;
 use phrases::english::farewells;
 ```
 
 We can use this shortcut:
 
-```{rust,ignore}
+```rust,ignore
 use phrases::english::{greetings, farewells};
 ```
 
@@ -445,7 +445,7 @@ interface that may not directly map to your internal code organization.
 
 Let’s look at an example. Modify your `src/main.rs` to read like this:
 
-```{rust,ignore}
+```rust,ignore
 extern crate phrases;
 
 use phrases::english::{greetings,farewells};
@@ -462,14 +462,14 @@ fn main() {
 
 Then, modify your `src/lib.rs` to make the `japanese` mod public:
 
-```{rust,ignore}
+```rust,ignore
 pub mod english;
 pub mod japanese;
 ```
 
 Next, make the two functions public, first in `src/japanese/greetings.rs`:
 
-```{rust,ignore}
+```rust,ignore
 pub fn hello() -> String {
     "こんにちは".to_string()
 }
@@ -477,7 +477,7 @@ pub fn hello() -> String {
 
 And then in `src/japanese/farewells.rs`:
 
-```{rust,ignore}
+```rust,ignore
 pub fn goodbye() -> String {
     "さようなら".to_string()
 }
@@ -485,7 +485,7 @@ pub fn goodbye() -> String {
 
 Finally, modify your `src/japanese/mod.rs` to read like this:
 
-```{rust,ignore}
+```rust,ignore
 pub use self::greetings::hello;
 pub use self::farewells::goodbye;
 
index b179c90ceb95fade47c570880c37348f7183ab9f..b24d50c890da4a259c95d12adf9f80724601892e 100644 (file)
@@ -2,26 +2,28 @@
 
 For our second project, let’s look at a classic concurrency problem. It’s
 called ‘the dining philosophers’. It was originally conceived by Dijkstra in
-1965, but we’ll use the version from [this paper][paper] by Tony Hoare in 1985.
+1965, but we’ll use a lightly adapted version from [this paper][paper] by Tony
+Hoare in 1985.
 
 [paper]: http://www.usingcsp.com/cspbook.pdf
 
 > In ancient times, a wealthy philanthropist endowed a College to accommodate
-> five eminent philosophers. Each philosopher had a room in which he could
-> engage in his professional activity of thinking; there was also a common
+> five eminent philosophers. Each philosopher had a room in which they could
+> engage in their professional activity of thinking; there was also a common
 > 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
-> was constantly replenished. A philosopher was expected to spend most of his
-> time thinking; but when he felt hungry, he went to the dining room, sat down
-> in his own chair, picked up his own fork on his left, and plunged it into the
-> spaghetti. But such is the tangled nature of spaghetti that a second fork is
-> required to carry it to the mouth. The philosopher therefore had also to pick
-> up the fork on his right. When we was finished he would put down both his
-> forks, get up from his chair, and continue thinking. Of course, a fork can be
-> used by only one philosopher at a time. If the other philosopher wants it, he
-> just has to wait until the fork is available again.
+> 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,
+> and plunged it into the spaghetti. But such is the tangled nature of
+> spaghetti that a second fork is required to carry it to the mouth. The
+> philosopher therefore had also to pick up the fork on their right. When
+> they were finished they would put down both their forks, get up from their
+> chair, and continue thinking. Of course, a fork can be used by only one
+> philosopher at a time. If the other philosopher wants it, they just have
+> to wait until the fork is available again.
 
 This classic problem shows off a few different elements of concurrency. The
 reason is that it's actually slightly tricky to implement: a simple
@@ -60,10 +62,10 @@ impl Philosopher {
 }
 
 fn main() {
-    let p1 = Philosopher::new("Baruch Spinoza");
+    let p1 = Philosopher::new("Judith Butler");
     let p2 = Philosopher::new("Gilles Deleuze");
     let p3 = Philosopher::new("Karl Marx");
-    let p4 = Philosopher::new("Friedrich Nietzsche");
+    let p4 = Philosopher::new("Emma Goldman");
     let p5 = Philosopher::new("Michel Foucault");
 }
 ```
@@ -159,10 +161,10 @@ look at `main()` again:
 # }
 # 
 fn main() {
-    let p1 = Philosopher::new("Baruch Spinoza");
+    let p1 = Philosopher::new("Judith Butler");
     let p2 = Philosopher::new("Gilles Deleuze");
     let p3 = Philosopher::new("Karl Marx");
-    let p4 = Philosopher::new("Friedrich Nietzsche");
+    let p4 = Philosopher::new("Emma Goldman");
     let p5 = Philosopher::new("Michel Foucault");
 }
 ```
@@ -176,10 +178,10 @@ that `new()` function, it would look like this:
 #     name: String,
 # }
 fn main() {
-    let p1 = Philosopher { name: "Baruch Spinoza".to_string() };
+    let p1 = Philosopher { name: "Judith Butler".to_string() };
     let p2 = Philosopher { name: "Gilles Deleuze".to_string() };
     let p3 = Philosopher { name: "Karl Marx".to_string() };
-    let p4 = Philosopher { name: "Friedrich Nietzche".to_string() };
+    let p4 = Philosopher { name: "Emma Goldman".to_string() };
     let p5 = Philosopher { name: "Michel Foucault".to_string() };
 }
 ```
@@ -211,10 +213,10 @@ impl Philosopher {
 
 fn main() {
     let philosophers = vec![
-        Philosopher::new("Baruch Spinoza"),
+        Philosopher::new("Judith Butler"),
         Philosopher::new("Gilles Deleuze"),
         Philosopher::new("Karl Marx"),
-        Philosopher::new("Friedrich Nietzsche"),
+        Philosopher::new("Emma Goldman"),
         Philosopher::new("Michel Foucault"),
     ];
 
@@ -247,10 +249,10 @@ mention they’re done eating. Running this program should give you the followin
 output:
 
 ```text
-Baruch Spinoza is done eating.
+Judith Butler is done eating.
 Gilles Deleuze is done eating.
 Karl Marx is done eating.
-Friedrich Nietzsche is done eating.
+Emma Goldman is done eating.
 Michel Foucault is done eating.
 ```
 
@@ -285,10 +287,10 @@ impl Philosopher {
 
 fn main() {
     let philosophers = vec![
-        Philosopher::new("Baruch Spinoza"),
+        Philosopher::new("Judith Butler"),
         Philosopher::new("Gilles Deleuze"),
         Philosopher::new("Karl Marx"),
-        Philosopher::new("Friedrich Nietzsche"),
+        Philosopher::new("Emma Goldman"),
         Philosopher::new("Michel Foucault"),
     ];
 
@@ -320,17 +322,17 @@ from the standard library, and so we need to `use` it.
 We now print out two messages, with a `sleep_ms()` in the middle. This will
 simulate the time it takes a philosopher to eat.
 
-If you run this program, You should see each philosopher eat in turn:
+If you run this program, you should see each philosopher eat in turn:
 
 ```text
-Baruch Spinoza is eating.
-Baruch Spinoza is done eating.
+Judith Butler is eating.
+Judith Butler is done eating.
 Gilles Deleuze is eating.
 Gilles Deleuze is done eating.
 Karl Marx is eating.
 Karl Marx is done eating.
-Friedrich Nietzsche is eating.
-Friedrich Nietzsche is done eating.
+Emma Goldman is eating.
+Emma Goldman is done eating.
 Michel Foucault is eating.
 Michel Foucault is done eating.
 ```
@@ -366,10 +368,10 @@ impl Philosopher {
 
 fn main() {
     let philosophers = vec![
-        Philosopher::new("Baruch Spinoza"),
+        Philosopher::new("Judith Butler"),
         Philosopher::new("Gilles Deleuze"),
         Philosopher::new("Karl Marx"),
-        Philosopher::new("Friedrich Nietzsche"),
+        Philosopher::new("Emma Goldman"),
         Philosopher::new("Michel Foucault"),
     ];
 
@@ -430,7 +432,9 @@ an extra annotation, `move`, to indicate that the closure is going to take
 ownership of the values it’s capturing. Primarily, the `p` variable of the
 `map` function.
 
-Inside the thread, all we do is call `eat()` on `p`.
+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
 
 ```rust,ignore
 }).collect();
@@ -458,11 +462,11 @@ We have multi-threading!
 ```text
 Gilles Deleuze is eating.
 Gilles Deleuze is done eating.
-Friedrich Nietzsche is eating.
-Friedrich Nietzsche is done eating.
+Emma Goldman is eating.
+Emma Goldman is done eating.
 Michel Foucault is eating.
-Baruch Spinoza is eating.
-Baruch Spinoza is done eating.
+Judith Butler is eating.
+Judith Butler is done eating.
 Karl Marx is eating.
 Karl Marx is done eating.
 Michel Foucault is done eating.
@@ -480,7 +484,7 @@ struct Table {
 }
 ```
 
-This `Table` has an vector of `Mutex`es. A mutex is a way to control
+This `Table` has a vector of `Mutex`es. A mutex is a way to control
 concurrency: only one thread can access the contents at once. This is exactly
 the property we need with our forks. We use an empty tuple, `()`, inside the
 mutex, since we’re not actually going to use the value, just hold onto it.
@@ -532,10 +536,10 @@ fn main() {
     ]});
 
     let philosophers = vec![
-        Philosopher::new("Baruch Spinoza", 0, 1),
+        Philosopher::new("Judith Butler", 0, 1),
         Philosopher::new("Gilles Deleuze", 1, 2),
         Philosopher::new("Karl Marx", 2, 3),
-        Philosopher::new("Friedrich Nietzsche", 3, 4),
+        Philosopher::new("Emma Goldman", 3, 4),
         Philosopher::new("Michel Foucault", 0, 4),
     ];
 
@@ -643,10 +647,10 @@ count will go up, and when each thread ends, it will go back down.
 
 ```rust,ignore
 let philosophers = vec![
-    Philosopher::new("Baruch Spinoza", 0, 1),
+    Philosopher::new("Judith Butler", 0, 1),
     Philosopher::new("Gilles Deleuze", 1, 2),
     Philosopher::new("Karl Marx", 2, 3),
-    Philosopher::new("Friedrich Nietzsche", 3, 4),
+    Philosopher::new("Emma Goldman", 3, 4),
     Philosopher::new("Michel Foucault", 0, 4),
 ];
 ```
@@ -670,21 +674,25 @@ let handles: Vec<_> = philosophers.into_iter().map(|p| {
 
 Finally, inside of our `map()`/`collect()` loop, we call `table.clone()`. The
 `clone()` method on `Arc<T>` is what bumps up the reference count, and when it
-goes out of scope, it decrements the count. You’ll notice we can introduce a
-new binding to `table` here, and it will shadow the old one. This is often used
-so that you don’t need to come up with two unique names.
+goes out of scope, it decrements the count. This is needed so that we know how
+many references to `table` exist across our threads. If we didn’t have a count,
+we wouldn’t know how to deallocate it.
+
+You’ll notice we can introduce a new binding to `table` here, and it will
+shadow the old one. This is often used so that you don’t need to come up with
+two unique names.
 
 With this, our program works! Only two philosophers can eat at any one time,
 and so you’ll get some output like this:
 
 ```text
 Gilles Deleuze is eating.
-Friedrich Nietzsche is eating.
-Friedrich Nietzsche is done eating.
+Emma Goldman is eating.
+Emma Goldman is done eating.
 Gilles Deleuze is done eating.
-Baruch Spinoza is eating.
+Judith Butler is eating.
 Karl Marx is eating.
-Baruch Spinoza is done eating.
+Judith Butler is done eating.
 Michel Foucault is eating.
 Karl Marx is done eating.
 Michel Foucault is done eating.
index b28343e7fb94c75f7acd8d654bad07c4098720b1..1a64ab6646db9566eafff23b2d907547726a176f 100644 (file)
@@ -42,7 +42,7 @@ Documentation comments are written in Markdown.
 Rust keeps track of these comments, and uses them when generating
 documentation. This is important when documenting things like enums:
 
-```
+```rust
 /// The `Option` type. See [the module level documentation](../) for more.
 enum Option<T> {
     /// No value
@@ -80,7 +80,7 @@ thing after that last comment.
 
 Anyway, let's cover each part of this comment in detail:
 
-```
+```rust
 /// Constructs a new `Rc<T>`.
 # fn foo() {}
 ```
@@ -88,7 +88,7 @@ Anyway, let's cover each part of this comment in detail:
 The first line of a documentation comment should be a short summary of its
 functionality. One sentence. Just the basics. High level.
 
-```
+```rust
 ///
 /// Other details about constructing `Rc<T>`s, maybe describing complicated
 /// semantics, maybe additional options, all kinds of stuff.
@@ -101,16 +101,11 @@ we could have added more explanation in a new paragraph.
 
 #### Special sections
 
-```
-/// # Examples
-# fn foo() {}
-```
-
 Next, are special sections. These are indicated with a header, `#`. There
 are three kinds of headers that are commonly used. They aren't special syntax,
 just convention, for now.
 
-```
+```rust
 /// # Panics
 # fn foo() {}
 ```
@@ -120,7 +115,7 @@ usually indicated by panics, which kill the whole current thread at the very
 least. If your function has a non-trivial contract like this, that is
 detected/enforced by panics, documenting it is very important.
 
-```
+```rust
 /// # Failures
 # fn foo() {}
 ```
@@ -130,7 +125,7 @@ conditions under which it returns `Err(E)` is a nice thing to do. This is
 slightly less important than `Panics`, because failure is encoded into the type
 system, but it's still a good thing to do.
 
-```
+```rust
 /// # Safety
 # fn foo() {}
 ```
@@ -138,7 +133,7 @@ system, but it's still a good thing to do.
 If your function is `unsafe`, you should explain which invariants the caller is
 responsible for upholding.
 
-```
+```rust
 /// # Examples
 ///
 /// ```
@@ -154,7 +149,7 @@ method, and your users will love you for it. These examples go inside of
 code block annotations, which we'll talk about in a moment, and can have
 more than one section:
 
-```
+```rust
 /// # Examples
 ///
 /// Simple `&str` patterns:
@@ -179,7 +174,7 @@ Let's discuss the details of these code blocks.
 
 To write some Rust code in a comment, use the triple graves:
 
-```
+```rust
 /// ```
 /// println!("Hello, world");
 /// ```
@@ -188,7 +183,7 @@ To write some Rust code in a comment, use the triple graves:
 
 If you want something that's not Rust code, you can add an annotation:
 
-```
+```rust
 /// ```c
 /// printf("Hello, world\n");
 /// ```
@@ -208,7 +203,7 @@ generate the documentation.
 
 Let's discuss our sample example documentation:
 
-```
+```rust
 /// ```
 /// println!("Hello, world");
 /// ```
@@ -219,7 +214,7 @@ 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.
 For example:
 
-```
+```rust
 /// ```
 /// use std::rc::Rc;
 ///
@@ -230,7 +225,7 @@ For example:
 
 This will end up testing:
 
-```
+```rust
 fn main() {
     use std::rc::Rc;
     let five = Rc::new(5);
@@ -259,7 +254,7 @@ with `///` we've been talking about? The raw text:
 
 looks different than the output:
 
-```
+```rust
 /// Some documentation.
 # fn foo() {}
 ```
@@ -274,7 +269,7 @@ 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);
@@ -284,7 +279,7 @@ Here's an explanation, rendered:
 
 First, we set `x` to five:
 
-```
+```rust
 let x = 5;
 # let y = 6;
 # println!("{}", x + y);
@@ -292,7 +287,7 @@ let x = 5;
 
 Next, we set `y` to six:
 
-```
+```rust
 # let x = 5;
 let y = 6;
 # println!("{}", x + y);
@@ -300,7 +295,7 @@ let y = 6;
 
 Finally, we print the sum of `x` and `y`:
 
-```
+```rust
 # let x = 5;
 # let y = 6;
 println!("{}", x + y);
@@ -340,7 +335,7 @@ explanation.
 
 Here’s an example of documenting a macro:
 
-```
+```rust
 /// Panic with a given message unless an expression evaluates to true.
 ///
 /// # Examples
@@ -388,7 +383,7 @@ but with a binary, there’s nothing to link to.
 There are a few more annotations that are useful to help `rustdoc` do the right
 thing when testing your code:
 
-```
+```rust
 /// ```ignore
 /// fn foo() {
 /// ```
@@ -400,7 +395,7 @@ what you want, as it's the most generic. Instead, consider annotating it
 with `text` if it's not code, or using `#`s to get a working example that
 only shows the part you care about.
 
-```
+```rust
 /// ```should_panic
 /// assert!(false);
 /// ```
@@ -410,7 +405,7 @@ only shows the part you care about.
 `should_panic` tells `rustdoc` that the code should compile correctly, but
 not actually pass as a test.
 
-```
+```rust
 /// ```no_run
 /// loop {
 ///     println!("Hello, world");
@@ -427,7 +422,7 @@ which you would want to make sure compile, but might run in an infinite loop!
 
 Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words:
 
-```
+```rust
 mod foo {
     //! This is documentation for the `foo` module.
     //!
@@ -440,7 +435,7 @@ mod foo {
 This is where you'll see `//!` used most often: for module documentation. If
 you have a module in `foo.rs`, you'll often open its code and see this:
 
-```
+```rust
 //! A module for using `foo`s.
 //!
 //! The `foo` module contains a lot of useful functionality blah blah blah
@@ -461,7 +456,7 @@ are written in Markdown, they're often `.md` files.
 When you write documentation in Markdown files, you don't need to prefix
 the documentation with comments. For example:
 
-```
+```rust
 /// # Examples
 ///
 /// ```
@@ -499,7 +494,7 @@ This `%` line needs to be the very first line of the file.
 
 At a deeper level, documentation comments are sugar for documentation attributes:
 
-```
+```rust
 /// this
 # fn foo() {}
 
@@ -509,7 +504,7 @@ At a deeper level, documentation comments are sugar for documentation attributes
 
 are the same, as are these:
 
-```
+```rust
 //! this
 
 #![doc="/// this"]
@@ -546,10 +541,10 @@ pub use foo::bar;
 You can control a few aspects of the HTML that `rustdoc` generates through the
 `#![doc]` version of the attribute:
 
-```
+```rust
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")];
+       html_root_url = "http://doc.rust-lang.org/")]
 ```
 
 This sets a few different options, with a logo, favicon, and a root URL.
index 01905caf5ec0dd9734a2d297f700e73c9b38a60b..8ad4eeedd187f46585a55e70935236c423067ef9 100644 (file)
@@ -64,3 +64,45 @@ equality yet, but we’ll find out in the [`traits`][traits] section.
 [match]: match.html
 [if-let]: if-let.html
 [traits]: traits.html
+
+# Constructors as functions
+
+An enum’s constructors can also be used like functions. For example:
+
+```rust
+# enum Message {
+# Write(String),
+# }
+let m = Message::Write("Hello, world".to_string());
+```
+
+Is the same as
+
+```rust
+# enum Message {
+# Write(String),
+# }
+fn foo(x: String) -> Message {
+    Message::Write(x)
+}
+
+let x = foo("Hello, world".to_string());
+```
+
+This is not immediately useful to us, but when we get to
+[`closures`][closures], we’ll talk about passing functions as arguments to
+other functions. For example, with [`iterators`][iterators], we can do this
+to convert a vector of `String`s into a vector of `Message::Write`s:
+
+```rust
+# enum Message {
+# Write(String),
+# }
+
+let v = vec!["Hello".to_string(), "World".to_string()];
+
+let v1: Vec<Message> = v.into_iter().map(Message::Write).collect();
+```
+
+[closures]: closures.html
+[iterators]: iterators.html
index dcaf698fd3c9d2d34377a8ba2fca5fb49d1981e7..580eaa6ca55710e2724d964a1409f12d2e212d04 100644 (file)
@@ -49,7 +49,7 @@ We use `assert!` to declare that something is true. If it's not true, something
 is very wrong. Wrong enough that we can't continue with things in the current
 state. Another example is using the `unreachable!()` macro:
 
-```{rust,ignore}
+```rust,ignore
 enum Event {
     NewRelease,
 }
@@ -188,7 +188,7 @@ The [`Debug`](../std/fmt/trait.Debug.html) trait is what lets us print the enum
 In the case of an error that is unexpected and not recoverable, the `panic!`
 macro will induce a panic. This will crash the current thread, and give an error:
 
-```{rust,ignore}
+```rust,ignore
 panic!("boom");
 ```
 
@@ -212,7 +212,7 @@ handle and possibly recover from error.
 If we don't want to handle this error, and would rather just abort the program,
 we can use the `unwrap()` method:
 
-```{rust,ignore}
+```rust,ignore
 io::stdin().read_line(&mut buffer).unwrap();
 ```
 
@@ -223,11 +223,11 @@ shorter. Sometimes, just crashing is appropriate.
 
 There's another way of doing this that's a bit nicer than `unwrap()`:
 
-```{rust,ignore}
+```rust,ignore
 let mut buffer = String::new();
-let input = io::stdin().read_line(&mut buffer)
-                       .ok()
-                       .expect("Failed to read line");
+let num_bytes_read = io::stdin().read_line(&mut buffer)
+                                .ok()
+                                .expect("Failed to read line");
 ```
 
 `ok()` converts the `Result` into an `Option`, and `expect()` does the same
@@ -284,7 +284,7 @@ struct Info {
 }
 
 fn write_info(info: &Info) -> io::Result<()> {
-    let mut file = try!(File::create("my_best_friends.txt"));
+    let mut file = File::create("my_best_friends.txt").unwrap();
 
     try!(writeln!(&mut file, "name: {}", info.name));
     try!(writeln!(&mut file, "age: {}", info.age));
index 2c5e6b2e5fc7c1af042149bd6452ed34aed3eb0a..917d8dbe196c76826939f168e5717f235ecd21e7 100644 (file)
@@ -81,7 +81,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous
 length is number of elements currently contained, and the capacity is the total size in elements of
 the allocated memory. The length is less than or equal to the capacity.
 
-```
+```rust
 # #![feature(libc)]
 # extern crate libc;
 # use libc::{c_int, size_t};
@@ -106,7 +106,7 @@ required capacity to hold the compressed output. The vector can then be passed t
 `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
 the true length after compression for setting the length.
 
-```
+```rust
 # #![feature(libc)]
 # extern crate libc;
 # use libc::{size_t, c_int};
@@ -133,7 +133,7 @@ pub fn compress(src: &[u8]) -> Vec<u8> {
 Decompression is similar, because snappy stores the uncompressed size as part of the compression
 format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
 
-```
+```rust
 # #![feature(libc)]
 # extern crate libc;
 # use libc::{size_t, c_int};
@@ -238,7 +238,7 @@ However it is often desired that the callback is targeted to a special
 Rust object. This could be the object that represents the wrapper for the
 respective C object.
 
-This can be achieved by passing an unsafe pointer to the object down to the
+This can be achieved by passing an raw pointer to the object down to the
 C library. The C library can then include the pointer to the Rust object in
 the notification. This will allow the callback to unsafely access the
 referenced Rust object.
@@ -342,8 +342,10 @@ Note that frameworks are only available on OSX targets.
 The different `kind` values are meant to differentiate how the native library
 participates in linkage. From a linkage perspective, the rust compiler creates
 two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
-Native dynamic libraries and frameworks are propagated to the final artifact
-boundary, while static libraries are not propagated at all.
+Native dynamic library and framework dependencies are propagated to the final
+artifact boundary, while static library dependencies are not propagated at
+all, because the static libraries are integrated directly into the subsequent
+artifact.
 
 A few examples of how this model can be used are:
 
@@ -368,14 +370,14 @@ On OSX, frameworks behave with the same semantics as a dynamic library.
 
 # Unsafe blocks
 
-Some operations, like dereferencing unsafe pointers or calling functions that have been marked
+Some operations, like dereferencing raw pointers or calling functions that have been marked
 unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
 the compiler that the unsafety does not leak out of the block.
 
 Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
 this:
 
-```
+```rust
 unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr }
 ```
 
@@ -439,7 +441,7 @@ Most foreign code exposes a C ABI, and Rust uses the platform's C calling conven
 calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
 conventions. Rust provides a way to tell the compiler which convention to use:
 
-```
+```rust
 # #![feature(libc)]
 extern crate libc;
 
@@ -516,7 +518,7 @@ function pointer using the C ABI.
 You may wish to compile Rust code in a way so that it can be called from C. This is
 fairly easy, but requires a few things:
 
-```
+```rust
 #[no_mangle]
 pub extern fn hello_rust() -> *const u8 {
     "Hello, world!\0".as_ptr()
@@ -528,3 +530,37 @@ The `extern` makes this function adhere to the C calling convention, as
 discussed above in "[Foreign Calling
 Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
 attribute turns off Rust's name mangling, so that it is easier to link to.
+
+# FFI and panics
+
+It’s important to be mindful of `panic!`s when working with FFI. This code,
+when called from C, will `abort`:
+
+```rust
+#[no_mangle]
+pub extern fn oh_no() -> ! {
+    panic!("Oops!");
+}
+# fn main() {}
+```
+
+If you’re writing code that may panic, you should run it in another thread,
+so that the panic doesn’t bubble up to C:
+
+```rust
+use std::thread;
+
+#[no_mangle]
+pub extern fn oh_no() -> i32 {
+    let h = thread::spawn(|| {
+        panic!("Oops!");
+    });
+
+    match h.join() {
+        Ok(_) => 1,
+        Err(_) => 0,
+    }
+}
+# fn main() {}
+```
+
index 1e3f2fa54bcc6c292bef7912c1ea1699b8603dc5..2866cee3a1a63bb4546b7c3d833ed0f9453ede9c 100644 (file)
@@ -41,3 +41,45 @@ so our loop will print `0` through `9`, not `10`.
 Rust does not have the “C-style” `for` loop on purpose. Manually controlling
 each element of the loop is complicated and error prone, even for experienced C
 developers.
+
+# Enumerate
+
+When you need to keep track of how many times you already looped, you can use the `.enumerate()` function.
+
+## On ranges:
+
+```rust
+for (i,j) in (5..10).enumerate() {
+    println!("i = {} and j = {}", i, j);
+}
+```
+
+Outputs:
+
+```text
+i = 0 and j = 5
+i = 1 and j = 6
+i = 2 and j = 7
+i = 3 and j = 8
+i = 4 and j = 9
+```
+
+Don't forget to add the parentheses around the range.
+
+## On iterators:
+
+```rust
+# let lines = "hello\nworld".lines();
+for (linenumber, line) in lines.enumerate() {
+    println!("{}: {}", linenumber, line);
+}
+```
+
+Outputs:
+
+```text
+0: Content of line one
+1: Content of line two
+2: Content of line tree
+3: Content of line four
+```
index 87af48532a050dd35a736ebe2fbfb8fc5cd754cf..ea927707ecd6fe272d8b8f454c2dddcc429e09cb 100644 (file)
@@ -144,9 +144,11 @@ an expression, and a `let` can only begin a statement, not an expression.
 Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
 expression, although its value is not particularly useful. Unlike other
 languages where an assignment evaluates to the assigned value (e.g. `5` in the
-previous example), in Rust the value of an assignment is an empty tuple `()`:
+previous example), in Rust the value of an assignment is an empty tuple `()`
+because the assigned value can have [just one owner](ownership.html), and any
+other returned value would be too surprising:
 
-```
+```rust
 let mut y = 5;
 
 let x = (y = 6);  // x has the value `()`, not `6`
@@ -204,7 +206,7 @@ time.
 Rust has some special syntax for ‘diverging functions’, which are functions that
 do not return:
 
-```
+```rust
 fn diverges() -> ! {
     panic!("This function never returns!");
 }
index 517a6e6064253295a6292e1a6b2a3e0147f5b2bd..c28d7c71608bbf82e754daae4bd1560e26efc7c6 100644 (file)
@@ -1,8 +1,8 @@
 % Generics
 
 Sometimes, when writing a function or data type, we may want it to work for
-multiple types of arguments. Luckily, Rust has a feature that gives us a better
-way: generics. Generics are called ‘parametric polymorphism’ in type theory,
+multiple types of arguments. In Rust, we can do this with generics.
+Generics are called ‘parametric polymorphism’ in type theory,
 which means that they are types or functions that have multiple forms (‘poly’
 is multiple, ‘morph’ is form) over a given parameter (‘parametric’).
 
@@ -110,7 +110,7 @@ Generic functions are most useful with ‘trait bounds’, which we’ll cover i
 
 You can store a generic type in a `struct` as well:
 
-```
+```rust
 struct Point<T> {
     x: T,
     y: T,
index 9845fcbdcd173ec3d6b3543bb2fba9689cf5727e..c97da0e95b8235a0d6c9d352d9e3ab86002707b2 100644 (file)
@@ -19,7 +19,7 @@ In the example above `x` and `y` have arity 2. `z` has arity 3.
 
 When a compiler is compiling your program, it does a number of different
 things. One of the things that it does is turn the text of your program into an
-‘abstract syntax tree’, or‘AST’. This tree is a representation of the
+‘abstract syntax tree’, or ‘AST’. This tree is a representation of the
 structure of your program. For example, `2 + 3` can be turned into a tree:
 
 ```text
index a2136431cb3dcd64aa1515c1c9285b97f2a0ef76..a599b8a855e9209bb63420737870f07bf45c0297 100644 (file)
@@ -38,7 +38,7 @@ Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
 
 ```rust
 fn main() {
-    println!("Hello, world!")
+    println!("Hello, world!");
 }
 ```
 
@@ -148,10 +148,10 @@ 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
-‘[pattern][patterns]’. We’ll use patterns more later. It’s easy enough
+‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
 to use for now:
 
-```
+```rust
 let foo = 5; // immutable.
 let mut bar = 5; // mutable
 ```
@@ -362,7 +362,7 @@ everything that follows it is part of it, until the next section starts.
 Cargo uses the dependencies section to know what dependencies on external
 crates you have, and what versions you require. In this case, we’ve used version `0.3.0`.
 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
-numbers. If we wanted to use the latest version we could use `*` or we could use a range 
+numbers. If we wanted to use the latest version we could use `*` or we could use a range
 of versions. [Cargo’s documentation][cargodoc] contains more details.
 
 [semver]: http://semver.org
@@ -637,7 +637,7 @@ When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
 should be a `String`, and so it doesn’t make us write out the type. And with
 our `secret_number`, there are a number of types which can have a value
 between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
-unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number. Or others.
+unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others.
 So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
 need to be the same type. Ultimately, we want to convert the `String` we
index cc8747d1fa7c17d6a7751dd9c6538abc60ded88d..8e479977887d7637d94c370ad3ea81cbb8f9711b 100644 (file)
@@ -33,9 +33,10 @@ $ mv main.rs src/main.rs
 ```
 
 Note that since we're creating an executable, we used `main.rs`. If we
-want to make a library instead, we should use `lib.rs`.
+want to make a library instead, we should use `lib.rs`. This convention is required
+for 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 described below.
+with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
 
 [crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
 
@@ -62,18 +63,17 @@ version = "0.0.1"
 authors = [ "Your name <you@example.com>" ]
 ```
 
-This file is in the [TOML][toml] format. Let’s let it explain itself to you:
+This file is in the [TOML][toml] format. TOML is similar to INI, but has some 
+extra goodies. According to the TOML docs, 
 
 > TOML aims to be a minimal configuration file format that's easy to read due
 > to obvious semantics. TOML is designed to map unambiguously to a hash table.
 > TOML should be easy to parse into data structures in a wide variety of
 > languages.
 
-TOML is very similar to INI, but with some extra goodies.
-
 [toml]: https://github.com/toml-lang/toml
 
-Once you have this file in place, we should be ready to build! Try this:
+Once you have this file in place, we should be ready to build! To do so, run:
 
 ```bash
 $ cargo build
@@ -82,7 +82,7 @@ $ ./target/debug/hello_world
 Hello, world!
 ```
 
-Bam! We build our project with `cargo build`, and run it with
+Bam! We built our project with `cargo build`, and ran it with
 `./target/debug/hello_world`. We can do both in one step with `cargo run`:
 
 ```bash
@@ -103,9 +103,9 @@ Hello, world!
 ```
 
 This hasn’t bought us a whole lot over our simple use of `rustc`, but think
-about the future: when our project gets more complex, we would need to do more
+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 `cargo build`, and it’ll work the right way.
+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.
@@ -118,7 +118,7 @@ name = "hello_world"
 version = "0.0.1"
 ```
 
-This file is used by Cargo to keep track of dependencies in your application.
+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.
 
@@ -145,8 +145,7 @@ To start a new project with Cargo, use `cargo new`:
 $ cargo new hello_world --bin
 ```
 
-We’re passing `--bin` because we're making a binary program: if we were making
-a library, we'd leave it off.
+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)
 
 Let's check out what Cargo has generated for us:
 
@@ -170,7 +169,7 @@ This is all we need to get started. First, let’s check out `Cargo.toml`:
 [package]
 
 name = "hello_world"
-version = "0.0.1"
+version = "0.1.0"
 authors = ["Your Name <you@example.com>"]
 ```
 
index 58c2a982dd3097443c88eb98e614e4a05690869b..4d9166d63bfb7e81b36c316effcde41382c63c6b 100644 (file)
@@ -25,7 +25,7 @@ crate to allow) and of course requires an `unsafe` block.
 The `assembly template` is the only required parameter and must be a
 literal string (i.e. `""`)
 
-```
+```rust
 #![feature(asm)]
 
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -51,7 +51,7 @@ fn main() {
 Output operands, input operands, clobbers and options are all optional
 but you must add the right number of `:` if you skip them:
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() { unsafe {
@@ -65,7 +65,7 @@ asm!("xor %eax, %eax"
 
 Whitespace also doesn't matter:
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() { unsafe {
@@ -79,7 +79,7 @@ Input and output operands follow the same format: `:
 "constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
 expressions must be mutable lvalues, or not yet assigned:
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 fn add(a: i32, b: i32) -> i32 {
@@ -106,7 +106,7 @@ you want, and you are required to put the specific size of the
 operand. This is useful for very low level programming, where 
 which register you use is important:
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # unsafe fn read_byte_in(port: u16) -> u8 {
@@ -123,7 +123,7 @@ different values so we use the clobbers list to indicate to the
 compiler not to assume any values loaded into those registers will
 stay valid.
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() { unsafe {
@@ -155,7 +155,7 @@ Current valid options are:
    the compiler to insert its usual stack alignment code
 3. *intel* - use intel syntax instead of the default AT&T.
 
-```
+```rust
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() {
index af1e503bb7fa96f263f9b5eea8e88a3b0bc76ff1..44eafd5192945fd457cb99d132e9d6107c324237 100644 (file)
@@ -2,8 +2,12 @@
 
 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 (note that you don't need to type in the
-`$`s, they just indicate the start of each command):
+or a Mac, all you 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.
 
 ```bash
 $ curl -sf -L https://static.rust-lang.org/rustup.sh | sh
@@ -41,10 +45,10 @@ 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
+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
+[from-source]: https://github.com/rust-lang/rust#building-from-source
 
 Oh, we should also mention the officially supported platforms:
 
index 25f7c54493188d93e76d85b7d2407722f355571f..e0a8bb59e346a042119896a727cc0d0d986246ff 100644 (file)
@@ -10,7 +10,7 @@ context, but wished to be able to `transmute` between types, and
 perform efficient pointer arithmetic, one would import those functions
 via a declaration like
 
-```
+```rust
 # #![feature(intrinsics)]
 # fn main() {}
 
index a93f622e9c529699e0ec03d6c6c0a9aeca5775f0..1c574f02091f8574f956557d3b67c7a2a4d30413 100644 (file)
@@ -116,7 +116,7 @@ A *consumer* operates on an iterator, returning some kind of value or values.
 The most common consumer is `collect()`. This code doesn't quite compile,
 but it shows the intention:
 
-```{rust,ignore}
+```rust,ignore
 let one_to_one_hundred = (1..101).collect();
 ```
 
@@ -213,7 +213,7 @@ As we've said before, an iterator is something that we can call the
 `.next()` method on repeatedly, and it gives us a sequence of things.
 Because you need to call the method, this means that iterators
 can be *lazy* and not generate all of the values upfront. This code,
-for example, does not actually generate the numbers `1-100`, instead
+for example, does not actually generate the numbers `1-99`, instead
 creating a value that merely represents the sequence:
 
 ```rust
@@ -253,7 +253,7 @@ we need to talk about with regards to iterators. Let's get to it!
 *Iterator adapters* take an iterator and modify it somehow, producing
 a new iterator. The simplest one is called `map`:
 
-```{rust,ignore}
+```rust,ignore
 (1..100).map(|x| x + 1);
 ```
 
@@ -272,7 +272,7 @@ warning: unused result which must be used: iterator adaptors are lazy and
 Laziness strikes again! That closure will never execute. This example
 doesn't print any numbers:
 
-```{rust,ignore}
+```rust,ignore
 (1..100).map(|x| println!("{}", x));
 ```
 
@@ -285,8 +285,7 @@ has no side effect on the original iterator. Let's try it out with our infinite
 iterator from before:
 
 ```rust
-# #![feature(step_by)]
-for i in (1..).step_by(5).take(5) {
+for i in (1..).take(5) {
     println!("{}", i);
 }
 ```
@@ -295,10 +294,10 @@ This will print
 
 ```text
 1
-6
-11
-16
-21
+2
+3
+4
+5
 ```
 
 `filter()` is an adapter that takes a closure as an argument. This closure
@@ -321,7 +320,7 @@ You can chain all three things together: start with an iterator, adapt it
 a few times, and then consume the result. Check it out:
 
 ```rust
-(1..1000)
+(1..)
     .filter(|&x| x % 2 == 0)
     .filter(|&x| x % 3 == 0)
     .take(5)
index 4808ad6ff1febb22e55291320747f7a6c10f1b15..8e7504c2f18ea5eb76bba3b5f02857ae98a5e17c 100644 (file)
@@ -15,7 +15,7 @@ For example, `Box` pointers require two lang items, one for allocation
 and one for deallocation. A freestanding program that uses the `Box`
 sugar for dynamic allocations via `malloc` and `free`:
 
-```
+```rust
 #![feature(lang_items, box_syntax, start, no_std, libc)]
 #![no_std]
 
index 342de413f0b9aab34a72de6036002bf3d8e677f1..11d651c5778e3ebdaad134184d11bcb3382c6fa2 100644 (file)
@@ -137,6 +137,27 @@ x: &'a i32,
 uses it. So why do we need a lifetime here? We need to ensure that any reference
 to a `Foo` cannot outlive the reference to an `i32` it contains.
 
+If you have multiple references, you can use the same lifetime multiple times:
+
+```rust
+fn x_or_y<'a>(x: &'a str, y: &'a str) -> &'a str {
+#    x
+# }
+```
+
+This says that `x` and `y` both are alive for the same scope, and that the
+return value is also alive for that scope. If you wanted `x` and `y` to have
+different lifetimes, you can use multiple lifetime parameters:
+
+```rust
+fn x_or_y<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
+#    x
+# }
+```
+
+In this example, `x` and `y` have different valid scopes, but the return value
+has the same lifetime as `x`.
+
 ## Thinking in scopes
 
 A way to think about lifetimes is to visualize the scope that a reference is
@@ -219,7 +240,7 @@ to it.
 ## Lifetime Elision
 
 Rust supports powerful local type inference in function bodies, but it’s
-forbidden in item signatures to allow reasoning about the types just based in
+forbidden in item signatures to allow reasoning about the types based on
 the item signature alone. However, for ergonomic reasons a very restricted
 secondary inference algorithm called “lifetime elision” applies in function
 signatures. It infers only based on the signature components themselves and not
@@ -284,7 +305,7 @@ fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
 fn get_str() -> &str; // ILLEGAL, no inputs
 
 fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
-fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is unclear
+fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is ambiguous
 
 fn get_mut(&mut self) -> &mut T; // elided
 fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
index d504fab206ddfd185d65c4b6362e5395eb8b7e9b..1317a1490903b435fda848f500d33ce9c5bbd0d2 100644 (file)
@@ -30,8 +30,8 @@ mind.
 
 # Defining a macro
 
-You may have seen the `vec!` macro, used to initialize a [vector][] with any
-number of elements.
+You may have seen the `vec!` macro, used to initialize a [vector][vector] with
+any number of elements.
 
 [vector]: vectors.html
 
@@ -224,7 +224,7 @@ more" match. Both forms optionally include a separator, which can be any token
 except `+` or `*`.
 
 This system is based on
-"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
+"[Macro-by-Example](https://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
 (PDF link).
 
 # Hygiene
@@ -319,7 +319,7 @@ syntax context where it was introduced. It’s as though the variable `state`
 inside `main` is painted a different "color" from the variable `state` inside
 the macro, and therefore they don’t conflict.
 
-[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
+[hygienic macro system]: https://en.wikipedia.org/wiki/Hygienic_macro
 
 This also restricts the ability of macros to introduce new bindings at the
 invocation site. Code such as the following will not work:
@@ -349,7 +349,7 @@ fn main() {
 }
 ```
 
-This holds for `let` bindings and loop labels, but not for [items][].
+This holds for `let` bindings and loop labels, but not for [items][items].
 So the following code does compile:
 
 ```rust
@@ -470,15 +470,15 @@ which syntactic form it matches.
 * `stmt`: a single statement. Example: `let x = 3`.
 * `block`: a brace-delimited sequence of statements. Example:
   `{ log(error, "hi"); return 12; }`.
-* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
+* `item`: an [item][item]. Examples: `fn foo() { }`; `struct Bar;`.
 * `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
 * `tt`: a single token tree.
 
 There are additional rules regarding the next token after a metavariable:
 
-* `expr` variables must be followed by one of: `=> , ;`
-* `ty` and `path` variables must be followed by one of: `=> , : = > as`
-* `pat` variables must be followed by one of: `=> , =`
+* `expr` variables may only be followed by one of: `=> , ;`
+* `ty` and `path` variables may only be followed by one of: `=> , : = > as`
+* `pat` variables may only be followed by one of: `=> , = if in`
 * Other variables may be followed by any token.
 
 These rules provide some flexibility for Rust’s syntax to evolve without
@@ -622,7 +622,7 @@ invocation gives you another opportunity to pattern-match the macro’s
 arguments.
 
 As an extreme example, it is possible, though hardly advisable, to implement
-the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
+the [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
 within Rust’s macro system.
 
 ```rust
@@ -683,9 +683,9 @@ let v = vec![0; 100];
 
 ## assert! and assert_eq!
 
-These two macros are used in tests. `assert!` takes a boolean, and `assert_eq!`
-takes two values and compares them. Truth passes, success `panic!`s. Like
-this:
+These two macros are used in tests. `assert!` takes a boolean. `assert_eq!`
+takes two values and checks them for equality. `true` passes, `false` `panic!`s.
+Like this:
 
 ```rust,no_run
 // A-ok!
@@ -698,6 +698,7 @@ assert_eq!(5, 3 + 2);
 assert!(5 < 3);
 assert_eq!(5, 3);
 ```
+
 ## try!
 
 `try!` is used for error handling. It takes something that can return a
index 1527d9cf978df96af30197592a36ab15f1cd015a..1afa622db7dd39a75d9c93957acca2b4d4da6180 100644 (file)
@@ -4,7 +4,7 @@ Functions are great, but if you want to call a bunch of them on some data, it
 can be awkward. Consider this code:
 
 ```rust,ignore
-baz(bar(foo)));
+baz(bar(foo));
 ```
 
 We would read this left-to right, and so we see ‘baz bar foo’. But this isn’t the
@@ -86,10 +86,10 @@ impl Circle {
 # Chaining method calls
 
 So, now we know how to call a method, such as `foo.bar()`. But what about our
-original example, `foo.bar().baz()`? This is called ‘method chaining’, and we
-can do it by returning `self`.
+original example, `foo.bar().baz()`? This is called ‘method chaining’. Let’s
+look at an example:
 
-```
+```rust
 struct Circle {
     x: f64,
     y: f64,
@@ -117,7 +117,7 @@ fn main() {
 
 Check the return type:
 
-```
+```rust
 # struct Circle;
 # impl Circle {
 fn grow(&self) -> Circle {
@@ -156,7 +156,7 @@ fn main() {
 
 This ‘associated function’ builds a new `Circle` for us. Note that associated
 functions are called with the `Struct::function()` syntax, rather than the
-`ref.method()` syntax. Some other langauges call associated functions ‘static
+`ref.method()` syntax. Some other languages call associated functions ‘static
 methods’.
 
 # Builder Pattern
@@ -167,7 +167,7 @@ and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t
 have method overloading, named arguments, or variable arguments. We employ
 the builder pattern instead. It looks like this:
 
-```
+```rust
 struct Circle {
     x: f64,
     y: f64,
index 7186c65cdf424e0ec291e6c90d8c63e52389b74e..ef569a09e21375904194d7a6bdc9e6aa61cda2e0 100644 (file)
@@ -89,7 +89,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
 > * exactly one mutable reference (`&mut T`)
 
 [ownership]: ownership.html
-[borrowing]: borrowing.html#The-Rules
+[borrowing]: references-and-borrowing.html#borrowing
 
 So, that’s the real definition of ‘immutability’: is this safe to have two
 pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside
@@ -159,9 +159,9 @@ b.x = 10; // error: cannot assign to immutable field `b.x`
 
 [struct]: structs.html
 
-However, by using `Cell<T>`, you can emulate field-level mutability:
+However, by using [`Cell<T>`][cell], you can emulate field-level mutability:
 
-```
+```rust
 use std::cell::Cell;
 
 struct Point {
@@ -176,4 +176,6 @@ point.y.set(7);
 println!("y: {:?}", point.y);
 ```
 
+[cell]: ../std/cell/struct.Cell.html
+
 This will print `y: Cell { value: 7 }`. We’ve successfully updated `y`.
index 2f3055deb04e063dbdc1e12ae97222e90bf2853d..c5aae5afcf57bc5e16b198ea3a89383d6f1d953b 100644 (file)
@@ -26,8 +26,8 @@ $ sh rustup.sh --channel=nightly
 If you're on Windows, please download either the [32-bit installer][win32] or
 the [64-bit installer][win64] and run it.
 
-[win32]: https://static.rust-lang.org/dist/rust-1.0.0-beta-i686-pc-windows-gnu.msi
-[win64]: https://static.rust-lang.org/dist/rust-1.0.0-beta-x86_64-pc-windows-gnu.msi
+[win32]: https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.msi
+[win64]: https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.msi
 
 ## Uninstalling
 
@@ -46,11 +46,11 @@ 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].
+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
-[install page]: http://www.rust-lang.org/install.html
+[from-source]: https://github.com/rust-lang/rust#building-from-source
+[install-page]: http://www.rust-lang.org/install.html
 
 Oh, we should also mention the officially supported platforms:
 
@@ -91,9 +91,9 @@ 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][stack overflow].
+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
 [users]: http://users.rust-lang.org/ 
-[stack overflow]: http://stackoverflow.com/questions/tagged/rust
+[stackoverflow]: http://stackoverflow.com/questions/tagged/rust
index 67db919c59f45a0f9cdf6b0ed9c872ceb3e5f13f..0a985334b5e4b694d797eb673986bc4fdebbbbe2 100644 (file)
@@ -20,7 +20,7 @@ default shim for the C `main` function with your own.
 The function marked `#[start]` is passed the command line parameters
 in the same format as C:
 
-```
+```rust
 #![feature(lang_items, start, no_std, libc)]
 #![no_std]
 
index 0ba2b33759cd518cde8964bcc2bc335f5705dde0..46af311acf31547332961f38c2a980bbf260ee06 100644 (file)
@@ -156,6 +156,46 @@ that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
 But, unlike a move, we can still use `v` afterward. This is because an `i32`
 has no pointers to data somewhere else, copying it is a full copy.
 
+All primitive types implement the `Copy` trait and their ownership is
+therefore not moved like one would assume, following the ´ownership rules´.
+To give an example, the two following snippets of code only compile because the 
+`i32` and `bool` types implement the `Copy` trait. 
+
+```rust
+fn main() {
+    let a = 5;
+
+    let _y = double(a);
+    println!("{}", a);
+}
+
+fn double(x: i32) -> i32 {
+    x * 2
+}
+```
+
+```rust
+fn main() {
+    let a = true;
+
+    let _y = change_truth(a);
+    println!("{}", a);
+}
+
+fn change_truth(x: bool) -> bool {
+    !x
+}
+```
+
+If we would have used types that do not implement the `Copy` trait,
+we would have gotten a compile error because we tried to use a moved value.
+
+```text
+error: use of moved value: `a`
+println!("{}", a);
+               ^
+```
+
 We will discuss how to make your own types `Copy` in the [traits][traits]
 section.
 
index 93df0f19e8eeb087283649842bcb5f64273c3247..7a1f8bf21bf345b735beeade0fcc74994d2b821a 100644 (file)
@@ -154,6 +154,31 @@ match x {
 
 This prints `Got an int!`.
 
+If you’re using `if` with multiple patterns, the `if` applies to both sides:
+
+```rust
+let x = 4;
+let y = false;
+
+match x {
+    4 | 5 if y => println!("yes"),
+    _ => println!("no"),
+}
+```
+
+This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
+just the `5`, In other words, the the precedence of `if` behaves like this:
+
+```text
+(4 | 5) if y => ...
+```
+
+not this:
+
+```text
+4 | (5 if y) => ...
+```
+
 # ref and ref mut
 
 If you want to get a [reference][ref], use the `ref` keyword:
@@ -196,12 +221,27 @@ struct Point {
 let origin = Point { x: 0, y: 0 };
 
 match origin {
-    Point { x: x, y: y } => println!("({},{})", x, y),
+    Point { x, y } => println!("({},{})", x, y),
 }
 ```
 
 [struct]: structs.html
 
+We can use `:` to give a value a different name.
+
+```rust
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+let origin = Point { x: 0, y: 0 };
+
+match origin {
+    Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
+}
+```
+
 If we only care about some of the values, we don’t have to give them all names:
 
 ```rust
@@ -213,7 +253,7 @@ struct Point {
 let origin = Point { x: 0, y: 0 };
 
 match origin {
-    Point { x: x, .. } => println!("x is {}", x),
+    Point { x, .. } => println!("x is {}", x),
 }
 ```
 
@@ -230,7 +270,7 @@ struct Point {
 let origin = Point { x: 0, y: 0 };
 
 match origin {
-    Point { y: y, .. } => println!("y is {}", y),
+    Point { y, .. } => println!("y is {}", y),
 }
 ```
 
index d3bf61434c9e5c75c63f649d9ffe2e2154019c49..027909dd058769c70031e0d32a8424a803c5e58b 100644 (file)
@@ -251,7 +251,7 @@ This pattern is very powerful, and we’ll see it repeated more later.
 You can disambiguate a single-element tuple from a value in parentheses with a
 comma:
 
-```
+```rust
 (0,); // single-element tuple
 (0); // zero in parentheses
 ```
@@ -283,7 +283,7 @@ documentation][tuple].
 
 Functions also have a type! They look like this:
 
-```
+```rust
 fn foo(x: i32) -> i32 { x }
 
 let x: fn(i32) -> i32 = foo;
index 4a37af3c227827f779157a1d2f44dcb54df03126..8a3b98b72927b3303f3146e076084347a327c014 100644 (file)
@@ -52,9 +52,9 @@ println!("raw points at {}", *raw);
 It gives this error:
 
 ```text
-error: dereference of unsafe pointer requires unsafe function or block [E0133]
-     println!("raw points at{}", *raw);
-                                 ^~~~
+error: dereference of raw pointer requires unsafe function or block [E0133]
+     println!("raw points at {}", *raw);
+                                  ^~~~
 ```
 
 When you dereference a raw pointer, you’re taking responsibility that it’s not
@@ -77,7 +77,7 @@ For more operations on raw pointers, see [their API documentation][rawapi].
 # FFI
 
 Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to
-C’s `const T*` and `T*`, respectfully. For more about this use, consult the
+C’s `const T*` and `T*`, respectively. For more about this use, consult the
 [FFI chapter][ffi].
 
 [ffi]: ffi.html
index c434371ce59d319ed4044c15d80440b204fabb35..b27db2ab7bea8c0ac120f59b9d3540ee05269159 100644 (file)
@@ -151,11 +151,11 @@ As it turns out, there are rules.
 
 Here’s the rules about borrowing in Rust:
 
-First, any borrow must last for a smaller scope than the owner. Second, you may
-have one or the other of these two kinds of borrows, but not both at the same
-time:
+First, any borrow must last for a scope no greater than that of the owner.
+Second, you may have one or the other of these two kinds of borrows, but not
+both at the same time:
 
-* 0 to N references (`&T`) to a resource.
+* one or more references (`&T`) to a resource.
 * exactly one mutable reference (`&mut T`)
 
 
@@ -206,7 +206,7 @@ fn main() {
 ^
 ```
 
-In other words, the mutable borow is held through the rest of our example. What
+In other words, the mutable borrow is held through the rest of our example. What
 we want is for the mutable borrow to end _before_ we try to call `println!` and
 make an immutable borrow. In Rust, borrowing is tied to the scope that the
 borrow is valid for. And our scopes look like this:
@@ -297,7 +297,7 @@ We can’t modify `v` because it’s borrowed by the loop.
 References must live as long as the resource they refer to. Rust will check the
 scopes of your references to ensure that this is true.
 
-If Rust didn’t check that this property, we could accidentally use a reference
+If Rust didn’t check this property, we could accidentally use a reference
 which was invalid. For example:
 
 ```rust,ignore
index a1ae50a0c5396565b4298e0f365d3b04078d9740..6129c98259ba4dd5534273ce1d45a9e7334b4261 100644 (file)
@@ -6,24 +6,24 @@ Rust’s greatest strengths: a lack of a substantial runtime.
 As organizations grow, they increasingly rely on a multitude of programming
 languages. Different programming languages have different strengths and
 weaknesses, and a polyglot stack lets you use a particular language where
-its strengths make sense, and use a different language where it’s weak.
+its strengths make sense and a different one where it’s weak.
 
 A very common area where many programming languages are weak is in runtime
 performance of programs. Often, using a language that is slower, but offers
-greater programmer productivity is a worthwhile trade-off. To help mitigate
-this, they provide a way to write some of your system in C, and then call
-the C code as though it were written in the higher-level language. This is
+greater programmer productivity, is a worthwhile trade-off. To help mitigate
+this, they provide a way to write some of your system in C and then call
+that C code as though it were written in the higher-level language. This is
 called a ‘foreign function interface’, often shortened to ‘FFI’.
 
 Rust has support for FFI in both directions: it can call into C code easily,
 but crucially, it can also be called _into_ as easily as C. Combined with
 Rust’s lack of a garbage collector and low runtime requirements, this makes
 Rust a great candidate to embed inside of other languages when you need
-some extra oomph.
+that extra oomph.
 
 There is a whole [chapter devoted to FFI][ffi] and its specifics elsewhere in
 the book, but in this chapter, we’ll examine this particular use-case of FFI,
-with three examples, in Ruby, Python, and JavaScript.
+with examples in Ruby, Python, and JavaScript.
 
 [ffi]: ffi.html
 
@@ -40,18 +40,18 @@ optimizations can stack allocate particular numbers, but rather than relying
 on an optimizer to do its job, we may want to ensure that we’re always using
 primitive number types rather than some sort of object type.
 
-Second, many languages have a ‘global interpreter lock’, which limits
+Second, many languages have a ‘global interpreter lock’ (GIL), which limits
 concurrency in many situations. This is done in the name of safety, which is
 a positive effect, but it limits the amount of work that can be done at the
 same time, which is a big negative.
 
 To emphasize these two aspects, we’re going to create a little project that
-uses these two aspects heavily. Since the focus of the example is the embedding
-of Rust into the languages, rather than the problem itself, we’ll just use a
+uses these two aspects heavily. Since the focus of the example is to embed
+Rust into other languages, rather than the problem itself, we’ll just use a
 toy example:
 
 > Start ten threads. Inside each thread, count from one to five million. After
-> All ten threads are finished, print out ‘done!’.
+> all ten threads are finished, print out ‘done!’.
 
 I chose five million based on my particular computer. Here’s an example of this
 code in Ruby:
@@ -66,10 +66,14 @@ threads = []
     5_000_000.times do
       count += 1
     end
+
+    count
   end
 end
 
-threads.each {|t| t.join }
+threads.each do |t|
+  puts "Thread finished with count=#{t.value}"
+end
 puts "done!"
 ```
 
@@ -82,12 +86,12 @@ sort of process monitoring tool, like `top`, I can see that it only uses one
 core on my machine. That’s the GIL kicking in.
 
 While it’s true that this is a synthetic program, one can imagine many problems
-that are similar to this in the real world. For our purposes, spinning up some
+that are similar to this in the real world. For our purposes, spinning up a few
 busy threads represents some sort of parallel, expensive computation.
 
 # A Rust library
 
-Let’s re-write this problem in Rust. First, let’s make a new project with
+Let’s rewrite this problem in Rust. First, let’s make a new project with
 Cargo:
 
 ```bash
@@ -103,55 +107,31 @@ use std::thread;
 fn process() {
     let handles: Vec<_> = (0..10).map(|_| {
         thread::spawn(|| {
-            let mut _x = 0;
-            for _ in (0..5_000_001) {
-                _x += 1
+            let mut x = 0;
+            for _ in (0..5_000_000) {
+                x += 1
             }
+           x
         })
     }).collect();
 
     for h in handles {
-        h.join().ok().expect("Could not join a thread!");
+        println!("Thread finished with count={}",
+           h.join().map_err(|_| "Could not join a thread!").unwrap());
     }
+    println!("done!");
 }
 ```
 
 Some of this should look familiar from previous examples. We spin up ten
 threads, collecting them into a `handles` vector. Inside of each thread, we
-loop five million times, and add one to `_x` each time. Why the underscore?
-Well, if we remove it and compile:
-
-```bash
-$ cargo build
-   Compiling embed v0.1.0 (file:///home/steve/src/embed)
-src/lib.rs:3:1: 16:2 warning: function is never used: `process`, #[warn(dead_code)] on by default
-src/lib.rs:3 fn process() {
-src/lib.rs:4     let handles: Vec<_> = (0..10).map(|_| {
-src/lib.rs:5         thread::spawn(|| {
-src/lib.rs:6             let mut x = 0;
-src/lib.rs:7             for _ in (0..5_000_001) {
-src/lib.rs:8                 x += 1
-             ...
-src/lib.rs:6:17: 6:22 warning: variable `x` is assigned to, but never used, #[warn(unused_variables)] on by default
-src/lib.rs:6             let mut x = 0;
-                             ^~~~~
-```
-
-That first warning is because we are building a library. If we had a test
-for this function, the warning would go away. But for now, it’s never
-called.
-
-The second is related to `x` versus `_x`. Because we never actually _do_
-anything with `x`, we get a warning about it. In our case, that’s perfectly
-okay, as we’re just trying to waste CPU cycles. Prefixing `x` with the
-underscore removes the warning.
-
-Finally, we join on each thread.
+loop five million times, and add one to `x` each time. Finally, we join on
+each thread.
 
 Right now, however, this is a Rust library, and it doesn’t expose anything
 that’s callable from C. If we tried to hook this up to another language right
 now, it wouldn’t work. We only need to make two small changes to fix this,
-though. The first is modify the beginning of our code:
+though. The first is to modify the beginning of our code:
 
 ```rust,ignore
 #[no_mangle]
@@ -161,7 +141,7 @@ pub extern fn process() {
 We have to add a new attribute, `no_mangle`. When you create a Rust library, it
 changes the name of the function in the compiled output. The reasons for this
 are outside the scope of this tutorial, but in order for other languages to
-know how to call the function, we need to not do that. This attribute turns
+know how to call the function, we can’t do that. This attribute turns
 that behavior off.
 
 The other change is the `pub extern`. The `pub` means that this function should
@@ -178,7 +158,7 @@ crate-type = ["dylib"]
 ```
 
 This tells Rust that we want to compile our library into a standard dynamic
-library. By default, Rust compiles into an ‘rlib’, a Rust-specific format.
+library. By default, Rust compiles an ‘rlib’, a Rust-specific format.
 
 Let’s build the project now:
 
@@ -204,7 +184,7 @@ Now that we’ve got our Rust library built, let’s use it from our Ruby.
 
 # Ruby
 
-Open up a `embed.rb` file inside of our project, and do this:
+Open up an `embed.rb` file inside of our project, and do this:
 
 ```ruby
 require 'ffi'
@@ -217,7 +197,7 @@ end
 
 Hello.process
 
-puts "done!”
+puts 'done!'
 ```
 
 Before we can run this, we need to install the `ffi` gem:
@@ -241,7 +221,7 @@ done!
 $
 ```
 
-Whoah, that was fast! On my system, this took `0.086` seconds, rather than
+Whoa, that was fast! On my system, this took `0.086` seconds, rather than
 the two seconds the pure Ruby version took. Let’s break down this Ruby
 code:
 
@@ -258,11 +238,11 @@ module Hello
   ffi_lib 'target/release/libembed.so'
 ```
 
-The `ffi` gem’s authors recommend using a module to scope the functions
-we’ll import from the shared library. Inside, we `extend` the necessary
-`FFI::Library` module, and then call `ffi_lib` to load up our shared
-object library. We just pass it the path that our library is stored,
-which as we saw before, is `target/release/libembed.so`.
+The `Hello` module is used to attach the native functions from the shared
+library. Inside, we `extend` the necessary `FFI::Library` module and then call
+`ffi_lib` to load up our shared object library. We just pass it the path that
+our library is stored, which, as we saw before, is
+`target/release/libembed.so`.
 
 ```ruby
 attach_function :process, [], :void
@@ -280,10 +260,10 @@ Hello.process
 
 This is the actual call into Rust. The combination of our `module`
 and the call to `attach_function` sets this all up. It looks like
-a Ruby function, but is actually Rust!
+a Ruby function but is actually Rust!
 
 ```ruby
-puts "done!"
+puts 'done!'
 ```
 
 Finally, as per our project’s requirements, we print out `done!`.
@@ -329,7 +309,7 @@ After that installs, we can use it:
 var ffi = require('ffi');
 
 var lib = ffi.Library('target/release/libembed', {
-  'process': [ 'void', []  ]
+  'process': ['void', []]
 });
 
 lib.process();
@@ -340,7 +320,7 @@ console.log("done!");
 It looks more like the Ruby example than the Python example. We use
 the `ffi` module to get access to `ffi.Library()`, which loads up
 our shared object. We need to annotate the return type and argument
-types of the function, which are 'void' for return, and an empty
+types of the function, which are `void` for return and an empty
 array to signify no arguments. From there, we just call it and
 print the result.
 
index 61a6ec3eb3f4d2e3f770dc53a7638a0c2b62b2b1..7d5c43ea14c03cc6bace35702e5a67586b89c0d6 100644 (file)
@@ -16,11 +16,11 @@ Rust has two main types of strings: `&str` and `String`. Let’s talk about
 `&'static str`:
 
 ```rust
-let string = "Hello there."; // string: &'static str
+let greeting = "Hello there."; // greeting: &'static str
 ```
 
 This string is statically allocated, meaning that it’s saved inside our
-compiled program, and exists for the entire duration it runs. The `string`
+compiled program, and exists for the entire duration it runs. The `greeting`
 binding is a reference to this statically allocated string. String slices
 have a fixed size, and cannot be mutated.
 
@@ -38,7 +38,7 @@ println!("{}", s);
 
 `String`s will coerce into `&str` with an `&`:
 
-```
+```rust
 fn takes_slice(slice: &str) {
     println!("Got: {}", slice);
 }
@@ -49,6 +49,20 @@ fn main() {
 }
 ```
 
+This coercion does not happen for functions that accept one of `&str`’s traits
+instead of `&str`. For example, [`TcpStream::connect`][connect] has a parameter
+of type `ToSocketAddrs`. A `&str` is okay but a `String` must be explicitly
+converted using `&*`.
+
+```rust,no_run
+use std::net::TcpStream;
+
+TcpStream::connect("192.168.0.1:3000"); // &str parameter
+
+let addr_string = "192.168.0.1:3000".to_string();
+TcpStream::connect(&*addr_string); // convert addr_string to &str
+```
+
 Viewing a `String` as a `&str` is cheap, but converting the `&str` to a
 `String` involves allocating memory. No reason to do that unless you have to!
 
@@ -103,6 +117,30 @@ let dog = hachiko.chars().nth(1); // kinda like hachiko[1]
 
 This emphasizes that we have to go through the whole list of `chars`.
 
+## Slicing
+
+You can get a slice of a string with slicing syntax:
+
+```rust
+let dog = "hachiko";
+let hachi = &dog[0..5];
+```
+
+But note that these are _byte_ offsets, not _character_ offsets. So
+this will fail at runtime:
+
+```rust,should_panic
+let dog = "忠犬ハチ公";
+let hachi = &dog[0..2];
+```
+
+with this error:
+
+```text
+thread '<main>' panicked at 'index 0 and/or 2 in `忠犬ハチ公` do not lie on
+character boundary'
+```
+
 ## Concatenation
 
 If you have a `String`, you can concatenate a `&str` to the end of it:
@@ -123,7 +161,8 @@ let world = "world!".to_string();
 let hello_world = hello + &world;
 ```
 
-This is because `&String` can automatically coerece to a `&str`. This is a
+This is because `&String` can automatically coerce to a `&str`. This is a
 feature called ‘[`Deref` coercions][dc]’.
 
 [dc]: deref-coercions.html
+[connect]: ../std/net/struct.TcpStream.html#method.connect
index 45f87a6740597c6ac892c8732b3df881b16d7b42..759543140b5769fd65925aa3785d1cc98ad49846 100644 (file)
@@ -195,7 +195,7 @@ parameter can be added to the `should_panic` attribute. The test harness will
 make sure that the failure message contains the provided text. A safer version
 of the example above would be:
 
-```
+```rust
 #[test]
 #[should_panic(expected = "assertion failed")]
 fn it_works() {
@@ -205,7 +205,7 @@ fn it_works() {
 
 That's all there is to the basics! Let's write one 'real' test:
 
-```{rust,ignore}
+```rust,ignore
 pub fn add_two(a: i32) -> i32 {
     a + 2
 }
@@ -225,7 +225,7 @@ There is one way in which our existing example is not idiomatic: it's
 missing the `tests` module. The idiomatic way of writing our example
 looks like this:
 
-```{rust,ignore}
+```rust,ignore
 pub fn add_two(a: i32) -> i32 {
     a + 2
 }
@@ -253,7 +253,7 @@ we need to bring our test function into scope. This can be annoying if you have
 a large module, and so this is a common use of the `glob` feature. Let's change
 our `src/lib.rs` to make use of it:
 
-```{rust,ignore}
+```rust,ignore
 
 pub fn add_two(a: i32) -> i32 {
     a + 2
@@ -302,7 +302,7 @@ the `tests` directory
 To write an integration test, let's make a `tests` directory, and
 put a `tests/lib.rs` file inside, with this as its contents:
 
-```{rust,ignore}
+```rust,ignore
 extern crate adder;
 
 #[test]
@@ -359,7 +359,7 @@ documentation has been written. To this end, Rust supports automatically
 running examples in your documentation. Here's a fleshed-out `src/lib.rs`
 with examples:
 
-```{rust,ignore}
+```rust,ignore
 //! The `adder` crate provides functions that add numbers to other numbers.
 //!
 //! # Examples
index c47dbd9789354ec60cc2886ec150cda60ef331bc..2c5f5927fd15a9da964ed956359eb0d5f789e319 100644 (file)
@@ -277,9 +277,9 @@ allocated on the heap:
 | 0       | x    | ?????? |
 
 [drop]: drop.html
-[moving]: We can make the memory live longer by transferring ownership,
-          sometimes called ‘moving out of the box’. More complex examples will
-          be covered later.
+[^moving]: We can make the memory live longer by transferring ownership,
+           sometimes called ‘moving out of the box’. More complex examples will
+           be covered later.
 
 
 And then the stack frame goes away, freeing all of our memory.
@@ -454,7 +454,7 @@ At the end of `bar()`, it calls `baz()`:
 | (2<sup>30</sup>) - 1 |      | 5                    |
 | ...                  | ...  | ...                  |
 | 12                   | g    | 100                  |
-| 11                   | f    | 4                    |
+| 11                   | f    | 9                    |
 | 10                   | e    | 9                    |
 | 9                    | d    | (2<sup>30</sup>) - 1 |
 | 8                    | c    | 5                    |
index c01129057418cf1af9db4d73fb37ed52d4133f19..f9dbc143c82852ef046c9f61f5c138e3dbd136b0 100644 (file)
@@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
 ```
 
 The `destructor` field in each vtable points to a function that will clean up
-any resources of the vtable’s type, for `u8` it is trivial, but for `String` it
+any resources of the vtable’s type: for `u8` it is trivial, but for `String` it
 will free the memory. This is necessary for owning trait objects like
 `Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
 internal type when they go out of scope. The `size` and `align` fields store
@@ -270,7 +270,7 @@ essentially unused at the moment since the information is embedded in the
 destructor, but will be used in the future, as trait objects are progressively
 made more flexible.
 
-Suppose we’ve got some values that implement `Foo`, then the explicit form of
+Suppose we’ve got some values that implement `Foo`. The explicit form of
 construction and use of `Foo` trait objects might look a bit like (ignoring the
 type mismatches: they’re all just pointers anyway):
 
@@ -300,7 +300,3 @@ let y = TraitObject {
 // y.method();
 (y.vtable.method)(y.data);
 ```
-
-If `b` or `y` were owning trait objects (`Box<Foo>`), there would be a
-`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of
-scope.
index 51ee4bf0cdc2833f1285d89bb4f118f3d7c0b751..687e2bbf00e783f7d0a1c8c12421eddd3867e00d 100644 (file)
@@ -1,5 +1,8 @@
 % Traits
 
+A trait is a language feature that tells the Rust compiler about
+functionality a type must provide.
+
 Do you remember the `impl` keyword, used to call a function with [method
 syntax][methodsyntax]?
 
@@ -45,7 +48,7 @@ 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`.
 
 We can use traits to constrain our generics. Consider this function, which
-does not compile, and gives us a similar error:
+does not compile:
 
 ```rust,ignore
 fn print_area<T>(shape: T) {
@@ -56,7 +59,7 @@ fn print_area<T>(shape: T) {
 Rust complains:
 
 ```text
-error: type `T` does not implement any method in scope named `area`
+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`
@@ -146,7 +149,7 @@ print_area(5);
 We get a compile-time error:
 
 ```text
-error: failed to find an implementation of trait main::HasArea for int
+error: the trait `HasArea` is not implemented for the type `_` [E0277]
 ```
 
 So far, we’ve only added trait implementations to structs, but you can
@@ -183,7 +186,8 @@ won’t have its methods:
 
 ```rust,ignore
 let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt");
-let result = f.write("whatever".as_bytes());
+let buf = b"whatever"; // byte string literal. buf: &[u8; 8]
+let result = f.write(buf);
 # result.unwrap(); // ignore the error
 ```
 
@@ -191,9 +195,8 @@ Here’s the error:
 
 ```text
 error: type `std::fs::File` does not implement any method in scope named `write`
-
-let result = f.write(b"whatever");
-               ^~~~~~~~~~~~~~~~~~
+let result = f.write(buf);
+               ^~~~~~~~~~
 ```
 
 We need to `use` the `Write` trait first:
@@ -202,19 +205,20 @@ We need to `use` the `Write` trait first:
 use std::io::Write;
 
 let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt");
-let result = f.write("whatever".as_bytes());
+let buf = b"whatever";
+let result = f.write(buf);
 # result.unwrap(); // ignore the error
 ```
 
 This will compile without error.
 
-This means that even if someone does something bad like add methods to `int`,
+This means that even if someone does something bad like add methods to `i32`,
 it won’t affect you, unless you `use` that trait.
 
-There’s one more restriction on implementing traits. Either the trait or the
-type you’re writing the `impl` for must be defined by you. So, we could
+There’s one more restriction on implementing traits: either the trait, or the
+type you’re writing the `impl` for, must be defined by you. So, we could
 implement the `HasArea` type for `i32`, because `HasArea` is in our code. But
-if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could
+if we tried to implement `ToString`, a trait provided by Rust, for `i32`, we could
 not, because neither the trait nor the type are in our code.
 
 One last thing about traits: generic functions with a trait bound use
@@ -252,7 +256,7 @@ Writing functions with only a few generic types and a small number of trait
 bounds isn’t too bad, but as the number increases, the syntax gets increasingly
 awkward:
 
-```
+```rust
 use std::fmt::Debug;
 
 fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
@@ -267,7 +271,7 @@ far right. The bounds are getting in the way.
 
 Rust has a solution, and it’s called a ‘`where` clause’:
 
-```
+```rust
 use std::fmt::Debug;
 
 fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
@@ -284,7 +288,7 @@ fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
 
 fn main() {
     foo("Hello", "world");
-    bar("Hello", "workd");
+    bar("Hello", "world");
 }
 ```
 
@@ -293,7 +297,7 @@ All you need to do is leave off the bounds when defining your type parameters,
 and then add `where` after the parameter list. For longer lists, whitespace can
 be added:
 
-```
+```rust
 use std::fmt::Debug;
 
 fn bar<T, K>(x: T, y: K)
@@ -310,7 +314,7 @@ This flexibility can add clarity in complex situations.
 
 `where` is also more powerful than the simpler syntax. For example:
 
-```
+```rust
 trait ConvertTo<Output> {
     fn convert(&self) -> Output;
 }
@@ -328,7 +332,7 @@ fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
 fn inverse<T>() -> T
         // this is using ConvertTo as if it were "ConvertFrom<i32>"
         where i32: ConvertTo<T> {
-    1i32.convert()
+    42.convert()
 }
 ```
 
index 6170bdb86eaa3a7843dc89af9a47260395cdb778..d8b894a2f6522ba45b78b6debf369e3b4edbd587 100644 (file)
@@ -16,7 +16,7 @@ this is just convention.)
 
 There’s an alternate form of `vec!` for repeating an initial value:
 
-```
+```rust
 let v = vec![0; 10]; // ten zeroes
 ```
 
index a56c546b5516f1584f5c77f41b2fdded3924889c..0f5c3c64a4b17e1665b9b0a7d0941360e684785e 100644 (file)
@@ -2,7 +2,7 @@
 
 Rust also has a `while` loop. It looks like this:
 
-```{rust}
+```rust
 let mut x = 5; // mut x: i32
 let mut done = false; // mut done: bool
 
index 855d89bc8a35eb42771d73cd8ee000fc23c6d285..cbb67014e276025f4e3e3eb1473cbf642ff8a67f 100644 (file)
@@ -17,6 +17,7 @@ extern crate serialize as rustc_serialize;
 use std::collections::BTreeMap;
 use std::fs::{read_dir, File};
 use std::io::{Read, Write};
+use std::env;
 use std::path::Path;
 use std::error::Error;
 
@@ -73,7 +74,7 @@ r##"<!DOCTYPE html>
 
     try!(write!(&mut output_file, "<h1>Rust Compiler Error Index</h1>\n"));
 
-    for (err_code, info) in err_map.iter() {
+    for (err_code, info) in err_map {
         // Enclose each error in a div so they can be shown/hidden en masse.
         let desc_desc = match info.description {
             Some(_) => "error-described",
@@ -106,7 +107,8 @@ r##"<!DOCTYPE html>
 }
 
 fn main_with_result() -> Result<(), Box<Error>> {
-    let metadata_dir = get_metadata_dir();
+    let build_arch = try!(env::var("CFG_BUILD"));
+    let metadata_dir = get_metadata_dir(&build_arch);
     let err_map = try!(load_all_errors(&metadata_dir));
     try!(render_error_page(&err_map, Path::new("doc/error-index.html")));
     Ok(())
diff --git a/src/etc/2014-06-rewrite-bytes-macros.py b/src/etc/2014-06-rewrite-bytes-macros.py
deleted file mode 100755 (executable)
index 73ddfcb..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-
-import sys
-import subprocess
-import re
-
-
-def main():
-    if len(sys.argv) <= 1:
-        print('Usage: %s [ --apply ] filename1.rs filename2.rs ...'
-              % sys.argv[0])
-    elif sys.argv[1] == '--apply':
-        for filename in sys.argv[2:]:
-            patch(filename)
-    else:
-        for filename in sys.argv[1:]:
-            diff(filename)
-
-
-def patch(filename):
-    source = read(filename)
-    rewritten = rewrite_bytes_macros(source)
-    if rewritten is not None and rewritten != source:
-        write(filename, rewritten)
-
-
-def diff(filename):
-    rewritten = rewrite_bytes_macros(read(filename))
-    if rewritten is not None:
-        p = subprocess.Popen(['diff', '-u', filename, '-'],
-                             stdin=subprocess.PIPE)
-        p.stdin.write(rewritten)
-        p.stdin.close()
-        p.wait()
-
-
-def read(filename):
-    with open(filename, 'rb') as f:
-        return f.read()
-
-
-def write(filename, content):
-    with open(filename, 'wb') as f:
-        f.write(content)
-
-
-def rewrite_bytes_macros(source):
-    rewritten, num_occurrences = BYTES_MACRO_RE.subn(rewrite_one_macro, source)
-    if num_occurrences > 0:
-        return rewritten
-
-
-BYTES_MACRO_RE = re.compile(br'bytes!\(  (?P<args>  [^)]*  )  \)', re.VERBOSE)
-
-
-def rewrite_one_macro(match):
-    try:
-        bytes = parse_bytes(split_args(match.group('args')))
-        return b'b"' + b''.join(map(escape, bytes)) + b'"'
-    except SkipThisRewrite:
-        print('Skipped: %s' % match.group(0).decode('utf8', 'replace'))
-        return match.group(0)
-
-
-class SkipThisRewrite(Exception):
-    pass
-
-
-def split_args(args):
-    previous = b''
-    for arg in args.split(b','):
-        if previous:
-            arg = previous + b',' + arg
-        if arg.count(b'"') % 2 == 0:
-            yield arg
-            previous = b''
-        else:
-            previous = arg
-    if previous:
-        yield previous
-
-
-def parse_bytes(args):
-    for arg in args:
-        arg = arg.strip()
-        if (arg.startswith(b'"') and arg.endswith(b'"')) or (
-                arg.startswith(b"'") and arg.endswith(b"'")):
-            # Escaped newline means something different in Rust and Python.
-            if b'\\\n' in arg:
-                raise SkipThisRewrite
-            for byte in eval(b'u' + arg).encode('utf8'):
-                yield ord(byte)
-        else:
-            if arg.endswith(b'u8'):
-                arg = arg[:-2]
-            # Assume that all Rust integer literals
-            # are valid Python integer literals
-            value = int(eval(arg))
-            assert value <= 0xFF
-            yield value
-
-
-def escape(byte):
-    c = chr(byte)
-    escaped = {
-        b'\0': br'\0',
-        b'\t': br'\t',
-        b'\n': br'\n',
-        b'\r': br'\r',
-        b'\'': b'\\\'',
-        b'\\': br'\\',
-    }.get(c)
-    if escaped is not None:
-        return escaped
-    elif b' ' <= c <= b'~':
-        return chr(byte)
-    else:
-        return ('\\x%02X' % byte).encode('ascii')
-
-
-if str is not bytes:
-    # Python 3.x
-    ord = lambda x: x
-    chr = lambda x: bytes([x])
-
-
-if __name__ == '__main__':
-    main()
diff --git a/src/etc/add-authors.sh b/src/etc/add-authors.sh
new file mode 100644 (file)
index 0000000..917053c
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# 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.
+
+# This script, invoked e.g. "add-authors.sh 1.0.0..rust-lang/master",
+# will merge new authors into AUTHORS.txt, obeying the mailmap
+# file.
+#
+# After running this script, run `git diff` to manually inspect
+# changes. If there are incorrect additions fix it by editing
+# .mailmap and re-running the script.
+
+set -u -e
+
+range="$1"
+
+authors_file="./AUTHORS.txt"
+tmp_file="./AUTHORS.txt.tmp"
+old_authors="$(cat "$authors_file" | tail -n +2 | sed "/^$/d" | sort)"
+new_authors="$(git log "$range" --format="%aN <%aE>" | sort | uniq)"
+
+echo "Rust was written by these fine people:\n" > "$tmp_file"
+echo "$old_authors\n$new_authors" | sort | uniq >> "$tmp_file"
+mv -f "$tmp_file" "$authors_file"
index fc8ed7b383ec5943f7852534e636e3e43d6ca6ad..0e103fbcffbad6a0fb1b2f34044b0887200519c8 100644 (file)
 # except according to those terms.
 
 import os
+import subprocess
 import sys
 import functools
 
 STATUS = 0
 
-
 def error_unless_permitted(env_var, message):
     global STATUS
     if not os.getenv(env_var):
         sys.stderr.write(message)
         STATUS = 1
 
-
 def only_on(platforms):
     def decorator(func):
         @functools.wraps(func)
@@ -33,8 +32,7 @@ def only_on(platforms):
         return inner
     return decorator
 
-
-@only_on(('linux', 'darwin', 'freebsd', 'openbsd'))
+@only_on(['linux', 'darwin', 'freebsd', 'openbsd'])
 def check_rlimit_core():
     import resource
     soft, hard = resource.getrlimit(resource.RLIMIT_CORE)
@@ -45,8 +43,14 @@ will segfault many rustc's, creating many potentially large core files.
 set ALLOW_NONZERO_RLIMIT_CORE to ignore this warning
 """ % (soft))
 
+@only_on(['win32'])
+def check_console_code_page():
+    if '65001' not in subprocess.check_output(['cmd', '/c', 'chcp']):
+        sys.stderr.write('Warning: the console output code page is not UTF-8, \
+some tests may fail. Use `cmd /c "chcp 65001"` to setup UTF-8 code page.\n')
 
 def main():
+    check_console_code_page()
     check_rlimit_core()
 
 if __name__ == '__main__':
index 917e1970a36c068928d1ca6695b5be099c210ec5..9312b685c14a2b5dc79d1aacfd31ad11e9901713 100755 (executable)
@@ -34,7 +34,7 @@ if __name__ == '__main__':
             summaries.append((fname, summary))
 
     def count(t):
-        return sum(map(lambda (f, s): len(s.get(t, [])), summaries))
+        return sum(map(lambda f: len(f[1].get(t, [])), summaries))
 
     logfiles = sys.argv[1:]
     for files in map(glob.glob, logfiles):
@@ -43,15 +43,15 @@ if __name__ == '__main__':
     failed = count('failed')
     ignored = count('ignored')
     measured = count('bench')
-    print "summary of %d test runs: %d passed; %d failed; %d ignored; %d measured" % \
-          (len(logfiles), ok, failed, ignored, measured)
-    print ""
+    print("summary of %d test runs: %d passed; %d failed; %d ignored; %d measured" %
+          (len(logfiles), ok, failed, ignored, measured))
+    print("")
 
     if failed > 0:
-        print "failed tests:"
+        print("failed tests:")
         for f, s in summaries:
             failures = s.get('failed', [])
             if len(failures) > 0:
-                print "  %s:" % (f)
+                print("  %s:" % (f))
             for test in failures:
-                print "    %s" % (test)
+                print("    %s" % (test))
diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py
new file mode 100644 (file)
index 0000000..6e667b3
--- /dev/null
@@ -0,0 +1,328 @@
+# 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 module provides an abstraction layer over common Rust pretty printing
+functionality needed by both GDB and LLDB.
+"""
+
+import re
+
+# Type codes that indicate the kind of type as it appears in DWARF debug
+# information. This code alone is not sufficient to determine the Rust type.
+# For example structs, tuples, fat pointers, or enum variants will all have
+# DWARF_TYPE_CODE_STRUCT.
+DWARF_TYPE_CODE_STRUCT = 1
+DWARF_TYPE_CODE_UNION  = 2
+DWARF_TYPE_CODE_PTR    = 3
+DWARF_TYPE_CODE_ARRAY  = 4
+DWARF_TYPE_CODE_ENUM   = 5
+
+# These constants specify the most specific kind of type that could be
+# determined for a given value.
+TYPE_KIND_UNKNOWN           = -1
+TYPE_KIND_EMPTY             = 0
+TYPE_KIND_SLICE             = 1
+TYPE_KIND_REGULAR_STRUCT    = 2
+TYPE_KIND_TUPLE             = 3
+TYPE_KIND_TUPLE_STRUCT      = 4
+TYPE_KIND_CSTYLE_VARIANT    = 5
+TYPE_KIND_TUPLE_VARIANT     = 6
+TYPE_KIND_STRUCT_VARIANT    = 7
+TYPE_KIND_STR_SLICE         = 8
+TYPE_KIND_STD_VEC           = 9
+TYPE_KIND_STD_STRING        = 10
+TYPE_KIND_REGULAR_ENUM      = 11
+TYPE_KIND_COMPRESSED_ENUM   = 12
+TYPE_KIND_SINGLETON_ENUM    = 13
+TYPE_KIND_CSTYLE_ENUM       = 14
+TYPE_KIND_PTR               = 15
+TYPE_KIND_FIXED_SIZE_VEC    = 16
+
+ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
+ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
+
+# Slice related constants
+SLICE_FIELD_NAME_DATA_PTR = "data_ptr"
+SLICE_FIELD_NAME_LENGTH = "length"
+SLICE_FIELD_NAMES = [SLICE_FIELD_NAME_DATA_PTR, SLICE_FIELD_NAME_LENGTH]
+
+# std::Vec<> related constants
+STD_VEC_FIELD_NAME_DATA_PTR = "ptr"
+STD_VEC_FIELD_NAME_LENGTH = "len"
+STD_VEC_FIELD_NAME_CAPACITY = "cap"
+STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_DATA_PTR,
+                       STD_VEC_FIELD_NAME_LENGTH,
+                       STD_VEC_FIELD_NAME_CAPACITY]
+
+# std::String related constants
+STD_STRING_FIELD_NAMES = ["vec"]
+
+
+class Type(object):
+    """
+    This class provides a common interface for type-oriented operations.
+    Sub-classes are supposed to wrap a debugger-specific type-object and
+    provide implementations for the abstract methods in this class.
+    """
+
+    def __init__(self):
+        self.__type_kind = None
+
+    def get_unqualified_type_name(self):
+        """
+        Implementations of this method should return the unqualified name of the
+        type-object they are wrapping. Some examples:
+
+        'int' -> 'int'
+        'std::vec::Vec<std::string::String>' -> 'Vec<std::string::String>'
+        '&std::option::Option<std::string::String>' -> '&std::option::Option<std::string::String>'
+
+        As you can see, type arguments stay fully qualified.
+        """
+        raise NotImplementedError("Override this method")
+
+    def get_dwarf_type_kind(self):
+        """
+        Implementations of this method should return the correct
+        DWARF_TYPE_CODE_* value for the wrapped type-object.
+        """
+        raise NotImplementedError("Override this method")
+
+    def get_fields(self):
+        """
+        Implementations of this method should return a list of field-objects of
+        this type. For Rust-enums (i.e. with DWARF_TYPE_CODE_UNION) these field-
+        objects represent the variants of the enum. Field-objects must have a
+        `name` attribute that gives their name as specified in DWARF.
+        """
+        assert ((self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT) or
+                (self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION))
+        raise NotImplementedError("Override this method")
+
+    def get_wrapped_value(self):
+        """
+        Returns the debugger-specific type-object wrapped by this object. This
+        is sometimes needed for doing things like pointer-arithmetic in GDB.
+        """
+        raise NotImplementedError("Override this method")
+
+    def get_type_kind(self):
+        """This method returns the TYPE_KIND_* value for this type-object."""
+        if self.__type_kind is None:
+            dwarf_type_code = self.get_dwarf_type_kind()
+
+            if dwarf_type_code == DWARF_TYPE_CODE_STRUCT:
+                self.__type_kind = self.__classify_struct()
+            elif dwarf_type_code == DWARF_TYPE_CODE_UNION:
+                self.__type_kind = self.__classify_union()
+            elif dwarf_type_code == DWARF_TYPE_CODE_PTR:
+                self.__type_kind = TYPE_KIND_PTR
+            elif dwarf_type_code == DWARF_TYPE_CODE_ARRAY:
+                self.__type_kind = TYPE_KIND_FIXED_SIZE_VEC
+            else:
+                self.__type_kind = TYPE_KIND_UNKNOWN
+        return self.__type_kind
+
+    def __classify_struct(self):
+        assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT
+
+        unqualified_type_name = self.get_unqualified_type_name()
+
+        # STR SLICE
+        if unqualified_type_name == "&str":
+            return TYPE_KIND_STR_SLICE
+
+        # REGULAR SLICE
+        if (unqualified_type_name.startswith("&[") and
+            unqualified_type_name.endswith("]") and
+            self.__conforms_to_field_layout(SLICE_FIELD_NAMES)):
+            return TYPE_KIND_SLICE
+
+        fields = self.get_fields()
+        field_count = len(fields)
+
+        # EMPTY STRUCT
+        if field_count == 0:
+            return TYPE_KIND_EMPTY
+
+        # STD VEC
+        if (unqualified_type_name.startswith("Vec<") and
+            self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
+            return TYPE_KIND_STD_VEC
+
+        # STD STRING
+        if (unqualified_type_name.startswith("String") and
+            self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
+            return TYPE_KIND_STD_STRING
+
+        # ENUM VARIANTS
+        if fields[0].name == ENUM_DISR_FIELD_NAME:
+            if field_count == 1:
+                return TYPE_KIND_CSTYLE_VARIANT
+            elif self.__all_fields_conform_to_tuple_field_naming(1):
+                return TYPE_KIND_TUPLE_VARIANT
+            else:
+                return TYPE_KIND_STRUCT_VARIANT
+
+        # TUPLE
+        if self.__all_fields_conform_to_tuple_field_naming(0):
+            if unqualified_type_name.startswith("("):
+                return TYPE_KIND_TUPLE
+            else:
+                return TYPE_KIND_TUPLE_STRUCT
+
+        # REGULAR STRUCT
+        return TYPE_KIND_REGULAR_STRUCT
+
+
+    def __classify_union(self):
+        assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
+
+        union_members = self.get_fields()
+        union_member_count = len(union_members)
+        if union_member_count == 0:
+            return TYPE_KIND_EMPTY
+        elif union_member_count == 1:
+            first_variant_name = union_members[0].name
+            if first_variant_name is None:
+                return TYPE_KIND_SINGLETON_ENUM
+            else:
+                assert first_variant_name.startswith(ENCODED_ENUM_PREFIX)
+                return TYPE_KIND_COMPRESSED_ENUM
+        else:
+            return TYPE_KIND_REGULAR_ENUM
+
+
+    def __conforms_to_field_layout(self, expected_fields):
+        actual_fields = self.get_fields()
+        actual_field_count = len(actual_fields)
+
+        if actual_field_count != len(expected_fields):
+            return False
+
+        for i in range(0, actual_field_count):
+            if actual_fields[i].name != expected_fields[i]:
+                return False
+
+        return True
+
+    def __all_fields_conform_to_tuple_field_naming(self, start_index):
+        fields = self.get_fields()
+        field_count = len(fields)
+
+        for i in range(start_index, field_count):
+            field_name = fields[i].name
+            if (field_name is None) or (re.match(r"__\d+$", field_name) is None):
+                return False
+        return True
+
+
+class Value(object):
+    """
+    This class provides a common interface for value-oriented operations.
+    Sub-classes are supposed to wrap a debugger-specific value-object and
+    provide implementations for the abstract methods in this class.
+    """
+    def __init__(self, ty):
+        self.type = ty
+
+    def get_child_at_index(self, index):
+        """Returns the value of the field, array element or variant at the given index"""
+        raise NotImplementedError("Override this method")
+
+    def as_integer(self):
+        """
+        Try to convert the wrapped value into a Python integer. This should
+        always succeed for values that are pointers or actual integers.
+        """
+        raise NotImplementedError("Override this method")
+
+    def get_wrapped_value(self):
+        """
+        Returns the debugger-specific value-object wrapped by this object. This
+        is sometimes needed for doing things like pointer-arithmetic in GDB.
+        """
+        raise NotImplementedError("Override this method")
+
+
+class EncodedEnumInfo(object):
+    """
+    This class provides facilities for handling enum values with compressed
+    encoding where a non-null field in one variant doubles as the discriminant.
+    """
+
+    def __init__(self, enum_val):
+        assert enum_val.type.get_type_kind() == TYPE_KIND_COMPRESSED_ENUM
+        variant_name = enum_val.type.get_fields()[0].name
+        last_separator_index = variant_name.rfind("$")
+        start_index = len(ENCODED_ENUM_PREFIX)
+        indices_substring = variant_name[start_index:last_separator_index].split("$")
+        self.__enum_val = enum_val
+        self.__disr_field_indices = [int(index) for index in indices_substring]
+        self.__null_variant_name = variant_name[last_separator_index + 1:]
+
+    def is_null_variant(self):
+        ty = self.__enum_val.type
+        sole_variant_val = self.__enum_val.get_child_at_index(0)
+        discriminant_val = sole_variant_val
+        for disr_field_index in self.__disr_field_indices:
+            discriminant_val = discriminant_val.get_child_at_index(disr_field_index)
+
+        # If the discriminant field is a fat pointer we have to consider the
+        # first word as the true discriminant
+        if discriminant_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT:
+            discriminant_val = discriminant_val.get_child_at_index(0)
+
+        return discriminant_val.as_integer() == 0
+
+    def get_non_null_variant_val(self):
+        return self.__enum_val.get_child_at_index(0)
+
+    def get_null_variant_name(self):
+        return self.__null_variant_name
+
+
+def get_discriminant_value_as_integer(enum_val):
+    assert enum_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
+    # we can take any variant here because the discriminant has to be the same
+    # for all of them.
+    variant_val = enum_val.get_child_at_index(0)
+    disr_val = variant_val.get_child_at_index(0)
+    return disr_val.as_integer()
+
+
+def extract_length_ptr_and_cap_from_std_vec(vec_val):
+    assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
+    length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
+    ptr_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_DATA_PTR)
+    cap_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_CAPACITY)
+
+    length = vec_val.get_child_at_index(length_field_index).as_integer()
+    vec_ptr_val = vec_val.get_child_at_index(ptr_field_index)
+    capacity = vec_val.get_child_at_index(cap_field_index).as_integer()
+
+    unique_ptr_val = vec_ptr_val.get_child_at_index(0)
+    data_ptr = unique_ptr_val.get_child_at_index(0)
+    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
+    return (length, data_ptr, capacity)
+
+def extract_length_and_ptr_from_slice(slice_val):
+    assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
+            slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
+
+    length_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_LENGTH)
+    ptr_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_DATA_PTR)
+
+    length = slice_val.get_child_at_index(length_field_index).as_integer()
+    data_ptr = slice_val.get_child_at_index(ptr_field_index)
+
+    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
+    return (length, data_ptr)
index 7b11504f3cd8023b63c4948f7bb2a97f15f54b27..4b1b78da9fde47e412de0cc7bb33426d90199288 100644 (file)
@@ -16,7 +16,7 @@ import os
 import re
 
 if len(sys.argv) < 2:
-    print "usage: errorck.py <src-dir>"
+    print("usage: errorck.py <src-dir>")
     sys.exit(1)
 
 src_dir = sys.argv[1]
index 86fa779cced5fe81f02fb8eb2f417a5c2209955a..e82f00f3e7df53b3fd222c67ac7ffa73375fc529 100644 (file)
 #     since the same version
 #   * Prints information about features
 
-import sys, os, re
+import sys
+import os
+import re
+import codecs
 
 if len(sys.argv) < 2:
-    print "usage: featurkck.py <src-dir>"
+    print("usage: featureck.py <src-dir>")
     sys.exit(1)
 
 src_dir = sys.argv[1]
@@ -47,7 +50,7 @@ with open(feature_gate_source, 'r') as f:
             line = line.replace("(", "").replace("),", "").replace(")", "")
             parts = line.split(",")
             if len(parts) != 3:
-                print "error: unexpected number of components in line: " + original_line
+                print("error: unexpected number of components in line: " + original_line)
                 sys.exit(1)
             feature_name = parts[0].strip().replace('"', "")
             since = parts[1].strip().replace('"', "")
@@ -79,7 +82,7 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
             continue
 
         path = os.path.join(dirpath, filename)
-        with open(path, 'r') as f:
+        with codecs.open(filename=path, mode='r', encoding="utf-8") as f:
             line_num = 0
             for line in f:
                 line_num += 1
@@ -107,9 +110,9 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
                         if not mm is None:
                             since = mm.group(1)
                         else:
-                            print "error: misformed stability attribute"
-                            print "line " + str(line_num) + " of " + path + ":"
-                            print line
+                            print("error: misformed stability attribute")
+                            print("line %d of %:" % (line_num, path))
+                            print(line)
                             errors = True
 
                     lib_features[feature_name] = feature_name
@@ -123,24 +126,24 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
                         (expected_since, source_path, source_line_num, source_line) = \
                             lib_features_and_level.get((feature_name, level))
                         if since != expected_since:
-                            print "error: mismatch in " + level + " feature '" + feature_name + "'"
-                            print "line " + str(source_line_num) + " of " + source_path + ":"
-                            print source_line
-                            print "line " + str(line_num) + " of " + path + ":"
-                            print line
+                            print("error: mismatch in %s feature '%s'" % (level, feature_name))
+                            print("line %d of %s:" % (source_line_num, source_path))
+                            print(source_line)
+                            print("line %d of %s:" % (line_num, path))
+                            print(line)
                             errors = True
 
                     # Verify that this lib feature doesn't duplicate a lang feature
                     if feature_name in language_feature_names:
-                        print "error: lib feature '" + feature_name + "' duplicates a lang feature"
-                        print "line " + str(line_num) + " of " + path + ":"
-                        print line
+                        print("error: lib feature '%s' duplicates a lang feature" % (feature_name))
+                        print("line %d of %s:" % (line_num, path))
+                        print(line)
                         errors = True
 
                 else:
-                    print "error: misformed stability attribute"
-                    print "line " + str(line_num) + " of " + path + ":"
-                    print line
+                    print("error: misformed stability attribute")
+                    print("line %d of %s:" % (line_num, path))
+                    print(line)
                     errors = True
 
 # Merge data about both lists
@@ -175,7 +178,7 @@ for f in lib_features:
     is_unstable = lib_features_and_level.get((name, "unstable")) is not None
 
     if is_stable and is_unstable:
-        print "error: feature '" + name + "' is both stable and unstable"
+        print("error: feature '%s' is both stable and unstable" % (name))
         errors = True
 
     if is_stable:
@@ -192,7 +195,7 @@ merged_stats = { }
 for name in lib_feature_stats:
     if language_feature_stats.get(name) is not None:
         if not name in joint_features:
-            print "error: feature '" + name + "' is both a lang and lib feature but not whitelisted"
+            print("error: feature '%s' is both a lang and lib feature but not whitelisted" % (name))
             errors = True
         lang_status = language_feature_stats[name][3]
         lib_status = lib_feature_stats[name][3]
@@ -200,13 +203,13 @@ for name in lib_feature_stats:
         lib_stable_since = lib_feature_stats[name][4]
 
         if lang_status != lib_status and lib_status != "deprecated":
-            print "error: feature '" + name + "' has lang status " + lang_status + \
-                  " but lib status " + lib_status
+            print("error: feature '%s' has lang status %s " +
+                  "but lib status %s" % (name, lang_status, lib_status))
             errors = True
 
         if lang_stable_since != lib_stable_since:
-            print "error: feature '" + name + "' has lang stable since " + lang_stable_since + \
-                  " but lib stable since " + lib_stable_since
+            print("error: feature '%s' has lang stable since %s " +
+                  "but lib stable since %s" % (name, lang_stable_since, lib_stable_since))
             errors = True
 
         merged_stats[name] = (name, True, True, lang_status, lang_stable_since)
@@ -240,5 +243,5 @@ lines.sort()
 
 print
 for line in lines:
-    print "* " + line
+    print("* " + line)
 print
index fc4d15a5168db5ac561280790c8b9bb2f20c6487..f93f3490215d187ee186719024cadf31f72abdbe 100755 (executable)
 
 import gdb
 import re
+import debugger_pretty_printers_common as rustpp
 
 #===============================================================================
 # GDB Pretty Printing Module for Rust
 #===============================================================================
 
+class GdbType(rustpp.Type):
 
-def register_printers(objfile):
-    "Registers Rust pretty printers for the given objfile"
-    objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
+    def __init__(self, ty):
+        super(GdbType, self).__init__()
+        self.ty = ty
+        self.fields = None
 
+    def get_unqualified_type_name(self):
+        tag = self.ty.tag
 
-def rust_pretty_printer_lookup_function(val):
-    "Returns the correct Rust pretty printer for the given value if there is one"
-    type_code = val.type.code
+        if tag is None:
+            return tag
 
-    if type_code == gdb.TYPE_CODE_STRUCT:
-        struct_kind = classify_struct(val.type)
+        return tag.replace("&'static ", "&")
 
-        if struct_kind == STRUCT_KIND_SLICE:
-            return RustSlicePrinter(val)
+    def get_dwarf_type_kind(self):
+        if self.ty.code == gdb.TYPE_CODE_STRUCT:
+            return rustpp.DWARF_TYPE_CODE_STRUCT
 
-        if struct_kind == STRUCT_KIND_STR_SLICE:
-            return RustStringSlicePrinter(val)
+        if self.ty.code == gdb.TYPE_CODE_UNION:
+            return rustpp.DWARF_TYPE_CODE_UNION
 
-        if struct_kind == STRUCT_KIND_STD_VEC:
-            return RustStdVecPrinter(val)
+        if self.ty.code == gdb.TYPE_CODE_PTR:
+            return rustpp.DWARF_TYPE_CODE_PTR
 
-        if struct_kind == STRUCT_KIND_STD_STRING:
-            return RustStdStringPrinter(val)
+        if self.ty.code == gdb.TYPE_CODE_ENUM:
+            return rustpp.DWARF_TYPE_CODE_ENUM
 
-        if struct_kind == STRUCT_KIND_TUPLE:
-            return RustTuplePrinter(val)
+    def get_fields(self):
+        assert ((self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT) or
+                (self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION))
+        if self.fields is None:
+            self.fields = list(self.ty.fields())
+        return self.fields
 
-        if struct_kind == STRUCT_KIND_TUPLE_STRUCT:
-            return RustTupleStructPrinter(val, False)
+    def get_wrapped_value(self):
+        return self.ty
 
-        if struct_kind == STRUCT_KIND_CSTYLE_VARIANT:
-            return RustCStyleEnumPrinter(val[get_field_at_index(val, 0)])
 
-        if struct_kind == STRUCT_KIND_TUPLE_VARIANT:
-            return RustTupleStructPrinter(val, True)
+class GdbValue(rustpp.Value):
+    def __init__(self, gdb_val):
+        super(GdbValue, self).__init__(GdbType(gdb_val.type))
+        self.gdb_val = gdb_val
+        self.children = {}
 
-        if struct_kind == STRUCT_KIND_STRUCT_VARIANT:
-            return RustStructPrinter(val, True)
+    def get_child_at_index(self, index):
+        child = self.children.get(index)
+        if child is None:
+            gdb_field = get_field_at_index(self.gdb_val, index)
+            child = GdbValue(self.gdb_val[gdb_field])
+            self.children[index] = child
+        return child
 
-        return RustStructPrinter(val, False)
+    def as_integer(self):
+        return int(self.gdb_val)
 
-    # Enum handling
-    if type_code == gdb.TYPE_CODE_UNION:
-        enum_members = list(val.type.fields())
-        enum_member_count = len(enum_members)
+    def get_wrapped_value(self):
+        return self.gdb_val
 
-        if enum_member_count == 0:
-            return RustStructPrinter(val, False)
 
-        if enum_member_count == 1:
-            first_variant_name = enum_members[0].name
-            if first_variant_name is None:
-                # This is a singleton enum
-                return rust_pretty_printer_lookup_function(val[enum_members[0]])
-            else:
-                assert first_variant_name.startswith("RUST$ENCODED$ENUM$")
-                # This is a space-optimized enum.
-                # This means this enum has only two states, and Rust uses one
-                # of the fields somewhere in the struct to determine which of
-                # the two states it's in. The location of the field is encoded
-                # in the name as something like
-                # RUST$ENCODED$ENUM$(num$)*name_of_zero_state
-                last_separator_index = first_variant_name.rfind("$")
-                start_index = len("RUST$ENCODED$ENUM$")
-                disr_field_indices = first_variant_name[start_index:last_separator_index].split("$")
-                disr_field_indices = [int(index) for index in disr_field_indices]
-
-                sole_variant_val = val[enum_members[0]]
-                discriminant = sole_variant_val
-                for disr_field_index in disr_field_indices:
-                    disr_field = get_field_at_index(discriminant, disr_field_index)
-                    discriminant = discriminant[disr_field]
-
-                # If the discriminant field is a fat pointer we have to consider the
-                # first word as the true discriminant
-                if discriminant.type.code == gdb.TYPE_CODE_STRUCT:
-                    discriminant = discriminant[get_field_at_index(discriminant, 0)]
-
-                if discriminant == 0:
-                    null_variant_name = first_variant_name[last_separator_index + 1:]
-                    return IdentityPrinter(null_variant_name)
-
-                return rust_pretty_printer_lookup_function(sole_variant_val)
+def register_printers(objfile):
+    """Registers Rust pretty printers for the given objfile"""
+    objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
 
-        # This is a regular enum, extract the discriminant
-        discriminant_name, discriminant_val = extract_discriminant_value(val)
-        return rust_pretty_printer_lookup_function(val[enum_members[discriminant_val]])
 
-    # No pretty printer has been found
-    return None
+def rust_pretty_printer_lookup_function(gdb_val):
+    """
+    Returns the correct Rust pretty printer for the given value
+    if there is one
+    """
 
-#=------------------------------------------------------------------------------
-# Pretty Printer Classes
-#=------------------------------------------------------------------------------
+    val = GdbValue(gdb_val)
+    type_kind = val.type.get_type_kind()
 
+    if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or
+        type_kind == rustpp.TYPE_KIND_EMPTY):
+        return RustStructPrinter(val,
+                                 omit_first_field = False,
+                                 omit_type_name = False,
+                                 is_tuple_like = False)
 
-class RustStructPrinter:
-    def __init__(self, val, hide_first_field):
-        self.val = val
-        self.hide_first_field = hide_first_field
+    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
+        return RustStructPrinter(val,
+                                 omit_first_field = True,
+                                 omit_type_name = False,
+                                 is_tuple_like = False)
 
-    def to_string(self):
-        return self.val.type.tag
+    if type_kind == rustpp.TYPE_KIND_SLICE:
+        return RustSlicePrinter(val)
 
-    def children(self):
-        cs = []
-        for field in self.val.type.fields():
-            field_name = field.name
-            # Normally the field name is used as a key to access the field
-            # value, because that's also supported in older versions of GDB...
-            field_key = field_name
-            if field_name is None:
-                field_name = ""
-                # ... but for fields without a name (as in tuples), we have to
-                # fall back to the newer method of using the field object
-                # directly as key. In older versions of GDB, this will just
-                # fail.
-                field_key = field
-            name_value_tuple = (field_name, self.val[field_key])
-            cs.append(name_value_tuple)
-
-        if self.hide_first_field:
-            cs = cs[1:]
+    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
+        return RustStringSlicePrinter(val)
 
-        return cs
+    if type_kind == rustpp.TYPE_KIND_STD_VEC:
+        return RustStdVecPrinter(val)
 
+    if type_kind == rustpp.TYPE_KIND_STD_STRING:
+        return RustStdStringPrinter(val)
 
-class RustTuplePrinter:
-    def __init__(self, val):
-        self.val = val
+    if type_kind == rustpp.TYPE_KIND_TUPLE:
+        return RustStructPrinter(val,
+                                 omit_first_field = False,
+                                 omit_type_name = True,
+                                 is_tuple_like = True)
 
-    def to_string(self):
-        return None
+    if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT:
+        return RustStructPrinter(val,
+                                 omit_first_field = False,
+                                 omit_type_name = False,
+                                 is_tuple_like = True)
 
-    def children(self):
-        cs = []
-        for field in self.val.type.fields():
-            cs.append(("", self.val[field]))
+    if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT:
+        return RustCStyleVariantPrinter(val.get_child_at_index(0))
 
-        return cs
+    if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT:
+        return RustStructPrinter(val,
+                                 omit_first_field = True,
+                                 omit_type_name = False,
+                                 is_tuple_like = True)
 
-    def display_hint(self):
-        return "array"
+    if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM:
+        variant = get_field_at_index(gdb_val, 0)
+        return rust_pretty_printer_lookup_function(gdb_val[variant])
 
+    if type_kind == rustpp.TYPE_KIND_REGULAR_ENUM:
+        # This is a regular enum, extract the discriminant
+        discriminant_val = rustpp.get_discriminant_value_as_integer(val)
+        variant = get_field_at_index(gdb_val, discriminant_val)
+        return rust_pretty_printer_lookup_function(gdb_val[variant])
+
+    if type_kind == rustpp.TYPE_KIND_COMPRESSED_ENUM:
+        encoded_enum_info = rustpp.EncodedEnumInfo(val)
+        if encoded_enum_info.is_null_variant():
+            return IdentityPrinter(encoded_enum_info.get_null_variant_name())
 
-class RustTupleStructPrinter:
-    def __init__(self, val, hide_first_field):
-        self.val = val
-        self.hide_first_field = hide_first_field
+        non_null_val = encoded_enum_info.get_non_null_variant_val()
+        return rust_pretty_printer_lookup_function(non_null_val.get_wrapped_value())
+
+    # No pretty printer has been found
+    return None
+
+
+#=------------------------------------------------------------------------------
+# Pretty Printer Classes
+#=------------------------------------------------------------------------------
+class RustStructPrinter:
+    def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like):
+        self.__val = val
+        self.__omit_first_field = omit_first_field
+        self.__omit_type_name = omit_type_name
+        self.__is_tuple_like = is_tuple_like
 
     def to_string(self):
-        return self.val.type.tag
+        if self.__omit_type_name:
+            return None
+        return self.__val.type.get_unqualified_type_name()
 
     def children(self):
         cs = []
-        for field in self.val.type.fields():
-            cs.append(("", self.val[field]))
+        wrapped_value = self.__val.get_wrapped_value()
+
+        for field in self.__val.type.get_fields():
+            field_value = wrapped_value[field.name]
+            if self.__is_tuple_like:
+                cs.append(("", field_value))
+            else:
+                cs.append((field.name, field_value))
 
-        if self.hide_first_field:
+        if self.__omit_first_field:
             cs = cs[1:]
 
         return cs
 
     def display_hint(self):
-        return "array"
+        if self.__is_tuple_like:
+            return "array"
+        else:
+            return ""
+
 
 class RustSlicePrinter:
     def __init__(self, val):
-        self.val = val
+        self.__val = val
 
     def display_hint(self):
         return "array"
 
     def to_string(self):
-        length = int(self.val["length"])
-        return self.val.type.tag + ("(len: %i)" % length)
+        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
+        return (self.__val.type.get_unqualified_type_name() +
+                ("(len: %i)" % length))
 
     def children(self):
         cs = []
-        length = int(self.val["length"])
-        data_ptr = self.val["data_ptr"]
-        assert data_ptr.type.code == gdb.TYPE_CODE_PTR
-        pointee_type = data_ptr.type.target()
+        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
+        assert data_ptr.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
+        raw_ptr = data_ptr.get_wrapped_value()
 
         for index in range(0, length):
-            cs.append((str(index), (data_ptr + index).dereference()))
+            cs.append((str(index), (raw_ptr + index).dereference()))
 
         return cs
 
+
 class RustStringSlicePrinter:
     def __init__(self, val):
-        self.val = val
+        self.__val = val
 
     def to_string(self):
-        slice_byte_len = self.val["length"]
-        return '"%s"' % self.val["data_ptr"].string(encoding="utf-8", length=slice_byte_len)
+        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
+        raw_ptr = data_ptr.get_wrapped_value()
+        return '"%s"' % raw_ptr.string(encoding="utf-8", length=length)
+
 
 class RustStdVecPrinter:
     def __init__(self, val):
-        self.val = val
+        self.__val = val
 
     def display_hint(self):
         return "array"
 
     def to_string(self):
-        length = int(self.val["len"])
-        cap = int(self.val["cap"])
-        return self.val.type.tag + ("(len: %i, cap: %i)" % (length, cap))
+        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val)
+        return (self.__val.type.get_unqualified_type_name() +
+                ("(len: %i, cap: %i)" % (length, cap)))
 
     def children(self):
         cs = []
-        (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val)
-        pointee_type = data_ptr.type.target()
-
+        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val)
+        gdb_ptr = data_ptr.get_wrapped_value()
         for index in range(0, length):
-            cs.append((str(index), (data_ptr + index).dereference()))
+            cs.append((str(index), (gdb_ptr + index).dereference()))
         return cs
 
+
 class RustStdStringPrinter:
     def __init__(self, val):
-        self.val = val
+        self.__val = val
 
     def to_string(self):
-        (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val["vec"])
-        return '"%s"' % data_ptr.string(encoding="utf-8", length=length)
+        vec = self.__val.get_child_at_index(0)
+        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec)
+        return '"%s"' % data_ptr.get_wrapped_value().string(encoding="utf-8",
+                                                            length=length)
 
 
-class RustCStyleEnumPrinter:
+class RustCStyleVariantPrinter:
     def __init__(self, val):
-        assert val.type.code == gdb.TYPE_CODE_ENUM
-        self.val = val
+        assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM
+        self.__val = val
 
     def to_string(self):
-        return str(self.val)
+        return str(self.__val.get_wrapped_value())
 
 
 class IdentityPrinter:
@@ -259,91 +278,11 @@ class IdentityPrinter:
     def to_string(self):
         return self.string
 
-STRUCT_KIND_REGULAR_STRUCT  = 0
-STRUCT_KIND_TUPLE_STRUCT    = 1
-STRUCT_KIND_TUPLE           = 2
-STRUCT_KIND_TUPLE_VARIANT   = 3
-STRUCT_KIND_STRUCT_VARIANT  = 4
-STRUCT_KIND_CSTYLE_VARIANT  = 5
-STRUCT_KIND_SLICE           = 6
-STRUCT_KIND_STR_SLICE       = 7
-STRUCT_KIND_STD_VEC         = 8
-STRUCT_KIND_STD_STRING      = 9
-
-
-def classify_struct(type):
-    # print("\nclassify_struct: tag=%s\n" % type.tag)
-    if type.tag == "&str":
-        return STRUCT_KIND_STR_SLICE
-
-    if type.tag.startswith("&[") and type.tag.endswith("]"):
-        return STRUCT_KIND_SLICE
-
-    fields = list(type.fields())
-    field_count = len(fields)
-
-    if field_count == 0:
-        return STRUCT_KIND_REGULAR_STRUCT
-
-    if (field_count == 3 and
-        fields[0].name == "ptr" and
-        fields[1].name == "len" and
-        fields[2].name == "cap" and
-        type.tag.startswith("Vec<")):
-        return STRUCT_KIND_STD_VEC
-
-    if (field_count == 1 and
-        fields[0].name == "vec" and
-        type.tag == "String"):
-        return STRUCT_KIND_STD_STRING
-
-    if fields[0].name == "RUST$ENUM$DISR":
-        if field_count == 1:
-            return STRUCT_KIND_CSTYLE_VARIANT
-        elif all_fields_conform_to_tuple_field_naming(fields, 1):
-            return STRUCT_KIND_TUPLE_VARIANT
-        else:
-            return STRUCT_KIND_STRUCT_VARIANT
-
-    if all_fields_conform_to_tuple_field_naming(fields, 0):
-        if type.tag.startswith("("):
-            return STRUCT_KIND_TUPLE
-        else:
-            return STRUCT_KIND_TUPLE_STRUCT
 
-    return STRUCT_KIND_REGULAR_STRUCT
-
-
-def extract_discriminant_value(enum_val):
-    assert enum_val.type.code == gdb.TYPE_CODE_UNION
-    for variant_descriptor in enum_val.type.fields():
-        variant_val = enum_val[variant_descriptor]
-        for field in variant_val.type.fields():
-            return (field.name, int(variant_val[field]))
-
-
-def first_field(val):
-    for field in val.type.fields():
-        return field
-
-def get_field_at_index(val, index):
+def get_field_at_index(gdb_val, index):
     i = 0
-    for field in val.type.fields():
+    for field in gdb_val.type.fields():
         if i == index:
             return field
         i += 1
     return None
-
-def all_fields_conform_to_tuple_field_naming(fields, start_index):
-    for i in range(start_index, len(fields)):
-        if (fields[i].name is None) or (re.match(r"__\d+$", fields[i].name) is None):
-            return False
-    return True
-
-def extract_length_and_data_ptr_from_std_vec(vec_val):
-    length = int(vec_val["len"])
-    vec_ptr_val = vec_val["ptr"]
-    unique_ptr_val = vec_ptr_val[first_field(vec_ptr_val)]
-    data_ptr = unique_ptr_val[first_field(unique_ptr_val)]
-    assert data_ptr.type.code == gdb.TYPE_CODE_PTR
-    return (length, data_ptr)
index 2aaa158875817bbca6dd9fe368222d29fa014f95..c22a60abf3f7662be6aa814dc7a27ffb8c25105a 100644 (file)
 
 import lldb
 import re
+import debugger_pretty_printers_common as rustpp
 
-def print_val(val, internal_dict):
-    '''Prints the given value with Rust syntax'''
-    type_class = val.GetType().GetTypeClass()
+#===============================================================================
+# LLDB Pretty Printing Module for Rust
+#===============================================================================
 
-    if type_class == lldb.eTypeClassStruct:
-        return print_struct_val(val, internal_dict)
+class LldbType(rustpp.Type):
 
-    if type_class == lldb.eTypeClassUnion:
-        return print_enum_val(val, internal_dict)
+    def __init__(self, ty):
+        super(LldbType, self).__init__()
+        self.ty = ty
+        self.fields = None
 
-    if type_class == lldb.eTypeClassPointer:
-        return print_pointer_val(val, internal_dict)
+    def get_unqualified_type_name(self):
+        qualified_name = self.ty.GetName()
 
-    if type_class == lldb.eTypeClassArray:
-        return print_fixed_size_vec_val(val, internal_dict)
+        if qualified_name is None:
+            return qualified_name
 
-    return val.GetValue()
+        return extract_type_name(qualified_name).replace("&'static ", "&")
 
+    def get_dwarf_type_kind(self):
+        type_class = self.ty.GetTypeClass()
 
-#=--------------------------------------------------------------------------------------------------
-# Type-Specialized Printing Functions
-#=--------------------------------------------------------------------------------------------------
+        if type_class == lldb.eTypeClassStruct:
+            return rustpp.DWARF_TYPE_CODE_STRUCT
+
+        if type_class == lldb.eTypeClassUnion:
+            return rustpp.DWARF_TYPE_CODE_UNION
+
+        if type_class == lldb.eTypeClassPointer:
+            return rustpp.DWARF_TYPE_CODE_PTR
+
+        if type_class == lldb.eTypeClassArray:
+            return rustpp.DWARF_TYPE_CODE_ARRAY
+
+        if type_class == lldb.eTypeClassEnumeration:
+            return rustpp.DWARF_TYPE_CODE_ENUM
+
+        return None
+
+    def get_fields(self):
+        assert ((self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT) or
+                (self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION))
+        if self.fields is None:
+            self.fields = list(self.ty.fields)
+        return self.fields
+
+    def get_wrapped_value(self):
+        return self.ty
+
+
+class LldbValue(rustpp.Value):
+    def __init__(self, lldb_val):
+        ty = lldb_val.type
+        wty = LldbType(ty)
+        super(LldbValue, self).__init__(wty)
+        self.lldb_val = lldb_val
+        self.children = {}
+
+    def get_child_at_index(self, index):
+        child = self.children.get(index)
+        if child is None:
+            lldb_field = self.lldb_val.GetChildAtIndex(index)
+            child = LldbValue(lldb_field)
+            self.children[index] = child
+        return child
+
+    def as_integer(self):
+        return self.lldb_val.GetValueAsUnsigned()
+
+    def get_wrapped_value(self):
+        return self.lldb_val
+
+
+def print_val(lldb_val, internal_dict):
+    val = LldbValue(lldb_val)
+    type_kind = val.type.get_type_kind()
 
-def print_struct_val(val, internal_dict):
-    '''Prints a struct, tuple, or tuple struct value with Rust syntax'''
-    assert val.GetType().GetTypeClass() == lldb.eTypeClassStruct
+    if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or
+        type_kind == rustpp.TYPE_KIND_EMPTY):
+        return print_struct_val(val,
+                                internal_dict,
+                                omit_first_field = False,
+                                omit_type_name = False,
+                                is_tuple_like = False)
 
-    if is_vec_slice(val):
+    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
+        return print_struct_val(val,
+                                internal_dict,
+                                omit_first_field = True,
+                                omit_type_name = False,
+                                is_tuple_like = False)
+
+    if type_kind == rustpp.TYPE_KIND_SLICE:
         return print_vec_slice_val(val, internal_dict)
-    elif is_std_vec(val):
+
+    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
+        return print_str_slice_val(val, internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_STD_VEC:
         return print_std_vec_val(val, internal_dict)
-    else:
-        return print_struct_val_starting_from(0, val, internal_dict)
 
+    if type_kind == rustpp.TYPE_KIND_STD_STRING:
+        return print_std_string_val(val, internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_TUPLE:
+        return print_struct_val(val,
+                                internal_dict,
+                                omit_first_field = False,
+                                omit_type_name = True,
+                                is_tuple_like = True)
+
+    if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT:
+        return print_struct_val(val,
+                                internal_dict,
+                                omit_first_field = False,
+                                omit_type_name = False,
+                                is_tuple_like = True)
+
+    if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT:
+        return val.type.get_unqualified_type_name()
+
+    if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT:
+        return print_struct_val(val,
+                                internal_dict,
+                                omit_first_field = True,
+                                omit_type_name = False,
+                                is_tuple_like = True)
+
+    if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM:
+        return print_val(lldb_val.GetChildAtIndex(0), internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_PTR:
+        return print_pointer_val(val, internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_FIXED_SIZE_VEC:
+        return print_fixed_size_vec_val(val, internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_REGULAR_ENUM:
+        # This is a regular enum, extract the discriminant
+        discriminant_val = rustpp.get_discriminant_value_as_integer(val)
+        return print_val(lldb_val.GetChildAtIndex(discriminant_val), internal_dict)
+
+    if type_kind == rustpp.TYPE_KIND_COMPRESSED_ENUM:
+        encoded_enum_info = rustpp.EncodedEnumInfo(val)
+        if encoded_enum_info.is_null_variant():
+            return encoded_enum_info.get_null_variant_name()
 
-def print_struct_val_starting_from(field_start_index, val, internal_dict):
+        non_null_val = encoded_enum_info.get_non_null_variant_val()
+        return print_val(non_null_val.get_wrapped_value(), internal_dict)
+
+    # No pretty printer has been found
+    return lldb_val.GetValue()
+
+
+#=--------------------------------------------------------------------------------------------------
+# Type-Specialized Printing Functions
+#=--------------------------------------------------------------------------------------------------
+
+def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tuple_like):
     '''
     Prints a struct, tuple, or tuple struct value with Rust syntax.
     Ignores any fields before field_start_index.
     '''
-    assert val.GetType().GetTypeClass() == lldb.eTypeClassStruct
-
-    t = val.GetType()
-    type_name = extract_type_name(t.GetName())
-    num_children = val.num_children
-
-    if (num_children - field_start_index) == 0:
-        # The only field of this struct is the enum discriminant
-        return type_name
+    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT
 
-    is_tuple_like = type_is_tuple_like(t)
+    if omit_type_name:
+        type_name = ""
+    else:
+        type_name = val.type.get_unqualified_type_name()
 
     if is_tuple_like:
         template = "%(type_name)s(%(body)s)"
@@ -70,20 +189,18 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
         template = "%(type_name)s {\n%(body)s\n}"
         separator = ", \n"
 
-    if type_name.startswith("("):
-        # this is a tuple, so don't print the type name
-        type_name = ""
+    fields = val.type.get_fields()
 
     def render_child(child_index):
         this = ""
         if not is_tuple_like:
-            field_name = t.GetFieldAtIndex(child_index).GetName()
+            field_name = fields[child_index].name
             this += field_name + ": "
 
-        field_val = val.GetChildAtIndex(child_index)
+        field_val = val.get_child_at_index(child_index)
 
-        if not field_val.IsValid():
-            field = t.GetFieldAtIndex(child_index)
+        if not field_val.get_wrapped_value().IsValid():
+            field = fields[child_index]
             # LLDB is not good at handling zero-sized values, so we have to help
             # it a little
             if field.GetType().GetByteSize() == 0:
@@ -91,95 +208,38 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
             else:
                 return this + "<invalid value>"
 
-        return this + print_val(field_val, internal_dict)
+        return this + print_val(field_val.get_wrapped_value(), internal_dict)
+
+    if omit_first_field:
+        field_start_index = 1
+    else:
+        field_start_index = 0
 
-    body = separator.join([render_child(idx) for idx in range(field_start_index, num_children)])
+    body = separator.join([render_child(idx) for idx in range(field_start_index, len(fields))])
 
     return template % {"type_name": type_name,
                        "body": body}
 
-
-def print_enum_val(val, internal_dict):
-    '''Prints an enum value with Rust syntax'''
-
-    assert val.GetType().GetTypeClass() == lldb.eTypeClassUnion
-
-    if val.num_children == 1:
-        # This is either an enum with just one variant, or it is an Option-like
-        # enum where the discriminant is encoded in a non-nullable pointer
-        # field. We find out which one it is by looking at the member name of
-        # the sole union variant. If it starts with "RUST$ENCODED$ENUM$" then
-        # we have an Option-like enum.
-        first_variant_name = val.GetChildAtIndex(0).GetName()
-        if first_variant_name and first_variant_name.startswith("RUST$ENCODED$ENUM$"):
-
-            # This is an Option-like enum. The position of the discriminator field is
-            # encoded in the name which has the format:
-            #  RUST$ENCODED$ENUM$<index of discriminator field>$<name of null variant>
-            last_separator_index = first_variant_name.rfind("$")
-            if last_separator_index == -1:
-                return "<invalid enum encoding: %s>" % first_variant_name
-
-            start_index = len("RUST$ENCODED$ENUM$")
-
-            # Extract indices of the discriminator field
-            try:
-                disr_field_indices = first_variant_name[start_index:last_separator_index].split("$")
-                disr_field_indices = [int(index) for index in disr_field_indices]
-            except:
-                return "<invalid enum encoding: %s>" % first_variant_name
-
-            # Read the discriminant
-            disr_val = val.GetChildAtIndex(0)
-            for index in disr_field_indices:
-                disr_val = disr_val.GetChildAtIndex(index)
-
-            # If the discriminant field is a fat pointer we have to consider the
-            # first word as the true discriminant
-            if disr_val.GetType().GetTypeClass() == lldb.eTypeClassStruct:
-                disr_val = disr_val.GetChildAtIndex(0)
-
-            if disr_val.GetValueAsUnsigned() == 0:
-                # Null case: Print the name of the null-variant
-                null_variant_name = first_variant_name[last_separator_index + 1:]
-                return null_variant_name
-            else:
-                # Non-null case: Interpret the data as a value of the non-null variant type
-                return print_struct_val_starting_from(0, val.GetChildAtIndex(0), internal_dict)
-        else:
-            # This is just a regular uni-variant enum without discriminator field
-            return print_struct_val_starting_from(0, val.GetChildAtIndex(0), internal_dict)
-
-    # If we are here, this is a regular enum with more than one variant
-    disr_val = val.GetChildAtIndex(0).GetChildMemberWithName("RUST$ENUM$DISR")
-    disr_type = disr_val.GetType()
-
-    if disr_type.GetTypeClass() != lldb.eTypeClassEnumeration:
-        return "<Invalid enum value encountered: Discriminator is not an enum>"
-
-    variant_index = disr_val.GetValueAsUnsigned()
-    return print_struct_val_starting_from(1, val.GetChildAtIndex(variant_index), internal_dict)
-
-
 def print_pointer_val(val, internal_dict):
     '''Prints a pointer value with Rust syntax'''
-    assert val.GetType().IsPointerType()
+    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
     sigil = "&"
-    type_name = extract_type_name(val.GetType().GetName())
-    if type_name and type_name[0:1] in ["&", "~", "*"]:
+    type_name = val.type.get_unqualified_type_name()
+    if type_name and type_name[0:1] in ["&", "*"]:
         sigil = type_name[0:1]
 
-    return sigil + hex(val.GetValueAsUnsigned()) #print_val(val.Dereference(), internal_dict)
+    return sigil + hex(val.as_integer())
 
 
 def print_fixed_size_vec_val(val, internal_dict):
-    assert val.GetType().GetTypeClass() == lldb.eTypeClassArray
+    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ARRAY
+    lldb_val = val.get_wrapped_value()
 
     output = "["
 
-    for i in range(val.num_children):
-        output += print_val(val.GetChildAtIndex(i), internal_dict)
-        if i != val.num_children - 1:
+    for i in range(lldb_val.num_children):
+        output += print_val(lldb_val.GetChildAtIndex(i), internal_dict)
+        if i != lldb_val.num_children - 1:
             output += ", "
 
     output += "]"
@@ -187,39 +247,38 @@ def print_fixed_size_vec_val(val, internal_dict):
 
 
 def print_vec_slice_val(val, internal_dict):
-    length = val.GetChildAtIndex(1).GetValueAsUnsigned()
-
-    data_ptr_val = val.GetChildAtIndex(0)
-    data_ptr_type = data_ptr_val.GetType()
-
-    return "&[%s]" % print_array_of_values(val.GetName(),
-                                           data_ptr_val,
+    (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(val)
+    return "&[%s]" % print_array_of_values(val.get_wrapped_value().GetName(),
+                                           data_ptr,
                                            length,
                                            internal_dict)
 
 
 def print_std_vec_val(val, internal_dict):
-    length = val.GetChildAtIndex(1).GetValueAsUnsigned()
-
-    # Vec<> -> Unique<> -> NonZero<> -> *T
-    data_ptr_val = val.GetChildAtIndex(0).GetChildAtIndex(0).GetChildAtIndex(0)
-    data_ptr_type = data_ptr_val.GetType()
-
-    return "vec![%s]" % print_array_of_values(val.GetName(),
-                                              data_ptr_val,
+    (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(val)
+    return "vec![%s]" % print_array_of_values(val.get_wrapped_value().GetName(),
+                                              data_ptr,
                                               length,
                                               internal_dict)
 
+def print_str_slice_val(val, internal_dict):
+    (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(val)
+    return read_utf8_string(data_ptr, length)
+
+def print_std_string_val(val, internal_dict):
+    vec = val.get_child_at_index(0)
+    (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec)
+    return read_utf8_string(data_ptr, length)
+
 #=--------------------------------------------------------------------------------------------------
 # Helper Functions
 #=--------------------------------------------------------------------------------------------------
 
-unqualified_type_markers = frozenset(["(", "[", "&", "*"])
-
+UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"])
 
 def extract_type_name(qualified_type_name):
     '''Extracts the type name from a fully qualified path'''
-    if qualified_type_name[0] in unqualified_type_markers:
+    if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS:
         return qualified_type_name
 
     end_of_search = qualified_type_name.find("<")
@@ -232,72 +291,34 @@ def extract_type_name(qualified_type_name):
     else:
         return qualified_type_name[index + 2:]
 
-
-def type_is_tuple_like(ty):
-    '''Returns true of this is a type with field names (struct, struct-like enum variant)'''
-    for field in ty.fields:
-        if field.GetName() == "RUST$ENUM$DISR":
-            # Ignore the enum discriminant field if there is one.
-            continue
-        if (field.GetName() is None) or (re.match(r"__\d+$", field.GetName()) is None):
-            return False
-    return True
-
-
-def is_vec_slice(val):
-    ty = val.GetType()
-    if ty.GetTypeClass() != lldb.eTypeClassStruct:
-        return False
-
-    if ty.GetNumberOfFields() != 2:
-        return False
-
-    if ty.GetFieldAtIndex(0).GetName() != "data_ptr":
-        return False
-
-    if ty.GetFieldAtIndex(1).GetName() != "length":
-        return False
-
-    type_name = extract_type_name(ty.GetName()).replace("&'static", "&").replace(" ", "")
-    return type_name.startswith("&[") and type_name.endswith("]")
-
-def is_std_vec(val):
-    ty = val.GetType()
-    if ty.GetTypeClass() != lldb.eTypeClassStruct:
-        return False
-
-    if ty.GetNumberOfFields() != 3:
-        return False
-
-    if ty.GetFieldAtIndex(0).GetName() != "ptr":
-        return False
-
-    if ty.GetFieldAtIndex(1).GetName() != "len":
-        return False
-
-    if ty.GetFieldAtIndex(2).GetName() != "cap":
-        return False
-
-    return ty.GetName().startswith("collections::vec::Vec<")
-
-
 def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
     '''Prints a contigous memory range, interpreting it as values of the
        pointee-type of data_ptr_val.'''
 
-    data_ptr_type = data_ptr_val.GetType()
-    assert data_ptr_type.IsPointerType()
+    data_ptr_type = data_ptr_val.type
+    assert data_ptr_type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
 
-    element_type = data_ptr_type.GetPointeeType()
+    element_type = data_ptr_type.get_wrapped_value().GetPointeeType()
     element_type_size = element_type.GetByteSize()
 
-    start_address = data_ptr_val.GetValueAsUnsigned()
+    start_address = data_ptr_val.as_integer()
+    raw_value = data_ptr_val.get_wrapped_value()
 
     def render_element(i):
         address = start_address + i * element_type_size
-        element_val = data_ptr_val.CreateValueFromAddress(array_name + ("[%s]" % i),
-                                                          address,
-                                                          element_type)
+        element_val = raw_value.CreateValueFromAddress(array_name + ("[%s]" % i),
+                                                       address,
+                                                       element_type)
         return print_val(element_val, internal_dict)
 
     return ', '.join([render_element(i) for i in range(length)])
+
+
+def read_utf8_string(ptr_val, byte_count):
+    error = lldb.SBError()
+    process = ptr_val.get_wrapped_value().GetProcess()
+    data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)
+    if error.Success():
+        return '"%s"' % data.decode(encoding='UTF-8')
+    else:
+        return '<error: %s>' % error.GetCString()
diff --git a/src/etc/mklldef.py b/src/etc/mklldef.py
new file mode 100644 (file)
index 0000000..d2f8ee4
--- /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.
+
+import sys
+
+input_file = sys.argv[1]
+output_file = sys.argv[2]
+name = sys.argv[3]
+
+with open(input_file, 'r') as f:
+    with open(output_file, 'w') as g:
+        print >> g, 'LIBRARY ' + name
+        print >> g, 'EXPORTS'
+        for x in f:
+            x = str(x)
+            if not x.startswith('    pub fn LLVM'): continue
+            name = x[11:x.find('(')]
+            print >> g, '  ' + name
index fe9feb3538d15493fb8f425743b053dd4d84058a..7a925fa3f33670ef57bc5acca15b56bd7336d7d5 100644 (file)
@@ -80,10 +80,13 @@ if enable_static == '1':
     assert('stdlib=libc++' not in out)
     f.write("#[link(name = \"stdc++\", 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
+    # right standard library.
     if 'stdlib=libc++' in out:
-        f.write("#[link(name = \"c++\")]\n")
+        f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"c++\"))]\n")
     else:
-        f.write("#[link(name = \"stdc++\")]\n")
+        f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"stdc++\"))]\n")
 
 # Attach everything to an extern block
 f.write("extern {}\n")
index 9a4973f4da8df109d7476ac29c7a7ca50c7ba61b..befb4641396a47922821ff21446a086a582c6236 100644 (file)
Binary files a/src/etc/snapshot.pyc and b/src/etc/snapshot.pyc differ
index c524fae7f0a42e6272ce736cd5d54517702baa11..9f5f919bce8d8c1c315a17b73038cac87f58cf4f 100644 (file)
@@ -81,7 +81,7 @@ check_cr = True
 check_linelength = True
 
 if len(sys.argv) < 2:
-    print "usage: tidy.py <src-dir>"
+    print("usage: tidy.py <src-dir>")
     sys.exit(1)
 
 src_dir = sys.argv[1]
@@ -200,10 +200,10 @@ except UnicodeDecodeError as e:
 
 print
 for ext in sorted(file_counts, key=file_counts.get, reverse=True):
-    print "* linted {} {} files".format(file_counts[ext], ext)
-print "* linted {} other files".format(count_other_linted_files)
-print "* total lines of code: {}".format(count_lines)
-print "* total non-blank lines of code: {}".format(count_non_blank_lines)
-print
+    print("* linted {} {} files".format(file_counts[ext], ext))
+print("* linted {} other files".format(count_other_linted_files))
+print("* total lines of code: {}".format(count_lines))
+print("* total non-blank lines of code: {}".format(count_non_blank_lines))
+print()
 
 sys.exit(err)
index 038a0806fd9fffcdcf79c9356b692da733f14015..f580127cddaf8386515919b10902772a45aacbcf 100755 (executable)
@@ -72,8 +72,9 @@ def is_surrogate(n):
 def load_unicode_data(f):
     fetch(f)
     gencats = {}
-    upperlower = {}
-    lowerupper = {}
+    to_lower = {}
+    to_upper = {}
+    to_title = {}
     combines = {}
     canon_decomp = {}
     compat_decomp = {}
@@ -103,12 +104,16 @@ def load_unicode_data(f):
 
         # generate char to char direct common and simple conversions
         # uppercase to lowercase
-        if gencat == "Lu" and lowcase != "" and code_org != lowcase:
-            upperlower[code] = int(lowcase, 16)
+        if lowcase != "" and code_org != lowcase:
+            to_lower[code] = (int(lowcase, 16), 0, 0)
 
         # lowercase to uppercase
-        if gencat == "Ll" and upcase != "" and code_org != upcase:
-            lowerupper[code] = int(upcase, 16)
+        if upcase != "" and code_org != upcase:
+            to_upper[code] = (int(upcase, 16), 0, 0)
+
+        # title case
+        if titlecase.strip() != "" and code_org != titlecase:
+            to_title[code] = (int(titlecase, 16), 0, 0)
 
         # store decomposition, if given
         if decomp != "":
@@ -144,7 +149,32 @@ def load_unicode_data(f):
     gencats = group_cats(gencats)
     combines = to_combines(group_cats(combines))
 
-    return (canon_decomp, compat_decomp, gencats, combines, lowerupper, upperlower)
+    return (canon_decomp, compat_decomp, gencats, combines, to_upper, to_lower, to_title)
+
+def load_special_casing(f, to_upper, to_lower, to_title):
+    fetch(f)
+    for line in fileinput.input(f):
+        data = line.split('#')[0].split(';')
+        if len(data) == 5:
+            code, lower, title, upper, _comment = data
+        elif len(data) == 6:
+            code, lower, title, upper, condition, _comment = data
+            if condition.strip():  # Only keep unconditional mappins
+                continue
+        else:
+            continue
+        code = code.strip()
+        lower = lower.strip()
+        title = title.strip()
+        upper = upper.strip()
+        key = int(code, 16)
+        for (map_, values) in [(to_lower, lower), (to_upper, upper), (to_title, title)]:
+            if values != code:
+                values = [int(i, 16) for i in values.split()]
+                for _ in range(len(values), 3):
+                    values.append(0)
+                assert len(values) == 3
+                map_[key] = values
 
 def group_cats(cats):
     cats_out = {}
@@ -279,7 +309,7 @@ def load_east_asian_width(want_widths, except_cats):
     return widths
 
 def escape_char(c):
-    return "'\\u{%x}'" % c
+    return "'\\u{%x}'" % c if c != 0 else "'\\0'"
 
 def emit_bsearch_range_table(f):
     f.write("""
@@ -319,7 +349,7 @@ def emit_property_module(f, mod, tbl, emit):
         f.write("    }\n\n")
     f.write("}\n\n")
 
-def emit_conversions_module(f, lowerupper, upperlower):
+def emit_conversions_module(f, to_upper, to_lower, to_title):
     f.write("pub mod conversions {")
     f.write("""
     use core::cmp::Ordering::{Equal, Less, Greater};
@@ -328,21 +358,28 @@ def emit_conversions_module(f, lowerupper, upperlower):
     use core::option::Option::{Some, None};
     use core::result::Result::{Ok, Err};
 
-    pub fn to_lower(c: char) -> char {
-        match bsearch_case_table(c, LuLl_table) {
-          None        => c,
-          Some(index) => LuLl_table[index].1
+    pub fn to_lower(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_lowercase_table) {
+          None        => [c, '\\0', '\\0'],
+          Some(index) => to_lowercase_table[index].1
+        }
+    }
+
+    pub fn to_upper(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_uppercase_table) {
+            None        => [c, '\\0', '\\0'],
+            Some(index) => to_uppercase_table[index].1
         }
     }
 
-    pub fn to_upper(c: char) -> char {
-        match bsearch_case_table(c, LlLu_table) {
-            None        => c,
-            Some(index) => LlLu_table[index].1
+    pub fn to_title(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_titlecase_table) {
+            None        => [c, '\\0', '\\0'],
+            Some(index) => to_titlecase_table[index].1
         }
     }
 
-    fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<usize> {
+    fn bsearch_case_table(c: char, table: &'static [(char, [char; 3])]) -> Option<usize> {
         match table.binary_search_by(|&(key, _)| {
             if c == key { Equal }
             else if key < c { Less }
@@ -354,10 +391,18 @@ def emit_conversions_module(f, lowerupper, upperlower):
     }
 
 """)
-    emit_table(f, "LuLl_table",
-        sorted(upperlower.iteritems(), key=operator.itemgetter(0)), is_pub=False)
-    emit_table(f, "LlLu_table",
-        sorted(lowerupper.iteritems(), key=operator.itemgetter(0)), is_pub=False)
+    t_type = "&'static [(char, [char; 3])]"
+    pfun = lambda x: "(%s,[%s,%s,%s])" % (
+        escape_char(x[0]), escape_char(x[1][0]), escape_char(x[1][1]), escape_char(x[1][2]))
+    emit_table(f, "to_lowercase_table",
+        sorted(to_lower.iteritems(), key=operator.itemgetter(0)),
+        is_pub=False, t_type = t_type, pfun=pfun)
+    emit_table(f, "to_uppercase_table",
+        sorted(to_upper.iteritems(), key=operator.itemgetter(0)),
+        is_pub=False, t_type = t_type, pfun=pfun)
+    emit_table(f, "to_titlecase_table",
+        sorted(to_title.iteritems(), key=operator.itemgetter(0)),
+        is_pub=False, t_type = t_type, pfun=pfun)
     f.write("}\n\n")
 
 def emit_grapheme_module(f, grapheme_table, grapheme_cats):
@@ -591,8 +636,10 @@ if __name__ == "__main__":
 pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
 """ % unicode_version)
         (canon_decomp, compat_decomp, gencats, combines,
-                lowerupper, upperlower) = load_unicode_data("UnicodeData.txt")
-        want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase"]
+                to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt")
+        load_special_casing("SpecialCasing.txt", to_upper, to_lower, to_title)
+        want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase",
+                        "Cased", "Case_Ignorable"]
         derived = load_properties("DerivedCoreProperties.txt", want_derived)
         scripts = load_properties("Scripts.txt", [])
         props = load_properties("PropList.txt",
@@ -611,7 +658,7 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
 
         # normalizations and conversions module
         emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props)
-        emit_conversions_module(rf, lowerupper, upperlower)
+        emit_conversions_module(rf, to_upper, to_lower, to_title)
 
         ### character width module
         width_table = []
index 47b0981a70ab3d36358cf421f0bdccd23824318d..4f4246ff1db7ccf880543ca69edc2a0d13fc198e 100644 (file)
@@ -1 +1 @@
-0.12.0-9659-g35ceea3997c79a3b7562e89b462ab76af5b86b22
+0.12.0-10860-g082e4763615bdbe7b4dd3dfd6fc2210b7773edf5
index 8c3c21a89023dc62322d1b0f8e21167225ba2a61..dd9c1d1fd188556cc89a78808411b9c89ef8dfd6 100644 (file)
@@ -77,11 +77,12 @@ use core::atomic;
 use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
 use core::fmt;
 use core::cmp::Ordering;
-use core::mem::{min_align_of, size_of};
+use core::mem::{align_of_val, size_of_val};
+use core::intrinsics::drop_in_place;
 use core::mem;
 use core::nonzero::NonZero;
-use core::ops::Deref;
-use core::ptr;
+use core::ops::{Deref, CoerceUnsized};
+use core::marker::Unsize;
 use core::hash::{Hash, Hasher};
 use heap::deallocate;
 
@@ -97,7 +98,6 @@ use heap::deallocate;
 /// increase the reference counter.
 ///
 /// ```
-/// # #![feature(alloc, core)]
 /// use std::sync::Arc;
 /// use std::thread;
 ///
@@ -118,47 +118,48 @@ use heap::deallocate;
 /// ```
 #[unsafe_no_drop_flag]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Arc<T> {
+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>>,
 }
 
-unsafe impl<T: Sync + Send> Send for Arc<T> { }
-unsafe impl<T: Sync + Send> Sync for Arc<T> { }
+unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> { }
+unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> { }
 
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
 /// A weak pointer to an `Arc`.
 ///
 /// Weak pointers will not keep the data inside of the `Arc` alive, and can be
 /// used to break cycles between `Arc` pointers.
 #[unsafe_no_drop_flag]
-#[unstable(feature = "alloc",
+#[unstable(feature = "arc_weak",
            reason = "Weak pointers may not belong in this module.")]
-pub struct Weak<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>>,
 }
 
-unsafe impl<T: Sync + Send> Send for Weak<T> { }
-unsafe impl<T: Sync + Send> Sync for Weak<T> { }
+unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
+unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for Weak<T> {
+impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
     }
 }
 
-struct ArcInner<T> {
+struct ArcInner<T: ?Sized> {
     strong: atomic::AtomicUsize,
     weak: atomic::AtomicUsize,
     data: T,
 }
 
-unsafe impl<T: Sync + Send> Send for ArcInner<T> {}
-unsafe impl<T: Sync + Send> Sync for ArcInner<T> {}
+unsafe impl<T: ?Sized + Sync + Send> Send for ArcInner<T> {}
+unsafe impl<T: ?Sized + Sync + Send> Sync for ArcInner<T> {}
 
 impl<T> Arc<T> {
     /// Constructs a new `Arc<T>`.
@@ -182,29 +183,43 @@ impl<T> Arc<T> {
         };
         Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
     }
+}
 
+impl<T: ?Sized> Arc<T> {
     /// Downgrades the `Arc<T>` to a `Weak<T>` reference.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(arc_weak)]
     /// use std::sync::Arc;
     ///
     /// let five = Arc::new(5);
     ///
     /// let weak_five = five.downgrade();
     /// ```
-    #[unstable(feature = "alloc",
+    #[unstable(feature = "arc_weak",
                reason = "Weak pointers may not belong in this module.")]
     pub fn downgrade(&self) -> Weak<T> {
         // See the clone() impl for why this is relaxed
         self.inner().weak.fetch_add(1, Relaxed);
         Weak { _ptr: self._ptr }
     }
-}
 
-impl<T> Arc<T> {
+    /// Get the number of weak references to this value.
+    #[inline]
+    #[unstable(feature = "arc_counts")]
+    pub fn weak_count(this: &Arc<T>) -> usize {
+        this.inner().weak.load(SeqCst) - 1
+    }
+
+    /// Get the number of strong references to this value.
+    #[inline]
+    #[unstable(feature = "arc_counts")]
+    pub fn strong_count(this: &Arc<T>) -> usize {
+        this.inner().strong.load(SeqCst)
+    }
+
     #[inline]
     fn inner(&self) -> &ArcInner<T> {
         // This unsafety is ok because while this arc is alive we're guaranteed
@@ -222,38 +237,44 @@ impl<T> Arc<T> {
 
         // Destroy the data at this time, even though we may not free the box
         // allocation itself (there may still be weak pointers lying around).
-        drop(ptr::read(&self.inner().data));
+        drop_in_place(&mut (*ptr).data);
 
         if self.inner().weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
-            deallocate(ptr as *mut u8, size_of::<ArcInner<T>>(), min_align_of::<ArcInner<T>>())
+            deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
         }
     }
 }
 
 /// Get the number of weak references to this value.
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn weak_count<T>(this: &Arc<T>) -> usize { this.inner().weak.load(SeqCst) - 1 }
+#[unstable(feature = "arc_counts")]
+#[deprecated(since = "1.2.0", reason = "renamed to Arc::weak_count")]
+pub fn weak_count<T: ?Sized>(this: &Arc<T>) -> usize { Arc::weak_count(this) }
 
 /// Get the number of strong references to this value.
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst) }
+#[unstable(feature = "arc_counts")]
+#[deprecated(since = "1.2.0", reason = "renamed to Arc::strong_count")]
+pub fn strong_count<T: ?Sized>(this: &Arc<T>) -> usize { Arc::strong_count(this) }
 
 
 /// Returns a mutable reference to the contained value if the `Arc<T>` is unique.
 ///
 /// Returns `None` if the `Arc<T>` is not unique.
 ///
+/// This function is marked **unsafe** because it is racy if weak pointers
+/// are active.
+///
 /// # Examples
 ///
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(arc_unique, alloc)]
 /// extern crate alloc;
 /// # fn main() {
 /// use alloc::arc::{Arc, get_mut};
 ///
+/// # unsafe {
 /// let mut x = Arc::new(3);
 /// *get_mut(&mut x).unwrap() = 4;
 /// assert_eq!(*x, 4);
@@ -261,17 +282,21 @@ pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst
 /// let _y = x.clone();
 /// assert!(get_mut(&mut x).is_none());
 /// # }
+/// # }
 /// ```
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn get_mut<T>(this: &mut Arc<T>) -> Option<&mut T> {
-    if strong_count(this) == 1 && weak_count(this) == 0 {
+#[unstable(feature = "arc_unique")]
+#[deprecated(since = "1.2.0",
+             reason = "this function is unsafe with weak pointers")]
+pub unsafe fn get_mut<T: ?Sized>(this: &mut Arc<T>) -> Option<&mut T> {
+    // FIXME(#24880) potential race with upgraded weak pointers here
+    if Arc::strong_count(this) == 1 && Arc::weak_count(this) == 0 {
         // This unsafety is ok because we're guaranteed that the pointer
         // returned is the *only* pointer that will ever be returned to T. Our
         // reference count is guaranteed to be 1 at this point, and we required
         // the Arc itself to be `mut`, so we're returning the only possible
         // reference to the inner data.
-        let inner = unsafe { &mut **this._ptr };
+        let inner = &mut **this._ptr;
         Some(&mut inner.data)
     } else {
         None
@@ -279,7 +304,7 @@ pub fn get_mut<T>(this: &mut Arc<T>) -> Option<&mut T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for Arc<T> {
+impl<T: ?Sized> Clone for Arc<T> {
     /// Makes a clone of the `Arc<T>`.
     ///
     /// This increases the strong reference count.
@@ -287,7 +312,6 @@ impl<T> Clone for Arc<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
     /// use std::sync::Arc;
     ///
     /// let five = Arc::new(5);
@@ -313,7 +337,7 @@ impl<T> Clone for Arc<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Deref for Arc<T> {
+impl<T: ?Sized> Deref for Arc<T> {
     type Target = T;
 
     #[inline]
@@ -328,19 +352,28 @@ impl<T: Clone> Arc<T> {
     /// This is also referred to as a copy-on-write operation because the inner
     /// data is cloned if the reference count is greater than one.
     ///
+    /// This method is marked **unsafe** because it is racy if weak pointers
+    /// are active.
+    ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(arc_unique)]
     /// use std::sync::Arc;
     ///
+    /// # unsafe {
     /// let mut five = Arc::new(5);
     ///
     /// let mut_five = five.make_unique();
+    /// # }
     /// ```
     #[inline]
-    #[unstable(feature = "alloc")]
-    pub fn make_unique(&mut self) -> &mut T {
+    #[unstable(feature = "arc_unique")]
+    #[deprecated(since = "1.2.0",
+                 reason = "this function is unsafe with weak pointers")]
+    pub unsafe fn make_unique(&mut self) -> &mut T {
+        // FIXME(#24880) potential race with upgraded weak pointers here
+        //
         // Note that we hold a strong reference, which also counts as a weak
         // reference, so we only clone if there is an additional reference of
         // either kind.
@@ -350,13 +383,13 @@ impl<T: Clone> Arc<T> {
         }
         // As with `get_mut()`, the unsafety is ok because our reference was
         // either unique to begin with, or became one upon cloning the contents.
-        let inner = unsafe { &mut **self._ptr };
+        let inner = &mut **self._ptr;
         &mut inner.data
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for Arc<T> {
+impl<T: ?Sized> Drop for Arc<T> {
     /// Drops the `Arc<T>`.
     ///
     /// This will decrement the strong reference count. If the strong reference
@@ -366,7 +399,6 @@ impl<T> Drop for Arc<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
     /// use std::sync::Arc;
     ///
     /// {
@@ -390,7 +422,9 @@ impl<T> Drop for Arc<T> {
         // it's run more than once)
         let ptr = *self._ptr;
         // if ptr.is_null() { return }
-        if ptr.is_null() || ptr as usize == mem::POST_DROP_USIZE { return }
+        if ptr as *mut u8 as usize == 0 || ptr as *mut u8 as usize == mem::POST_DROP_USIZE {
+            return
+        }
 
         // Because `fetch_sub` is already atomic, we do not need to synchronize
         // with other threads unless we are going to delete the object. This
@@ -422,9 +456,9 @@ impl<T> Drop for Arc<T> {
     }
 }
 
-#[unstable(feature = "alloc",
+#[unstable(feature = "arc_weak",
            reason = "Weak pointers may not belong in this module.")]
-impl<T> Weak<T> {
+impl<T: ?Sized> Weak<T> {
     /// Upgrades a weak reference to a strong reference.
     ///
     /// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
@@ -435,7 +469,7 @@ impl<T> Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(arc_weak)]
     /// use std::sync::Arc;
     ///
     /// let five = Arc::new(5);
@@ -463,9 +497,9 @@ impl<T> Weak<T> {
     }
 }
 
-#[unstable(feature = "alloc",
+#[unstable(feature = "arc_weak",
            reason = "Weak pointers may not belong in this module.")]
-impl<T> Clone for Weak<T> {
+impl<T: ?Sized> Clone for Weak<T> {
     /// Makes a clone of the `Weak<T>`.
     ///
     /// This increases the weak reference count.
@@ -473,7 +507,7 @@ impl<T> Clone for Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(arc_weak)]
     /// use std::sync::Arc;
     ///
     /// let weak_five = Arc::new(5).downgrade();
@@ -489,7 +523,7 @@ impl<T> Clone for Weak<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for Weak<T> {
+impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
     /// This will decrement the weak reference count.
@@ -497,7 +531,7 @@ impl<T> Drop for Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(arc_weak)]
     /// use std::sync::Arc;
     ///
     /// {
@@ -520,21 +554,24 @@ impl<T> Drop for Weak<T> {
         let ptr = *self._ptr;
 
         // see comments above for why this check is here
-        if ptr.is_null() || ptr as usize == mem::POST_DROP_USIZE { return }
+        if ptr as *mut u8 as usize == 0 || ptr as *mut u8 as usize == mem::POST_DROP_USIZE {
+            return
+        }
 
         // If we find out that we were the last weak pointer, then its time to
         // deallocate the data entirely. See the discussion in Arc::drop() about
         // the memory orderings
         if self.inner().weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
-            unsafe { deallocate(ptr as *mut u8, size_of::<ArcInner<T>>(),
-                                min_align_of::<ArcInner<T>>()) }
+            unsafe { deallocate(ptr as *mut u8,
+                                size_of_val(&*ptr),
+                                align_of_val(&*ptr)) }
         }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialEq> PartialEq for Arc<T> {
+impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
     /// Equality for two `Arc<T>`s.
     ///
     /// Two `Arc<T>`s are equal if their inner value are equal.
@@ -566,7 +603,7 @@ impl<T: PartialEq> PartialEq for Arc<T> {
     fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialOrd> PartialOrd for Arc<T> {
+impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
     /// Partial comparison for two `Arc<T>`s.
     ///
     /// The two are compared by calling `partial_cmp()` on their inner values.
@@ -645,21 +682,21 @@ impl<T: PartialOrd> PartialOrd for Arc<T> {
     fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Ord for Arc<T> {
+impl<T: ?Sized + Ord> Ord for Arc<T> {
     fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq> Eq for Arc<T> {}
+impl<T: ?Sized + Eq> Eq for Arc<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Display> fmt::Display for Arc<T> {
+impl<T: ?Sized + fmt::Display> fmt::Display for Arc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&**self, f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for Arc<T> {
+impl<T: ?Sized + fmt::Debug> fmt::Debug for Arc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
@@ -679,7 +716,7 @@ impl<T: Default> Default for Arc<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Hash> Hash for Arc<T> {
+impl<T: ?Sized + Hash> Hash for Arc<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         (**self).hash(state)
     }
@@ -735,39 +772,43 @@ mod tests {
 
     #[test]
     fn test_arc_get_mut() {
-        let mut x = Arc::new(3);
-        *get_mut(&mut x).unwrap() = 4;
-        assert_eq!(*x, 4);
-        let y = x.clone();
-        assert!(get_mut(&mut x).is_none());
-        drop(y);
-        assert!(get_mut(&mut x).is_some());
-        let _w = x.downgrade();
-        assert!(get_mut(&mut x).is_none());
+        unsafe {
+            let mut x = Arc::new(3);
+            *get_mut(&mut x).unwrap() = 4;
+            assert_eq!(*x, 4);
+            let y = x.clone();
+            assert!(get_mut(&mut x).is_none());
+            drop(y);
+            assert!(get_mut(&mut x).is_some());
+            let _w = x.downgrade();
+            assert!(get_mut(&mut x).is_none());
+        }
     }
 
     #[test]
     fn test_cowarc_clone_make_unique() {
-        let mut cow0 = Arc::new(75);
-        let mut cow1 = cow0.clone();
-        let mut cow2 = cow1.clone();
-
-        assert!(75 == *cow0.make_unique());
-        assert!(75 == *cow1.make_unique());
-        assert!(75 == *cow2.make_unique());
-
-        *cow0.make_unique() += 1;
-        *cow1.make_unique() += 2;
-        *cow2.make_unique() += 3;
-
-        assert!(76 == *cow0);
-        assert!(77 == *cow1);
-        assert!(78 == *cow2);
-
-        // none should point to the same backing memory
-        assert!(*cow0 != *cow1);
-        assert!(*cow0 != *cow2);
-        assert!(*cow1 != *cow2);
+        unsafe {
+            let mut cow0 = Arc::new(75);
+            let mut cow1 = cow0.clone();
+            let mut cow2 = cow1.clone();
+
+            assert!(75 == *cow0.make_unique());
+            assert!(75 == *cow1.make_unique());
+            assert!(75 == *cow2.make_unique());
+
+            *cow0.make_unique() += 1;
+            *cow1.make_unique() += 2;
+            *cow2.make_unique() += 3;
+
+            assert!(76 == *cow0);
+            assert!(77 == *cow1);
+            assert!(78 == *cow2);
+
+            // none should point to the same backing memory
+            assert!(*cow0 != *cow1);
+            assert!(*cow0 != *cow2);
+            assert!(*cow1 != *cow2);
+        }
     }
 
     #[test]
@@ -780,7 +821,9 @@ mod tests {
         assert!(75 == *cow1);
         assert!(75 == *cow2);
 
-        *cow0.make_unique() += 1;
+        unsafe {
+            *cow0.make_unique() += 1;
+        }
 
         assert!(76 == *cow0);
         assert!(75 == *cow1);
@@ -801,7 +844,9 @@ mod tests {
         assert!(75 == *cow0);
         assert!(75 == *cow1_weak.upgrade().unwrap());
 
-        *cow0.make_unique() += 1;
+        unsafe {
+            *cow0.make_unique() += 1;
+        }
 
         assert!(76 == *cow0);
         assert!(cow1_weak.upgrade().is_none());
@@ -906,4 +951,13 @@ mod tests {
     // Make sure deriving works with Arc<T>
     #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
     struct Foo { inner: Arc<i32> }
+
+    #[test]
+    fn test_unsized() {
+        let x: Arc<[i32]> = Arc::new([1, 2, 3]);
+        assert_eq!(format!("{:?}", x), "[1, 2, 3]");
+        let y = x.clone().downgrade();
+        drop(x);
+        assert!(y.upgrade().is_none());
+    }
 }
index 35732dacd44f9aee58808895ae0a47daa42ce199..1039756363e9fa1aa6a05ed1a9f7f30720a19488 100644 (file)
@@ -10,9 +10,9 @@
 
 //! A pointer type for heap allocation.
 //!
-//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
-//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
-//! scope.
+//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
+//! heap allocation in Rust. Boxes provide ownership for this allocation, and
+//! drop their contents when they go out of scope.
 //!
 //! # Examples
 //!
 //!
 //! This will print `Cons(1, Cons(2, Nil))`.
 //!
-//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
+//! Recursive structures must be boxed, because if the definition of `Cons`
+//! looked like this:
 //!
 //! ```rust,ignore
 //! Cons(T, List<T>),
 //! ```
 //!
-//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
-//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
-//! which has a defined size, we know how big `Cons` needs to be.
+//! It wouldn't work. This is because the size of a `List` depends on how many
+//! elements are in the list, and so we don't know how much memory to allocate
+//! for a `Cons`. By introducing a `Box`, which has a defined size, we know how
+//! big `Cons` needs to be.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -57,23 +59,19 @@ use core::any::Any;
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{self, Hash};
+use core::marker::Unsize;
 use core::mem;
-use core::ops::{Deref, DerefMut};
+use core::ops::{CoerceUnsized, Deref, DerefMut};
 use core::ptr::{Unique};
 use core::raw::{TraitObject};
 
-#[cfg(not(stage0))]
-use core::marker::Unsize;
-#[cfg(not(stage0))]
-use core::ops::CoerceUnsized;
-
 /// A value that represents the heap. This is the default place that the `box`
 /// keyword allocates into when no place is supplied.
 ///
 /// The following two examples are equivalent:
 ///
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(box_heap)]
 /// #![feature(box_syntax)]
 /// use std::boxed::HEAP;
 ///
@@ -83,9 +81,9 @@ use core::ops::CoerceUnsized;
 /// }
 /// ```
 #[lang = "exchange_heap"]
-#[unstable(feature = "alloc",
+#[unstable(feature = "box_heap",
            reason = "may be renamed; uncertain about custom allocator design")]
-pub static HEAP: () = ();
+pub const HEAP: () = ();
 
 /// A pointer type for heap allocation.
 ///
@@ -123,12 +121,37 @@ impl<T : ?Sized> Box<T> {
     /// Function is unsafe, because improper use of this function may
     /// lead to memory problems like double-free, for example if the
     /// function is called twice on the same raw pointer.
-    #[unstable(feature = "alloc",
+    #[unstable(feature = "box_raw",
                reason = "may be renamed or moved out of Box scope")]
     #[inline]
+    // NB: may want to be called from_ptr, see comments on CStr::from_ptr
     pub unsafe fn from_raw(raw: *mut T) -> Self {
         mem::transmute(raw)
     }
+
+    /// Consumes the `Box`, returning the wrapped raw pointer.
+    ///
+    /// After call to this function, caller is responsible for the memory
+    /// previously managed by `Box`, in particular caller should properly
+    /// destroy `T` and release memory. The proper way to do it is to
+    /// convert pointer back to `Box` with `Box::from_raw` function, because
+    /// `Box` does not specify, how memory is allocated.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(box_raw)]
+    /// use std::boxed;
+    ///
+    /// let seventeen = Box::new(17u32);
+    /// let raw = boxed::into_raw(seventeen);
+    /// let boxed_again = unsafe { Box::from_raw(raw) };
+    /// ```
+    #[unstable(feature = "box_raw", reason = "may be renamed")]
+    #[inline]
+    // NB: may want to be called into_ptr, see comments on CStr::from_ptr
+    pub fn into_raw(b: Box<T>) -> *mut T {
+        unsafe { mem::transmute(b) }
+    }
 }
 
 /// Consumes the `Box`, returning the wrapped raw pointer.
@@ -139,24 +162,20 @@ impl<T : ?Sized> Box<T> {
 /// convert pointer back to `Box` with `Box::from_raw` function, because
 /// `Box` does not specify, how memory is allocated.
 ///
-/// Function is unsafe, because result of this function is no longer
-/// automatically managed that may lead to memory or other resource
-/// leak.
-///
 /// # Examples
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(box_raw)]
 /// use std::boxed;
 ///
 /// let seventeen = Box::new(17u32);
-/// let raw = unsafe { boxed::into_raw(seventeen) };
+/// let raw = boxed::into_raw(seventeen);
 /// let boxed_again = unsafe { Box::from_raw(raw) };
 /// ```
-#[unstable(feature = "alloc",
-           reason = "may be renamed")]
+#[unstable(feature = "box_raw", reason = "may be renamed")]
+#[deprecated(since = "1.2.0", reason = "renamed to Box::into_raw")]
 #[inline]
-pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
-    mem::transmute(b)
+pub fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
+    Box::into_raw(b)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -189,7 +208,7 @@ impl<T: Clone> Clone for Box<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc, core)]
+    /// # #![feature(box_raw)]
     /// let x = Box::new(5);
     /// let mut y = Box::new(10);
     ///
@@ -250,7 +269,7 @@ impl Box<Any> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
-                let raw = into_raw(self);
+                let raw = Box::into_raw(self);
                 let to: TraitObject =
                     mem::transmute::<*mut Any, TraitObject>(raw);
 
@@ -342,7 +361,7 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
 /// -> i32>`.
 ///
 /// ```
-/// #![feature(core)]
+/// #![feature(fnbox)]
 ///
 /// use std::boxed::FnBox;
 /// use std::collections::HashMap;
@@ -363,7 +382,7 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
 /// }
 /// ```
 #[rustc_paren_sugar]
-#[unstable(feature = "core", reason = "Newly introduced")]
+#[unstable(feature = "fnbox", reason = "Newly introduced")]
 pub trait FnBox<A> {
     type Output;
 
@@ -396,5 +415,4 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
     }
 }
 
-#[cfg(not(stage0))]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
index e155dc86f3251d497b43cea25c82ae1d503e9bd1..14797d7f4b54d20cee3bd5a164162dae18806513 100644 (file)
@@ -8,6 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![unstable(feature = "heap_api",
+            reason = "the precise API and guarantees it provides may be tweaked \
+                      slightly, especially to possibly take into account the \
+                      types being stored to make room for a future \
+                      tracing garbage collector")]
+
 use core::{isize, usize};
 
 #[inline(always)]
@@ -94,7 +100,6 @@ pub fn usable_size(size: usize, align: usize) -> usize {
 ///
 /// These statistics may be inconsistent if other threads use the allocator
 /// during the call.
-#[unstable(feature = "alloc")]
 pub fn stats_print() {
     imp::stats_print();
 }
@@ -345,47 +350,94 @@ mod imp {
           not(jemalloc),
           windows))]
 mod imp {
-    use libc::{c_void, size_t};
-    use libc;
+    use core::mem::size_of;
+    use libc::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T, INVALID_HANDLE_VALUE};
+    use libc::{WriteFile};
     use super::MIN_ALIGN;
 
-    extern {
-        fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
-        fn _aligned_realloc(block: *mut c_void, size: size_t,
-                            align: size_t) -> *mut c_void;
-        fn _aligned_free(ptr: *mut c_void);
+    extern "system" {
+        fn GetProcessHeap() -> HANDLE;
+        fn GetStdHandle(nStdHandle: DWORD) -> HANDLE;
+        fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, 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;
+        fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) -> BOOL;
+    }
+
+    #[repr(C)] #[allow(non_snake_case)]
+    struct HEAP_SUMMARY {
+        cb: DWORD,
+        cbAllocated: SIZE_T,
+        cbCommitted: SIZE_T,
+        cbReserved: SIZE_T,
+        cbMaxReserve: SIZE_T,
+    }
+    #[allow(non_camel_case_types)]
+    type LPHEAP_SUMMARY = *mut HEAP_SUMMARY;
+
+    #[repr(C)]
+    struct Header(*mut u8);
+
+    const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
+    const STD_OUTPUT_HANDLE: DWORD = -11i32 as u32;
+
+    #[inline]
+    unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
+        &mut *(ptr as *mut Header).offset(-1)
+    }
+
+    #[inline]
+    unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
+        let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize);
+        *get_header(aligned) = Header(ptr);
+        aligned
     }
 
     #[inline]
     pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
         if align <= MIN_ALIGN {
-            libc::malloc(size as size_t) as *mut u8
+            HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
         } else {
-            _aligned_malloc(size as size_t, align as size_t) as *mut u8
+            let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
+            if ptr.is_null() { return ptr }
+            align_ptr(ptr, align)
         }
     }
 
     #[inline]
     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 c_void, size as size_t) as *mut u8
+            HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8
         } else {
-            _aligned_realloc(ptr as *mut c_void, size as size_t, align as size_t) as *mut u8
+            let header = get_header(ptr);
+            let new = HeapReAlloc(GetProcessHeap(), 0, header.0 as LPVOID,
+                                  (size + align) as SIZE_T) as *mut u8;
+            if new.is_null() { return new }
+            align_ptr(new, align)
         }
     }
 
     #[inline]
-    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
-                                     _align: usize) -> usize {
-        old_size
+    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 }
+        } else {
+            old_size
+        }
     }
 
     #[inline]
     pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
         if align <= MIN_ALIGN {
-            libc::free(ptr as *mut libc::c_void)
+            let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
+            debug_assert!(err != 0);
         } else {
-            _aligned_free(ptr as *mut c_void)
+            let header = get_header(ptr);
+            let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
+            debug_assert!(err != 0);
         }
     }
 
@@ -394,7 +446,45 @@ mod imp {
         size
     }
 
-    pub fn stats_print() {}
+    pub fn stats_print() {
+        use core::fmt::{Error, Result, Write};
+        use core::ptr::null_mut;
+        use core::raw::Repr;
+        use core::result::Result::{Ok, Err};
+        struct Console(HANDLE);
+        impl Write for Console {
+            fn write_str(&mut self, s: &str) -> Result {
+                let repr = s.repr();
+                let mut written = 0;
+                let err = unsafe { WriteFile(self.0, repr.data as LPVOID, repr.len as DWORD,
+                                             &mut written, null_mut()) };
+                if written as usize != repr.len { return Err(Error) }
+                if err == 0 { return Err(Error) }
+                Ok(())
+            }
+        }
+        let mut hs = HEAP_SUMMARY {
+            cb: size_of::<HEAP_SUMMARY>() as DWORD,
+            cbAllocated: 0,
+            cbCommitted: 0,
+            cbReserved: 0,
+            cbMaxReserve: 0,
+        };
+        let err = unsafe { HeapSummary(GetProcessHeap(), 0, &mut hs) };
+        assert!(err != 0);
+        let handle = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
+        if handle.is_null() || handle == INVALID_HANDLE_VALUE { panic!("Failed to open stdout") }
+        let mut out = Console(handle);
+        writeln!(&mut out, "Allocated: {}", hs.cbAllocated).unwrap();
+        writeln!(&mut out, "Committed: {}", hs.cbCommitted).unwrap();
+        writeln!(&mut out, "Reserved: {}", hs.cbReserved).unwrap();
+        writeln!(&mut out, "MaxReserve: {}", hs.cbMaxReserve).unwrap();
+    }
+
+    #[test]
+    fn alignment_header_size() {
+        assert!(size_of::<Header>() <= MIN_ALIGN);
+    }
 }
 
 #[cfg(test)]
index 473429b813c50bc6d093a61cb60338de324520d9..7dcf7a76da083ba3dc5143a78200add26ebaae10 100644 (file)
@@ -22,9 +22,9 @@
 //!
 //! ## Boxed values
 //!
-//! The [`Box`](boxed/index.html) type is the core owned pointer type in Rust.
-//! There can only be one owner of a `Box`, and the owner can decide to mutate
-//! the contents, which live on the heap.
+//! The [`Box`](boxed/index.html) type is a smart pointer type. There can
+//! only be one owner of a `Box`, and the owner can decide to mutate the
+//! contents, which live on the heap.
 //!
 //! This type can be sent among threads efficiently as the size of a `Box` value
 //! is the same as that of a pointer. Tree-like data structures are often built
 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "alloc"]
-#![unstable(feature = "alloc")]
-#![feature(staged_api)]
-#![staged_api]
 #![crate_type = "rlib"]
+#![staged_api]
+#![unstable(feature = "alloc",
+            reason = "this library is unlikely to be stabilized in its current \
+                      form or name")]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![doc(test(no_crate_inject))]
-
-#![feature(no_std)]
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "http://doc.rust-lang.org/nightly/",
+       test(no_crate_inject))]
 #![no_std]
+
 #![feature(allocator)]
+#![feature(box_syntax)]
+#![feature(coerce_unsized)]
+#![feature(core)]
+#![feature(core_intrinsics)]
+#![feature(core_prelude)]
 #![feature(custom_attribute)]
 #![feature(fundamental)]
 #![feature(lang_items)]
-#![feature(box_syntax)]
+#![feature(no_std)]
+#![feature(nonzero)]
 #![feature(optin_builtin_traits)]
+#![feature(raw)]
+#![feature(staged_api)]
 #![feature(unboxed_closures)]
-#![feature(unsafe_no_drop_flag, filling_drop)]
-#![feature(core)]
 #![feature(unique)]
-#![cfg_attr(test, feature(test, alloc, rustc_private))]
+#![feature(unsafe_no_drop_flag, filling_drop)]
+#![feature(unsize)]
+
+#![cfg_attr(test, feature(test, alloc, rustc_private, box_raw))]
 #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
             feature(libc))]
 
-
 #[macro_use]
 extern crate core;
 
@@ -118,6 +126,7 @@ pub mod rc;
 /// Common out-of-memory routine
 #[cold]
 #[inline(never)]
+#[unstable(feature = "oom", reason = "not a scrutinized interface")]
 pub fn oom() -> ! {
     // FIXME(#14674): This really needs to do something other than just abort
     //                here, but any printing done must be *guaranteed* to not
@@ -138,4 +147,5 @@ pub fn oom() -> ! {
 //                to get linked in to libstd successfully (the linker won't
 //                optimize it out).
 #[doc(hidden)]
+#[unstable(feature = "issue_14344_fixme")]
 pub fn fixme_14344_be_sure_to_link_to_collections() {}
index f2b83fdeefa3a8a0f2a8a143acc2886c9aaa3277..3dfafd0a378b90bef31771c17dbb43d28f069b78 100644 (file)
@@ -32,7 +32,6 @@
 //! and have the `Owner` remain allocated as long as any `Gadget` points at it.
 //!
 //! ```rust
-//! # #![feature(alloc, collections)]
 //! use std::rc::Rc;
 //!
 //! struct Owner {
@@ -49,7 +48,7 @@
 //! fn main() {
 //!     // Create a reference counted Owner.
 //!     let gadget_owner : Rc<Owner> = Rc::new(
-//!             Owner { name: String::from_str("Gadget Man") }
+//!             Owner { name: String::from("Gadget Man") }
 //!     );
 //!
 //!     // Create Gadgets belonging to gadget_owner. To increment the reference
@@ -92,7 +91,7 @@
 //! documentation for more details on interior mutability.
 //!
 //! ```rust
-//! # #![feature(alloc)]
+//! # #![feature(rc_weak)]
 //! use std::rc::Rc;
 //! use std::rc::Weak;
 //! use std::cell::RefCell;
 //!     // At the end of the method, gadget_owner, gadget1 and gadget2 get
 //!     // destroyed. There are now no strong (`Rc<T>`) references to the gadgets.
 //!     // Once they get destroyed, the Gadgets get destroyed. This zeroes the
-//!     // reference count on Gadget Man, so he gets destroyed as well.
+//!     // reference count on Gadget Man, they get destroyed as well.
 //! }
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
+
+use core::prelude::*;
+
 #[cfg(not(test))]
-use boxed;
+use boxed::Box;
 #[cfg(test)]
-use std::boxed;
+use std::boxed::Box;
+
 use core::cell::Cell;
-use core::clone::Clone;
-use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
-use core::default::Default;
+use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{Hasher, Hash};
-use core::marker::{self, Sized};
-use core::mem::{self, min_align_of, size_of, forget};
+use core::intrinsics::{assume, drop_in_place};
+use core::marker::{self, Unsize};
+use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget};
 use core::nonzero::NonZero;
-use core::ops::{Deref, Drop};
-use core::option::Option;
-use core::option::Option::{Some, None};
+use core::ops::{CoerceUnsized, Deref};
 use core::ptr;
-use core::result::Result;
-use core::result::Result::{Ok, Err};
-use core::intrinsics::assume;
-
-#[cfg(not(stage0))]
-use core::intrinsics::drop_in_place;
-#[cfg(not(stage0))]
-use core::marker::Unsize;
-#[cfg(not(stage0))]
-use core::mem::{min_align_of_val, size_of_val};
-#[cfg(not(stage0))]
-use core::ops::CoerceUnsized;
 
 use heap::deallocate;
 
-#[cfg(stage0)]
-struct RcBox<T> {
-    strong: Cell<usize>,
-    weak: Cell<usize>,
-    value: T,
-}
-
-#[cfg(not(stage0))]
 struct RcBox<T: ?Sized> {
     strong: Cell<usize>,
     weak: Cell<usize>,
@@ -199,15 +179,6 @@ struct RcBox<T: ?Sized> {
 /// A reference-counted pointer type over an immutable value.
 ///
 /// See the [module level documentation](./index.html) for more details.
-#[cfg(stage0)]
-#[unsafe_no_drop_flag]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Rc<T> {
-    // FIXME #12808: strange names to try to avoid interfering with field
-    // accesses of the contained type via Deref
-    _ptr: NonZero<*mut RcBox<T>>,
-}
-#[cfg(not(stage0))]
 #[unsafe_no_drop_flag]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
@@ -216,19 +187,9 @@ pub struct Rc<T: ?Sized> {
     _ptr: NonZero<*mut RcBox<T>>,
 }
 
-#[cfg(stage0)]
-impl<T> !marker::Send for Rc<T> {}
-
-#[cfg(not(stage0))]
 impl<T: ?Sized> !marker::Send for Rc<T> {}
-
-#[cfg(stage0)]
-impl<T> !marker::Sync for Rc<T> {}
-
-#[cfg(not(stage0))]
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
-#[cfg(not(stage0))]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
 impl<T> Rc<T> {
@@ -249,7 +210,7 @@ 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(boxed::into_raw(box RcBox {
+                _ptr: NonZero::new(Box::into_raw(box RcBox {
                     strong: Cell::new(1),
                     weak: Cell::new(1),
                     value: value
@@ -257,71 +218,134 @@ impl<T> Rc<T> {
             }
         }
     }
+
+    /// Unwraps the contained value if the `Rc<T>` is unique.
+    ///
+    /// If the `Rc<T>` is not unique, an `Err` is returned with the same
+    /// `Rc<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(rc_unique)]
+    /// use std::rc::Rc;
+    ///
+    /// let x = Rc::new(3);
+    /// assert_eq!(Rc::try_unwrap(x), Ok(3));
+    ///
+    /// let x = Rc::new(4);
+    /// let _y = x.clone();
+    /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
+    /// ```
+    #[inline]
+    #[unstable(feature = "rc_unique")]
+    pub fn try_unwrap(rc: Rc<T>) -> Result<T, Rc<T>> {
+        if Rc::is_unique(&rc) {
+            unsafe {
+                let val = ptr::read(&*rc); // copy the contained object
+                // destruct the box and skip our Drop
+                // we can ignore the refcounts because we know we're unique
+                deallocate(*rc._ptr as *mut u8, size_of::<RcBox<T>>(),
+                            align_of::<RcBox<T>>());
+                forget(rc);
+                Ok(val)
+            }
+        } else {
+            Err(rc)
+        }
+    }
 }
 
-#[cfg(not(stage0))]
 impl<T: ?Sized> Rc<T> {
     /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_weak)]
     /// use std::rc::Rc;
     ///
     /// let five = Rc::new(5);
     ///
     /// let weak_five = five.downgrade();
     /// ```
-    #[unstable(feature = "alloc",
+    #[unstable(feature = "rc_weak",
                reason = "Weak pointers may not belong in this module")]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
         Weak { _ptr: self._ptr }
     }
-}
 
-#[cfg(stage0)]
-impl<T> Rc<T> {
-    /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
+    /// Get the number of weak references to this value.
+    #[inline]
+    #[unstable(feature = "rc_counts")]
+    pub fn weak_count(this: &Rc<T>) -> usize { this.weak() - 1 }
+
+    /// Get the number of strong references to this value.
+    #[inline]
+    #[unstable(feature = "rc_counts")]
+    pub fn strong_count(this: &Rc<T>) -> usize { this.strong() }
+
+    /// Returns true if there are no other `Rc` or `Weak<T>` values that share
+    /// the same inner value.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_unique)]
     /// use std::rc::Rc;
     ///
     /// let five = Rc::new(5);
     ///
-    /// let weak_five = five.downgrade();
+    /// assert!(Rc::is_unique(&five));
     /// ```
-    #[unstable(feature = "alloc",
-               reason = "Weak pointers may not belong in this module")]
-    pub fn downgrade(&self) -> Weak<T> {
-        self.inc_weak();
-        Weak { _ptr: self._ptr }
+    #[inline]
+    #[unstable(feature = "rc_unique")]
+    pub fn is_unique(rc: &Rc<T>) -> bool {
+        Rc::weak_count(rc) == 0 && Rc::strong_count(rc) == 1
+    }
+
+    /// Returns a mutable reference to the contained value if the `Rc<T>` is
+    /// unique.
+    ///
+    /// Returns `None` if the `Rc<T>` is not unique.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(rc_unique)]
+    /// use std::rc::Rc;
+    ///
+    /// let mut x = Rc::new(3);
+    /// *Rc::get_mut(&mut x).unwrap() = 4;
+    /// assert_eq!(*x, 4);
+    ///
+    /// let _y = x.clone();
+    /// assert!(Rc::get_mut(&mut x).is_none());
+    /// ```
+    #[inline]
+    #[unstable(feature = "rc_unique")]
+    pub fn get_mut(rc: &mut Rc<T>) -> Option<&mut T> {
+        if Rc::is_unique(rc) {
+            let inner = unsafe { &mut **rc._ptr };
+            Some(&mut inner.value)
+        } else {
+            None
+        }
     }
 }
 
 /// Get the number of weak references to this value.
-#[cfg(stage0)]
-#[inline]
-#[unstable(feature = "alloc")]
-pub fn weak_count<T>(this: &Rc<T>) -> usize { this.weak() - 1 }
-#[cfg(not(stage0))]
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn weak_count<T: ?Sized>(this: &Rc<T>) -> usize { this.weak() - 1 }
+#[unstable(feature = "rc_counts")]
+#[deprecated(since = "1.2.0", reason = "renamed to Rc::weak_count")]
+pub fn weak_count<T: ?Sized>(this: &Rc<T>) -> usize { Rc::weak_count(this) }
 
 /// Get the number of strong references to this value.
-#[cfg(stage0)]
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn strong_count<T>(this: &Rc<T>) -> usize { this.strong() }
-#[cfg(not(stage0))]
-#[inline]
-#[unstable(feature = "alloc")]
-pub fn strong_count<T: ?Sized>(this: &Rc<T>) -> usize { this.strong() }
+#[unstable(feature = "rc_counts")]
+#[deprecated(since = "1.2.0", reason = "renamed to Rc::strong_count")]
+pub fn strong_count<T: ?Sized>(this: &Rc<T>) -> usize { Rc::strong_count(this) }
 
 /// Returns true if there are no other `Rc` or `Weak<T>` values that share the
 /// same inner value.
@@ -329,7 +353,7 @@ pub fn strong_count<T: ?Sized>(this: &Rc<T>) -> usize { this.strong() }
 /// # Examples
 ///
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(rc_unique)]
 /// use std::rc;
 /// use std::rc::Rc;
 ///
@@ -338,10 +362,9 @@ pub fn strong_count<T: ?Sized>(this: &Rc<T>) -> usize { this.strong() }
 /// rc::is_unique(&five);
 /// ```
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn is_unique<T>(rc: &Rc<T>) -> bool {
-    weak_count(rc) == 0 && strong_count(rc) == 1
-}
+#[unstable(feature = "rc_unique")]
+#[deprecated(since = "1.2.0", reason = "renamed to Rc::is_unique")]
+pub fn is_unique<T>(rc: &Rc<T>) -> bool { Rc::is_unique(rc) }
 
 /// Unwraps the contained value if the `Rc<T>` is unique.
 ///
@@ -350,7 +373,7 @@ pub fn is_unique<T>(rc: &Rc<T>) -> bool {
 /// # Examples
 ///
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(rc_unique)]
 /// use std::rc::{self, Rc};
 ///
 /// let x = Rc::new(3);
@@ -361,22 +384,9 @@ pub fn is_unique<T>(rc: &Rc<T>) -> bool {
 /// assert_eq!(rc::try_unwrap(x), Err(Rc::new(4)));
 /// ```
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
-    if is_unique(&rc) {
-        unsafe {
-            let val = ptr::read(&*rc); // copy the contained object
-            // destruct the box and skip our Drop
-            // we can ignore the refcounts because we know we're unique
-            deallocate(*rc._ptr as *mut u8, size_of::<RcBox<T>>(),
-                        min_align_of::<RcBox<T>>());
-            forget(rc);
-            Ok(val)
-        }
-    } else {
-        Err(rc)
-    }
-}
+#[unstable(feature = "rc_unique")]
+#[deprecated(since = "1.2.0", reason = "renamed to Rc::try_unwrap")]
+pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> { Rc::try_unwrap(rc) }
 
 /// Returns a mutable reference to the contained value if the `Rc<T>` is unique.
 ///
@@ -385,7 +395,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
 /// # Examples
 ///
 /// ```
-/// # #![feature(alloc)]
+/// # #![feature(rc_unique)]
 /// use std::rc::{self, Rc};
 ///
 /// let mut x = Rc::new(3);
@@ -396,15 +406,9 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
 /// assert!(rc::get_mut(&mut x).is_none());
 /// ```
 #[inline]
-#[unstable(feature = "alloc")]
-pub fn get_mut<T>(rc: &mut Rc<T>) -> Option<&mut T> {
-    if is_unique(rc) {
-        let inner = unsafe { &mut **rc._ptr };
-        Some(&mut inner.value)
-    } else {
-        None
-    }
-}
+#[unstable(feature = "rc_unique")]
+#[deprecated(since = "1.2.0", reason = "renamed to Rc::get_mut")]
+pub fn get_mut<T>(rc: &mut Rc<T>) -> Option<&mut T> { Rc::get_mut(rc) }
 
 impl<T: Clone> Rc<T> {
     /// Make a mutable reference from the given `Rc<T>`.
@@ -415,7 +419,7 @@ impl<T: Clone> Rc<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_unique)]
     /// use std::rc::Rc;
     ///
     /// let mut five = Rc::new(5);
@@ -423,9 +427,9 @@ impl<T: Clone> Rc<T> {
     /// let mut_five = five.make_unique();
     /// ```
     #[inline]
-    #[unstable(feature = "alloc")]
+    #[unstable(feature = "rc_unique")]
     pub fn make_unique(&mut self) -> &mut T {
-        if !is_unique(self) {
+        if !Rc::is_unique(self) {
             *self = Rc::new((**self).clone())
         }
         // This unsafety is ok because we're guaranteed that the pointer
@@ -438,17 +442,6 @@ impl<T: Clone> Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Deref for Rc<T> {
-    type Target = T;
-
-    #[inline(always)]
-    fn deref(&self) -> &T {
-        &self.inner().value
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Rc<T> {
     type Target = T;
@@ -459,58 +452,6 @@ impl<T: ?Sized> Deref for Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for Rc<T> {
-    /// Drops the `Rc<T>`.
-    ///
-    /// This will decrement the strong reference count. If the strong reference
-    /// count becomes zero and the only other references are `Weak<T>` ones,
-    /// `drop`s the inner value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(alloc)]
-    /// use std::rc::Rc;
-    ///
-    /// {
-    ///     let five = Rc::new(5);
-    ///
-    ///     // stuff
-    ///
-    ///     drop(five); // explicit drop
-    /// }
-    /// {
-    ///     let five = Rc::new(5);
-    ///
-    ///     // stuff
-    ///
-    /// } // implicit drop
-    /// ```
-    fn drop(&mut self) {
-        unsafe {
-            let ptr = *self._ptr;
-            if !ptr.is_null() && ptr as usize != mem::POST_DROP_USIZE {
-                self.dec_strong();
-                if self.strong() == 0 {
-                    ptr::read(&**self); // destroy the contained object
-
-                    // remove the implicit "strong weak" pointer now that we've
-                    // destroyed the contents.
-                    self.dec_weak();
-
-                    if self.weak() == 0 {
-                        deallocate(ptr as *mut u8, size_of::<RcBox<T>>(),
-                                   min_align_of::<RcBox<T>>())
-                    }
-                }
-            }
-        }
-    }
-}
-
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for Rc<T> {
     /// Drops the `Rc<T>`.
@@ -522,7 +463,6 @@ impl<T: ?Sized> Drop for Rc<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
     /// use std::rc::Rc;
     ///
     /// {
@@ -543,7 +483,7 @@ impl<T: ?Sized> Drop for Rc<T> {
         unsafe {
             let ptr = *self._ptr;
             if !(*(&ptr as *const _ as *const *const ())).is_null() &&
-               ptr 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
@@ -556,7 +496,7 @@ impl<T: ?Sized> Drop for Rc<T> {
                     if self.weak() == 0 {
                         deallocate(ptr as *mut u8,
                                    size_of_val(&*ptr),
-                                   min_align_of_val(&*ptr))
+                                   align_of_val(&*ptr))
                     }
                 }
             }
@@ -564,32 +504,6 @@ impl<T: ?Sized> Drop for Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for Rc<T> {
-
-    /// Makes a clone of the `Rc<T>`.
-    ///
-    /// When you clone an `Rc<T>`, it will create another pointer to the data and
-    /// increase the strong reference counter.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(alloc)]
-    /// use std::rc::Rc;
-    ///
-    /// let five = Rc::new(5);
-    ///
-    /// five.clone();
-    /// ```
-    #[inline]
-    fn clone(&self) -> Rc<T> {
-        self.inc_strong();
-        Rc { _ptr: self._ptr }
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Clone for Rc<T> {
 
@@ -601,7 +515,6 @@ impl<T: ?Sized> Clone for Rc<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
     /// use std::rc::Rc;
     ///
     /// let five = Rc::new(5);
@@ -634,7 +547,7 @@ impl<T: Default> Default for Rc<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialEq> PartialEq for Rc<T> {
+impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
     /// Equality for two `Rc<T>`s.
     ///
     /// Two `Rc<T>`s are equal if their inner value are equal.
@@ -669,10 +582,10 @@ impl<T: PartialEq> PartialEq for Rc<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq> Eq for Rc<T> {}
+impl<T: ?Sized + Eq> Eq for Rc<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialOrd> PartialOrd for Rc<T> {
+impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
     /// Partial comparison for two `Rc<T>`s.
     ///
     /// The two are compared by calling `partial_cmp()` on their inner values.
@@ -757,7 +670,7 @@ impl<T: PartialOrd> PartialOrd for Rc<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Ord for Rc<T> {
+impl<T: ?Sized + Ord> Ord for Rc<T> {
     /// Comparison for two `Rc<T>`s.
     ///
     /// The two are compared by calling `cmp()` on their inner values.
@@ -775,14 +688,6 @@ impl<T: Ord> Ord for Rc<T> {
     fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Hash> Hash for Rc<T> {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized+Hash> Hash for Rc<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -790,14 +695,6 @@ impl<T: ?Sized+Hash> Hash for Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Display> fmt::Display for Rc<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&**self, f)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized+fmt::Display> fmt::Display for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -805,14 +702,6 @@ impl<T: ?Sized+fmt::Display> fmt::Display for Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for Rc<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&**self, f)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized+fmt::Debug> fmt::Debug for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -833,18 +722,8 @@ impl<T> fmt::Pointer for Rc<T> {
 /// dropped.
 ///
 /// See the [module level documentation](./index.html) for more.
-#[cfg(stage0)]
-#[unsafe_no_drop_flag]
-#[unstable(feature = "alloc",
-           reason = "Weak pointers may not belong in this module.")]
-pub struct Weak<T> {
-    // FIXME #12808: strange names to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut RcBox<T>>,
-}
-#[cfg(not(stage0))]
 #[unsafe_no_drop_flag]
-#[unstable(feature = "alloc",
+#[unstable(feature = "rc_weak",
            reason = "Weak pointers may not belong in this module.")]
 pub struct Weak<T: ?Sized> {
     // FIXME #12808: strange names to try to avoid interfering with
@@ -852,52 +731,10 @@ pub struct Weak<T: ?Sized> {
     _ptr: NonZero<*mut RcBox<T>>,
 }
 
-#[cfg(stage0)]
-impl<T> !marker::Send for Weak<T> {}
-#[cfg(not(stage0))]
 impl<T: ?Sized> !marker::Send for Weak<T> {}
-
-#[cfg(stage0)]
-impl<T> !marker::Sync for Weak<T> {}
-#[cfg(not(stage0))]
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
-
-#[cfg(stage0)]
-#[unstable(feature = "alloc",
-           reason = "Weak pointers may not belong in this module.")]
-impl<T> Weak<T> {
-
-    /// Upgrades a weak reference to a strong reference.
-    ///
-    /// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
-    ///
-    /// Returns `None` if there were no strong references and the data was
-    /// destroyed.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(alloc)]
-    /// use std::rc::Rc;
-    ///
-    /// let five = Rc::new(5);
-    ///
-    /// let weak_five = five.downgrade();
-    ///
-    /// let strong_five: Option<Rc<_>> = weak_five.upgrade();
-    /// ```
-    pub fn upgrade(&self) -> Option<Rc<T>> {
-        if self.strong() == 0 {
-            None
-        } else {
-            self.inc_strong();
-            Some(Rc { _ptr: self._ptr })
-        }
-    }
-}
-#[cfg(not(stage0))]
-#[unstable(feature = "alloc",
+#[unstable(feature = "rc_weak",
            reason = "Weak pointers may not belong in this module.")]
 impl<T: ?Sized> Weak<T> {
 
@@ -911,7 +748,7 @@ impl<T: ?Sized> Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_weak)]
     /// use std::rc::Rc;
     ///
     /// let five = Rc::new(5);
@@ -930,52 +767,6 @@ impl<T: ?Sized> Weak<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for Weak<T> {
-    /// Drops the `Weak<T>`.
-    ///
-    /// This will decrement the weak reference count.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(alloc)]
-    /// use std::rc::Rc;
-    ///
-    /// {
-    ///     let five = Rc::new(5);
-    ///     let weak_five = five.downgrade();
-    ///
-    ///     // stuff
-    ///
-    ///     drop(weak_five); // explicit drop
-    /// }
-    /// {
-    ///     let five = Rc::new(5);
-    ///     let weak_five = five.downgrade();
-    ///
-    ///     // stuff
-    ///
-    /// } // implicit drop
-    /// ```
-    fn drop(&mut self) {
-        unsafe {
-            let ptr = *self._ptr;
-            if !ptr.is_null() && ptr 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::<RcBox<T>>(),
-                               min_align_of::<RcBox<T>>())
-                }
-            }
-        }
-    }
-}
-
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
@@ -985,7 +776,7 @@ impl<T: ?Sized> Drop for Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_weak)]
     /// use std::rc::Rc;
     ///
     /// {
@@ -1008,46 +799,20 @@ impl<T: ?Sized> Drop for Weak<T> {
         unsafe {
             let ptr = *self._ptr;
             if !(*(&ptr as *const _ as *const *const ())).is_null() &&
-               ptr 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),
-                               min_align_of_val(&*ptr))
+                               align_of_val(&*ptr))
                 }
             }
         }
     }
 }
 
-#[cfg(stage0)]
-#[unstable(feature = "alloc",
-           reason = "Weak pointers may not belong in this module.")]
-impl<T> Clone for Weak<T> {
-
-    /// Makes a clone of the `Weak<T>`.
-    ///
-    /// This increases the weak reference count.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(alloc)]
-    /// use std::rc::Rc;
-    ///
-    /// let weak_five = Rc::new(5).downgrade();
-    ///
-    /// weak_five.clone();
-    /// ```
-    #[inline]
-    fn clone(&self) -> Weak<T> {
-        self.inc_weak();
-        Weak { _ptr: self._ptr }
-    }
-}
-#[cfg(not(stage0))]
-#[unstable(feature = "alloc",
+#[unstable(feature = "rc_weak",
            reason = "Weak pointers may not belong in this module.")]
 impl<T: ?Sized> Clone for Weak<T> {
 
@@ -1058,7 +823,7 @@ impl<T: ?Sized> Clone for Weak<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc)]
+    /// # #![feature(rc_weak)]
     /// use std::rc::Rc;
     ///
     /// let weak_five = Rc::new(5).downgrade();
@@ -1072,14 +837,6 @@ impl<T: ?Sized> Clone for Weak<T> {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for Weak<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "(Weak)")
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized+fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -1087,30 +844,6 @@ impl<T: ?Sized+fmt::Debug> fmt::Debug for Weak<T> {
     }
 }
 
-#[cfg(stage0)]
-#[doc(hidden)]
-trait RcBoxPtr<T> {
-    fn inner(&self) -> &RcBox<T>;
-
-    #[inline]
-    fn strong(&self) -> usize { self.inner().strong.get() }
-
-    #[inline]
-    fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
-
-    #[inline]
-    fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
-
-    #[inline]
-    fn weak(&self) -> usize { self.inner().weak.get() }
-
-    #[inline]
-    fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); }
-
-    #[inline]
-    fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
-}
-#[cfg(not(stage0))]
 #[doc(hidden)]
 trait RcBoxPtr<T: ?Sized> {
     fn inner(&self) -> &RcBox<T>;
@@ -1134,21 +867,6 @@ trait RcBoxPtr<T: ?Sized> {
     fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
 }
 
-#[cfg(stage0)]
-impl<T> RcBoxPtr<T> for Rc<T> {
-    #[inline(always)]
-    fn inner(&self) -> &RcBox<T> {
-        unsafe {
-            // Safe to assume this here, as if it weren't true, we'd be breaking
-            // the contract anyway.
-            // This allows the null check to be elided in the destructor if we
-            // manipulated the reference count in the same function.
-            assume(!(*(&self._ptr as *const _ as *const *const ())).is_null());
-            &(**self._ptr)
-        }
-    }
-}
-#[cfg(not(stage0))]
 impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
     #[inline(always)]
     fn inner(&self) -> &RcBox<T> {
@@ -1163,21 +881,6 @@ impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
     }
 }
 
-#[cfg(stage0)]
-impl<T> RcBoxPtr<T> for Weak<T> {
-    #[inline(always)]
-    fn inner(&self) -> &RcBox<T> {
-        unsafe {
-            // Safe to assume this here, as if it weren't true, we'd be breaking
-            // the contract anyway.
-            // This allows the null check to be elided in the destructor if we
-            // manipulated the reference count in the same function.
-            assume(!(*(&self._ptr as *const _ as *const *const ())).is_null());
-            &(**self._ptr)
-        }
-    }
-}
-#[cfg(not(stage0))]
 impl<T: ?Sized> RcBoxPtr<T> for Weak<T> {
     #[inline(always)]
     fn inner(&self) -> &RcBox<T> {
@@ -1399,4 +1102,9 @@ mod tests {
         assert_eq!(format!("{:?}", foo), "75");
     }
 
+    #[test]
+    fn test_unsized() {
+        let foo: Rc<[i32]> = Rc::new([1, 2, 3]);
+        assert_eq!(foo, foo.clone());
+    }
 }
index adfcca14d8d5a138284b9ab09ee940c8293d3d17..4d064b16ad027ea210d39b2fe0c1028d1d2782c8 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(alloc)]
 #![feature(box_syntax)]
-#![feature(core)]
+#![feature(core_intrinsics)]
+#![feature(heap_api)]
+#![feature(oom)]
+#![feature(ptr_as_ref)]
+#![feature(raw)]
 #![feature(staged_api)]
-#![feature(unboxed_closures)]
 #![cfg_attr(test, feature(test))]
 
 extern crate alloc;
@@ -127,7 +130,7 @@ impl<'longer_than_self> Drop for Arena<'longer_than_self> {
     fn drop(&mut self) {
         unsafe {
             destroy_chunk(&*self.head.borrow());
-            for chunk in &*self.chunks.borrow() {
+            for chunk in self.chunks.borrow().iter() {
                 if !chunk.is_copy.get() {
                     destroy_chunk(chunk);
                 }
@@ -241,7 +244,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
     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::min_align_of::<T>());
+                                            mem::align_of::<T>());
             let ptr = ptr as *mut T;
             ptr::write(&mut (*ptr), op());
             return &mut *ptr;
@@ -297,7 +300,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
             let tydesc = get_tydesc::<T>();
             let (ty_ptr, ptr) =
                 self.alloc_noncopy_inner(mem::size_of::<T>(),
-                                         mem::min_align_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
@@ -390,7 +393,7 @@ struct TypedArenaChunk<T> {
 
 fn calculate_size<T>(capacity: usize) -> usize {
     let mut size = mem::size_of::<TypedArenaChunk<T>>();
-    size = round_up(size, mem::min_align_of::<T>());
+    size = round_up(size, mem::align_of::<T>());
     let elem_size = mem::size_of::<T>();
     let elems_size = elem_size.checked_mul(capacity).unwrap();
     size = size.checked_add(elems_size).unwrap();
@@ -402,7 +405,7 @@ impl<T> 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::min_align_of::<TypedArenaChunk<T>>())
+        let chunk = allocate(size, mem::align_of::<TypedArenaChunk<T>>())
                     as *mut TypedArenaChunk<T>;
         if chunk.is_null() { alloc::oom() }
         (*chunk).next = next;
@@ -428,7 +431,7 @@ impl<T> TypedArenaChunk<T> {
         let size = calculate_size::<T>(self.capacity);
         let self_ptr: *mut TypedArenaChunk<T> = self;
         deallocate(self_ptr as *mut u8, size,
-                   mem::min_align_of::<TypedArenaChunk<T>>());
+                   mem::align_of::<TypedArenaChunk<T>>());
         if !next.is_null() {
             let capacity = (*next).capacity;
             (*next).destroy(capacity);
@@ -441,7 +444,7 @@ impl<T> TypedArenaChunk<T> {
         let this: *const TypedArenaChunk<T> = self;
         unsafe {
             mem::transmute(round_up(this.offset(1) as usize,
-                                    mem::min_align_of::<T>()))
+                                    mem::align_of::<T>()))
         }
     }
 
index 00e4002f82f4f296bd5ec30b321baf068d4db10f..f6204173ed7a57c6ff59f9fdfa3a3d97636b55a8 100644 (file)
 
 //! A priority queue implemented with a binary heap.
 //!
-//! Insertion and popping the largest element have `O(log n)` time complexity. Checking the largest
-//! element is `O(1)`. Converting a vector to a binary heap can be done in-place, and has `O(n)`
-//! complexity. A binary heap can also be converted to a sorted vector in-place, allowing it to
-//! be used for an `O(n log n)` in-place heapsort.
+//! Insertion and popping the largest element have `O(log n)` time complexity.
+//! Checking the largest element is `O(1)`. Converting a vector to a binary heap
+//! can be done in-place, and has `O(n)` complexity. A binary heap can also be
+//! converted to a sorted vector in-place, allowing it to be used for an `O(n
+//! log n)` in-place heapsort.
 //!
 //! # Examples
 //!
@@ -85,7 +86,7 @@
 //!
 //!         // For each node we can reach, see if we can find a way with
 //!         // a lower cost going through this node
-//!         for edge in adj_list[position].iter() {
+//!         for edge in &adj_list[position] {
 //!             let next = State { cost: cost + edge.cost, position: edge.node };
 //!
 //!             // If so, add it to the frontier and continue
@@ -450,7 +451,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// let vec = heap.into_vec();
     ///
     /// // Will print in some order
-    /// for x in vec.iter() {
+    /// for x in vec {
     ///     println!("{}", x);
     /// }
     /// ```
@@ -539,8 +540,9 @@ impl<T: Ord> BinaryHeap<T> {
     ///
     /// The elements are removed in arbitrary order.
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
+    #[unstable(feature = "drain",
+               reason = "matches collection reform specification, \
+                         waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain { iter: self.data.drain(..) }
     }
@@ -678,7 +680,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// An iterator that drains a `BinaryHeap`.
-#[unstable(feature = "collections", reason = "recent addition")]
+#[unstable(feature = "drain", reason = "recent addition")]
 pub struct Drain<'a, T: 'a> {
     iter: vec::Drain<'a, T>,
 }
@@ -760,3 +762,10 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> {
         }
     }
 }
+
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
+    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
index 8ec4a68f2b14b7c6334a24f8a10cd33676d61fd9..51914900fdd9978fb1e95555ac6b459d7f5a82b9 100644 (file)
@@ -38,7 +38,7 @@
 //! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
 //!
 //! ```
-//! # #![feature(collections, core, step_by)]
+//! # #![feature(bitset, bitvec, range_inclusive, step_by)]
 //! use std::collections::{BitSet, BitVec};
 //! use std::iter;
 //!
@@ -86,6 +86,7 @@ use core::cmp::Ordering;
 use core::cmp;
 use core::fmt;
 use core::hash;
+#[allow(deprecated)]
 use core::iter::RandomAccessIterator;
 use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned};
 use core::iter::{self, FromIterator};
@@ -125,15 +126,15 @@ fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWo
     }
 }
 
-static TRUE: bool = true;
-static FALSE: bool = false;
+const TRUE: &'static bool = &true;
+const FALSE: &'static bool = &false;
 
 /// The bitvector type.
 ///
 /// # Examples
 ///
 /// ```
-/// # #![feature(collections)]
+/// # #![feature(bitvec)]
 /// use std::collections::BitVec;
 ///
 /// let mut bv = BitVec::from_elem(10, false);
@@ -156,8 +157,7 @@ static FALSE: bool = false;
 /// println!("{:?}", bv);
 /// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
 /// ```
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 pub struct BitVec {
     /// Internal representation of the bit vector
     storage: Vec<u32>,
@@ -172,23 +172,25 @@ impl Index<usize> for BitVec {
     #[inline]
     fn index(&self, i: usize) -> &bool {
         if self.get(i).expect("index out of bounds") {
-            &TRUE
+            TRUE
         } else {
-            &FALSE
+            FALSE
         }
     }
 }
 
 /// Computes how many blocks are needed to store that many bits
 fn blocks_for_bits(bits: usize) -> usize {
-    // If we want 17 bits, dividing by 32 will produce 0. So we add 1 to make sure we
-    // reserve enough. But if we want exactly a multiple of 32, this will actually allocate
-    // one too many. So we need to check if that's the case. We can do that by computing if
-    // bitwise AND by `32 - 1` is 0. But LLVM should be able to optimize the semantically
-    // superior modulo operator on a power of two to this.
+    // If we want 17 bits, dividing by 32 will produce 0. So we add 1 to make
+    // sure we reserve enough. But if we want exactly a multiple of 32, this
+    // will actually allocate one too many. So we need to check if that's the
+    // case. We can do that by computing if bitwise AND by `32 - 1` is 0. But
+    // LLVM should be able to optimize the semantically superior modulo operator
+    // on a power of two to this.
     //
     // Note that we can technically avoid this branch with the expression
-    // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX this will overflow.
+    // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX
+    // this will overflow.
     if bits % u32::BITS == 0 {
         bits / u32::BITS
     } else {
@@ -202,6 +204,7 @@ fn mask_for_bits(bits: usize) -> u32 {
     !0 >> (u32::BITS - bits % u32::BITS) % u32::BITS
 }
 
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 impl BitVec {
     /// Applies the given operation to the blocks of self and other, and sets
     /// self to be the result. This relies on the caller not to corrupt the
@@ -248,7 +251,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     /// let mut bv = BitVec::new();
     /// ```
@@ -263,12 +266,12 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
-    /// let mut bv = BitVec::from_elem(10, false);
+    /// let bv = BitVec::from_elem(10, false);
     /// assert_eq!(bv.len(), 10);
-    /// for x in bv.iter() {
+    /// for x in &bv {
     ///     assert_eq!(x, false);
     /// }
     /// ```
@@ -304,7 +307,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let bv = BitVec::from_bytes(&[0b10100000, 0b00010010]);
@@ -347,7 +350,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let bv = BitVec::from_fn(5, |i| { i % 2 == 0 });
@@ -366,7 +369,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let bv = BitVec::from_bytes(&[0b01100000]);
@@ -399,7 +402,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(5, false);
@@ -407,8 +410,6 @@ impl BitVec {
     /// assert_eq!(bv[3], true);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "panic semantics are likely to change in the future")]
     pub fn set(&mut self, i: usize, x: bool) {
         assert!(i < self.nbits);
         let w = i / u32::BITS;
@@ -424,7 +425,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let before = 0b01100000;
@@ -445,7 +446,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let before = 0b01100000;
@@ -474,7 +475,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let a   = 0b01100100;
@@ -505,7 +506,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let a   = 0b01100100;
@@ -536,7 +537,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let a   = 0b01100100;
@@ -566,7 +567,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(5, true);
@@ -591,7 +592,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let bv = BitVec::from_bytes(&[0b01110100, 0b10010010]);
@@ -608,7 +609,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_vec_append_split_off)]
+    /// # #![feature(bitvec, append)]
     /// use std::collections::BitVec;
     ///
     /// let mut a = BitVec::from_bytes(&[0b10000000]);
@@ -621,7 +622,7 @@ impl BitVec {
     /// assert!(a.eq_vec(&[true, false, false, false, false, false, false, false,
     ///                    false, true, true, false, false, false, false, true]));
     /// ```
-    #[unstable(feature = "bit_vec_append_split_off",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         let b = self.len() % u32::BITS;
@@ -651,7 +652,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_vec_append_split_off)]
+    /// # #![feature(bitvec, split_off)]
     /// use std::collections::BitVec;
     /// let mut a = BitVec::new();
     /// a.push(true);
@@ -666,7 +667,7 @@ impl BitVec {
     /// assert!(a.eq_vec(&[true, false]));
     /// assert!(b.eq_vec(&[false, true]));
     /// ```
-    #[unstable(feature = "bit_vec_append_split_off",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         assert!(at <= self.len(), "`at` out of bounds");
@@ -712,7 +713,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(10, false);
@@ -730,7 +731,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(10, false);
@@ -752,7 +753,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(3, true);
@@ -800,7 +801,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let bv = BitVec::from_bytes(&[0b10100000]);
@@ -821,7 +822,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_bytes(&[0b01001011]);
@@ -848,7 +849,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(3, false);
@@ -879,7 +880,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_elem(3, false);
@@ -902,7 +903,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::new();
@@ -924,7 +925,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_bytes(&[0b01001011]);
@@ -975,7 +976,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::from_bytes(&[0b01001001]);
@@ -1006,7 +1007,7 @@ impl BitVec {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitvec)]
     /// use std::collections::BitVec;
     ///
     /// let mut bv = BitVec::new();
@@ -1070,6 +1071,13 @@ impl Extend<bool> for BitVec {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a> Extend<&'a bool> for BitVec {
+    fn extend<I: IntoIterator<Item=&'a bool>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Clone for BitVec {
     #[inline]
@@ -1181,6 +1189,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> {
 impl<'a> ExactSizeIterator for Iter<'a> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl<'a> RandomAccessIterator for Iter<'a> {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1217,7 +1226,7 @@ impl<'a> IntoIterator for &'a BitVec {
 /// # Examples
 ///
 /// ```
-/// # #![feature(collections)]
+/// # #![feature(bitvec, bitset)]
 /// use std::collections::{BitSet, BitVec};
 ///
 /// // It's a regular set
@@ -1238,7 +1247,7 @@ impl<'a> IntoIterator for &'a BitVec {
 /// s.union_with(&other);
 ///
 /// // Print 0, 1, 3 in some order
-/// for x in s.iter() {
+/// for x in &s {
 ///     println!("{}", x);
 /// }
 ///
@@ -1247,8 +1256,7 @@ impl<'a> IntoIterator for &'a BitVec {
 /// assert!(bv[3]);
 /// ```
 #[derive(Clone)]
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitset", reason = "RFC 509")]
 pub struct BitSet {
     bit_vec: BitVec,
 }
@@ -1278,6 +1286,13 @@ impl Extend<usize> for BitSet {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a> Extend<&'a usize> for BitSet {
+    fn extend<I: IntoIterator<Item=&'a usize>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for BitSet {
     #[inline]
@@ -1308,13 +1323,14 @@ impl cmp::PartialEq for BitSet {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::Eq for BitSet {}
 
+#[unstable(feature = "bitset", reason = "RFC 509")]
 impl BitSet {
     /// Creates a new empty `BitSet`.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1331,7 +1347,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::with_capacity(100);
@@ -1349,14 +1365,14 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let bv = BitVec::from_bytes(&[0b01100000]);
     /// let s = BitSet::from_bit_vec(bv);
     ///
     /// // Print 1, 2 in arbitrary order
-    /// for x in s.iter() {
+    /// for x in &s {
     ///     println!("{}", x);
     /// }
     /// ```
@@ -1371,7 +1387,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::with_capacity(100);
@@ -1383,9 +1399,9 @@ impl BitSet {
         self.bit_vec.capacity()
     }
 
-    /// Reserves capacity for the given `BitSet` to contain `len` distinct elements. In the case
-    /// of `BitSet` this means reallocations will not occur as long as all inserted elements
-    /// are less than `len`.
+    /// Reserves capacity for the given `BitSet` to contain `len` distinct
+    /// elements. In the case of `BitSet` this means reallocations will not
+    /// occur as long as all inserted elements are less than `len`.
     ///
     /// The collection may reserve more space to avoid frequent reallocations.
     ///
@@ -1393,7 +1409,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1408,19 +1424,19 @@ impl BitSet {
         }
     }
 
-    /// Reserves the minimum capacity for the given `BitSet` to contain `len` distinct elements.
-    /// In the case of `BitSet` this means reallocations will not occur as long as all inserted
-    /// elements are less than `len`.
+    /// Reserves the minimum capacity for the given `BitSet` to contain `len`
+    /// distinct elements.  In the case of `BitSet` this means reallocations
+    /// will not occur as long as all inserted elements are less than `len`.
     ///
-    /// Note that the allocator may give the collection more space than it requests. Therefore
-    /// capacity can not be relied upon to be precisely minimal. Prefer `reserve_len` if future
-    /// insertions are expected.
+    /// Note that the allocator may give the collection more space than it
+    /// requests. Therefore capacity can not be relied upon to be precisely
+    /// minimal. Prefer `reserve_len` if future insertions are expected.
     ///
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1441,7 +1457,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1462,7 +1478,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1509,7 +1525,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset)]
     /// use std::collections::BitSet;
     ///
     /// let mut s = BitSet::new();
@@ -1542,7 +1558,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let s = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01001010]));
@@ -1555,7 +1571,7 @@ impl BitSet {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> bit_set::Iter {
-        SetIter {set: self, next_idx: 0}
+        SetIter(BlockIter::from_blocks(self.bit_vec.blocks()))
     }
 
     /// Iterator over each usize stored in `self` union `other`.
@@ -1564,7 +1580,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
@@ -1580,22 +1596,21 @@ impl BitSet {
     pub fn union<'a>(&'a self, other: &'a BitSet) -> Union<'a> {
         fn or(w1: u32, w2: u32) -> u32 { w1 | w2 }
 
-        Union(TwoBitPositions {
-            set: self,
-            other: other,
+        Union(BlockIter::from_blocks(TwoBitPositions {
+            set: self.bit_vec.blocks(),
+            other: other.bit_vec.blocks(),
             merge: or,
-            current_word: 0,
-            next_idx: 0
-        })
+        }))
     }
 
     /// Iterator over each usize stored in `self` intersect `other`.
-    /// See [intersect_with](#method.intersect_with) for an efficient in-place version.
+    /// See [intersect_with](#method.intersect_with) for an efficient in-place
+    /// version.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
@@ -1611,22 +1626,22 @@ impl BitSet {
     pub fn intersection<'a>(&'a self, other: &'a BitSet) -> Intersection<'a> {
         fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 }
         let min = cmp::min(self.bit_vec.len(), other.bit_vec.len());
-        Intersection(TwoBitPositions {
-            set: self,
-            other: other,
+
+        Intersection(BlockIter::from_blocks(TwoBitPositions {
+            set: self.bit_vec.blocks(),
+            other: other.bit_vec.blocks(),
             merge: bitand,
-            current_word: 0,
-            next_idx: 0
-        }.take(min))
+        }).take(min))
     }
 
     /// Iterator over each usize stored in the `self` setminus `other`.
-    /// See [difference_with](#method.difference_with) for an efficient in-place version.
+    /// See [difference_with](#method.difference_with) for an efficient in-place
+    /// version.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
@@ -1649,23 +1664,22 @@ impl BitSet {
     pub fn difference<'a>(&'a self, other: &'a BitSet) -> Difference<'a> {
         fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 }
 
-        Difference(TwoBitPositions {
-            set: self,
-            other: other,
+        Difference(BlockIter::from_blocks(TwoBitPositions {
+            set: self.bit_vec.blocks(),
+            other: other.bit_vec.blocks(),
             merge: diff,
-            current_word: 0,
-            next_idx: 0
-        })
+        }))
     }
 
-    /// Iterator over each usize stored in the symmetric difference of `self` and `other`.
-    /// See [symmetric_difference_with](#method.symmetric_difference_with) for
-    /// an efficient in-place version.
+    /// Iterator over each usize stored in the symmetric difference of `self`
+    /// and `other`.  See
+    /// [symmetric_difference_with](#method.symmetric_difference_with) for an
+    /// efficient in-place version.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
@@ -1681,13 +1695,11 @@ impl BitSet {
     pub fn symmetric_difference<'a>(&'a self, other: &'a BitSet) -> SymmetricDifference<'a> {
         fn bitxor(w1: u32, w2: u32) -> u32 { w1 ^ w2 }
 
-        SymmetricDifference(TwoBitPositions {
-            set: self,
-            other: other,
+        SymmetricDifference(BlockIter::from_blocks(TwoBitPositions {
+            set: self.bit_vec.blocks(),
+            other: other.bit_vec.blocks(),
             merge: bitxor,
-            current_word: 0,
-            next_idx: 0
-        })
+        }))
     }
 
     /// Unions in-place with the specified other bit vector.
@@ -1695,7 +1707,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a   = 0b01101000;
@@ -1719,7 +1731,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a   = 0b01101000;
@@ -1744,7 +1756,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a   = 0b01101000;
@@ -1777,7 +1789,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(bitset, bitvec)]
     /// use std::collections::{BitSet, BitVec};
     ///
     /// let a   = 0b01101000;
@@ -1801,7 +1813,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_set_append_split_off)]
+    /// # #![feature(bitset, bitvec, append)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let mut a = BitSet::new();
@@ -1819,7 +1831,7 @@ impl BitSet {
     /// assert_eq!(b.len(), 0);
     /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
     /// ```
-    #[unstable(feature = "bit_set_append_split_off",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         self.union_with(other);
@@ -1832,7 +1844,7 @@ impl BitSet {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_set_append_split_off)]
+    /// # #![feature(bitset, bitvec, split_off)]
     /// use std::collections::{BitSet, BitVec};
     /// let mut a = BitSet::new();
     /// a.insert(2);
@@ -1847,7 +1859,7 @@ impl BitSet {
     /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000])));
     /// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010])));
     /// ```
-    #[unstable(feature = "bit_set_append_split_off",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let mut other = BitSet::new();
@@ -1994,98 +2006,114 @@ impl hash::Hash for BitSet {
     }
 }
 
-/// An iterator for `BitSet`.
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SetIter<'a> {
-    set: &'a BitSet,
-    next_idx: usize
+struct BlockIter<T> where T: Iterator<Item=u32> {
+    head: u32,
+    head_offset: usize,
+    tail: T,
+}
+
+impl<'a, T> BlockIter<T> where T: Iterator<Item=u32> {
+    fn from_blocks(mut blocks: T) -> BlockIter<T> {
+        let h = blocks.next().unwrap_or(0);
+        BlockIter {tail: blocks, head: h, head_offset: 0}
+    }
 }
 
 /// An iterator combining two `BitSet` iterators.
 #[derive(Clone)]
 struct TwoBitPositions<'a> {
-    set: &'a BitSet,
-    other: &'a BitSet,
+    set: Blocks<'a>,
+    other: Blocks<'a>,
     merge: fn(u32, u32) -> u32,
-    current_word: u32,
-    next_idx: usize
 }
 
+/// An iterator for `BitSet`.
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Union<'a>(TwoBitPositions<'a>);
+pub struct SetIter<'a>(BlockIter<Blocks<'a>>);
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Intersection<'a>(Take<TwoBitPositions<'a>>);
+pub struct Union<'a>(BlockIter<TwoBitPositions<'a>>);
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Difference<'a>(TwoBitPositions<'a>);
+pub struct Intersection<'a>(Take<BlockIter<TwoBitPositions<'a>>>);
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SymmetricDifference<'a>(TwoBitPositions<'a>);
+pub struct Difference<'a>(BlockIter<TwoBitPositions<'a>>);
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SymmetricDifference<'a>(BlockIter<TwoBitPositions<'a>>);
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for SetIter<'a> {
+impl<'a, T> Iterator for BlockIter<T> where T: Iterator<Item=u32> {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
-        while self.next_idx < self.set.bit_vec.len() {
-            let idx = self.next_idx;
-            self.next_idx += 1;
-
-            if self.set.contains(&idx) {
-                return Some(idx);
+        while self.head == 0 {
+            match self.tail.next() {
+                Some(w) => self.head = w,
+                None => return None
             }
+            self.head_offset += u32::BITS;
         }
 
-        return None;
+        // from the current block, isolate the
+        // LSB and subtract 1, producing k:
+        // a block with a number of set bits
+        // equal to the index of the LSB
+        let k = (self.head & (!self.head + 1)) - 1;
+        // update block, removing the LSB
+        self.head &= self.head - 1;
+        // return offset + (index of LSB)
+        Some(self.head_offset + (u32::count_ones(k) as usize))
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(self.set.bit_vec.len() - self.next_idx))
+        match self.tail.size_hint() {
+            (_, Some(h)) => (0, Some(1 + h * (u32::BITS as usize))),
+            _ => (0, None)
+        }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for TwoBitPositions<'a> {
-    type Item = usize;
-
-    fn next(&mut self) -> Option<usize> {
-        while self.next_idx < self.set.bit_vec.len() ||
-              self.next_idx < self.other.bit_vec.len() {
-            let bit_idx = self.next_idx % u32::BITS;
-            if bit_idx == 0 {
-                let s_bit_vec = &self.set.bit_vec;
-                let o_bit_vec = &self.other.bit_vec;
-                // Merging the two words is a bit of an awkward dance since
-                // one BitVec might be longer than the other
-                let word_idx = self.next_idx / u32::BITS;
-                let w1 = if word_idx < s_bit_vec.storage.len() {
-                             s_bit_vec.storage[word_idx]
-                         } else { 0 };
-                let w2 = if word_idx < o_bit_vec.storage.len() {
-                             o_bit_vec.storage[word_idx]
-                         } else { 0 };
-                self.current_word = (self.merge)(w1, w2);
-            }
-
-            self.next_idx += 1;
-            if self.current_word & (1 << bit_idx) != 0 {
-                return Some(self.next_idx - 1);
-            }
+    type Item = u32;
+
+    fn next(&mut self) -> Option<u32> {
+        match (self.set.next(), self.other.next()) {
+            (Some(a), Some(b)) => Some((self.merge)(a, b)),
+            (Some(a), None) => Some((self.merge)(a, 0)),
+            (None, Some(b)) => Some((self.merge)(0, b)),
+            _ => return None
         }
-        return None;
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let cap = cmp::max(self.set.bit_vec.len(), self.other.bit_vec.len());
-        (0, Some(cap - self.next_idx))
+        let (a, au) = self.set.size_hint();
+        let (b, bu) = self.other.size_hint();
+
+        let upper = match (au, bu) {
+            (Some(au), Some(bu)) => Some(cmp::max(au, bu)),
+            _ => None
+        };
+
+        (cmp::max(a, b), upper)
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Iterator for SetIter<'a> {
+    type Item = usize;
+
+    #[inline] fn next(&mut self) -> Option<usize> { self.0.next() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Union<'a> {
     type Item = usize;
index c40cfe79d81add5d23e923adb910ccafd5e581da..d7242b9077556da112e5bac4bbd9eb40c01485d6 100644 (file)
@@ -124,11 +124,11 @@ impl<T: ?Sized> BorrowMut<T> for boxed::Box<T> {
     fn borrow_mut(&mut self) -> &mut T { &mut **self }
 }
 
-impl<T> Borrow<T> for rc::Rc<T> {
+impl<T: ?Sized> Borrow<T> for rc::Rc<T> {
     fn borrow(&self) -> &T { &**self }
 }
 
-impl<T> Borrow<T> for arc::Arc<T> {
+impl<T: ?Sized> Borrow<T> for arc::Arc<T> {
     fn borrow(&self) -> &T { &**self }
 }
 
index 291b66939e5ef038eab3fc1cb3b4bf4b724b4b8d..27b10213ecd7cacad8c6344072f149f715fd2dc8 100644 (file)
@@ -685,10 +685,7 @@ mod stack {
         /// tied to the original tree.
         pub fn into_top(mut self) -> &'a mut V {
             unsafe {
-                mem::copy_mut_lifetime(
-                    self.map,
-                    self.top.from_raw_mut().val_mut()
-                )
+                &mut *(self.top.from_raw_mut().val_mut() as *mut V)
             }
         }
     }
@@ -879,6 +876,13 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> {
+    fn extend<I: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -900,7 +904,7 @@ impl<K: Ord, V> Default for BTreeMap<K, V> {
 impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
     fn eq(&self, other: &BTreeMap<K, V>) -> bool {
         self.len() == other.len() &&
-            self.iter().zip(other.iter()).all(|(a, b)| a == b)
+            self.iter().zip(other).all(|(a, b)| a == b)
     }
 }
 
@@ -926,7 +930,7 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish()
+        f.debug_map().entries(self.iter()).finish()
     }
 }
 
@@ -1144,7 +1148,7 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
 }
 
 impl<'a, K: Ord, V> Entry<'a, K, V> {
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "entry",
                reason = "will soon be replaced by or_insert")]
     #[deprecated(since = "1.0",
                 reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
@@ -1291,14 +1295,13 @@ impl<K, V> BTreeMap<K, V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut a = BTreeMap::new();
     /// a.insert(1, "a");
     /// a.insert(2, "b");
     ///
-    /// let keys: Vec<usize> = a.keys().cloned().collect();
+    /// let keys: Vec<_> = a.keys().cloned().collect();
     /// assert_eq!(keys, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1314,7 +1317,6 @@ impl<K, V> BTreeMap<K, V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut a = BTreeMap::new();
@@ -1502,7 +1504,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(btree_range, collections_bound)]
     /// use std::collections::BTreeMap;
     /// use std::collections::Bound::{Included, Unbounded};
     ///
@@ -1515,7 +1517,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// }
     /// assert_eq!(Some((&5, &"b")), map.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&K>, max: Bound<&K>) -> Range<'a, K, V> {
         range_impl!(&self.root, min, max, as_slices_internal, iter, Range, edges, [])
@@ -1529,7 +1531,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(btree_range, collections_bound)]
     /// use std::collections::BTreeMap;
     /// use std::collections::Bound::{Included, Excluded};
     ///
@@ -1539,11 +1541,11 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// for (_, balance) in map.range_mut(Included(&"B"), Excluded(&"Cheryl")) {
     ///     *balance += 100;
     /// }
-    /// for (name, balance) in map.iter() {
+    /// for (name, balance) in &map {
     ///     println!("{} => {}", name, balance);
     /// }
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range_mut<'a>(&'a mut self, min: Bound<&K>, max: Bound<&K>) -> RangeMut<'a, K, V> {
         range_impl!(&mut self.root, min, max, as_slices_internal_mut, iter_mut, RangeMut,
@@ -1555,7 +1557,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
index bca0e1427e4426ae687d4e7d2f34a499daf0dea6..4d76a986700a25ed316f879c3b43eb261ad83c81 100644 (file)
@@ -19,6 +19,7 @@ pub use self::TraversalItem::*;
 use core::prelude::*;
 
 use core::cmp::Ordering::{Greater, Less, Equal};
+use core::intrinsics::arith_offset;
 use core::iter::Zip;
 use core::marker::PhantomData;
 use core::ops::{Deref, DerefMut, Index, IndexMut};
@@ -162,12 +163,12 @@ fn test_offset_calculation() {
 }
 
 fn calculate_allocation_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize, usize) {
-    let (keys_size, keys_align) = (capacity * mem::size_of::<K>(), mem::min_align_of::<K>());
-    let (vals_size, vals_align) = (capacity * mem::size_of::<V>(), mem::min_align_of::<V>());
+    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)
     } else {
-        ((capacity + 1) * mem::size_of::<Node<K, V>>(), mem::min_align_of::<Node<K, V>>())
+        ((capacity + 1) * mem::size_of::<Node<K, V>>(), mem::align_of::<Node<K, V>>())
     };
 
     calculate_allocation(
@@ -180,11 +181,11 @@ fn calculate_allocation_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize,
 fn calculate_offsets_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize, usize) {
     let keys_size = capacity * mem::size_of::<K>();
     let vals_size = capacity * mem::size_of::<V>();
-    let vals_align = mem::min_align_of::<V>();
+    let vals_align = mem::align_of::<V>();
     let edges_align = if is_leaf {
         1
     } else {
-        mem::min_align_of::<Node<K, V>>()
+        mem::align_of::<Node<K, V>>()
     };
 
     calculate_offsets(
@@ -209,7 +210,7 @@ impl<T> RawItems<T> {
         if mem::size_of::<T>() == 0 {
             RawItems {
                 head: ptr,
-                tail: (ptr as usize + len) as *const T,
+                tail: arith_offset(ptr as *const i8, len as isize) as *const T,
             }
         } else {
             RawItems {
@@ -223,7 +224,7 @@ impl<T> RawItems<T> {
         ptr::write(self.tail as *mut T, val);
 
         if mem::size_of::<T>() == 0 {
-            self.tail = (self.tail as usize + 1) as *const T;
+            self.tail = arith_offset(self.tail as *const i8, 1) as *const T;
         } else {
             self.tail = self.tail.offset(1);
         }
@@ -241,7 +242,7 @@ impl<T> Iterator for RawItems<T> {
                 let ret = Some(ptr::read(self.head));
 
                 if mem::size_of::<T>() == 0 {
-                    self.head = (self.head as usize + 1) as *const T;
+                    self.head = arith_offset(self.head as *const i8, 1) as *const T;
                 } else {
                     self.head = self.head.offset(1);
                 }
@@ -259,7 +260,7 @@ impl<T> DoubleEndedIterator for RawItems<T> {
         } else {
             unsafe {
                 if mem::size_of::<T>() == 0 {
-                    self.tail = (self.tail as usize - 1) as *const T;
+                    self.tail = arith_offset(self.tail as *const i8, -1) as *const T;
                 } else {
                     self.tail = self.tail.offset(-1);
                 }
index fc346151e0b4bf70415f6d36176e1a70130b2a3f..7c4cda305adf2f50281c49f71f0a752363eb1116 100644 (file)
@@ -102,7 +102,7 @@ impl<T: Ord> BTreeSet<T> {
     /// Makes a new BTreeSet with the given B.
     ///
     /// B cannot be less than 2.
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_b",
                reason = "probably want this to be on the type, eventually")]
     pub fn with_b(b: usize) -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::with_b(b) }
@@ -115,7 +115,6 @@ impl<T> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
@@ -124,7 +123,7 @@ impl<T> BTreeSet<T> {
     ///     println!("{}", x);
     /// }
     ///
-    /// let v: Vec<usize> = set.iter().cloned().collect();
+    /// let v: Vec<_> = set.iter().cloned().collect();
     /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -142,7 +141,7 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(btree_range, collections_bound)]
     /// use std::collections::BTreeSet;
     /// use std::collections::Bound::{Included, Unbounded};
     ///
@@ -155,7 +154,7 @@ impl<T: Ord> BTreeSet<T> {
     /// }
     /// assert_eq!(Some(&5), set.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&T>, max: Bound<&T>) -> Range<'a, T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
@@ -171,7 +170,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let mut a = BTreeSet::new();
@@ -182,7 +180,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(2);
     /// b.insert(3);
     ///
-    /// let diff: Vec<usize> = a.difference(&b).cloned().collect();
+    /// let diff: Vec<_> = a.difference(&b).cloned().collect();
     /// assert_eq!(diff, [1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -195,7 +193,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let mut a = BTreeSet::new();
@@ -206,7 +203,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(2);
     /// b.insert(3);
     ///
-    /// let sym_diff: Vec<usize> = a.symmetric_difference(&b).cloned().collect();
+    /// let sym_diff: Vec<_> = a.symmetric_difference(&b).cloned().collect();
     /// assert_eq!(sym_diff, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -220,7 +217,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let mut a = BTreeSet::new();
@@ -231,7 +227,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(2);
     /// b.insert(3);
     ///
-    /// let intersection: Vec<usize> = a.intersection(&b).cloned().collect();
+    /// let intersection: Vec<_> = a.intersection(&b).cloned().collect();
     /// assert_eq!(intersection, [2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -245,7 +241,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let mut a = BTreeSet::new();
@@ -254,7 +249,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let mut b = BTreeSet::new();
     /// b.insert(2);
     ///
-    /// let union: Vec<usize> = a.union(&b).cloned().collect();
+    /// let union: Vec<_> = a.union(&b).cloned().collect();
     /// assert_eq!(union, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -318,7 +313,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
@@ -336,7 +330,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
@@ -358,7 +351,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
@@ -401,7 +393,6 @@ impl<T: Ord> BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect();
@@ -483,12 +474,11 @@ impl<T> IntoIterator for BTreeSet<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::BTreeSet;
     ///
     /// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
     ///
-    /// let v: Vec<usize> = set.into_iter().collect();
+    /// let v: Vec<_> = set.into_iter().collect();
     /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     fn into_iter(self) -> IntoIter<T> {
@@ -519,6 +509,13 @@ impl<T: Ord> Extend<T> for BTreeSet<T> {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet<T> {
+    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Default for BTreeSet<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -622,7 +619,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for BTreeSet<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish()
+        f.debug_set().entries(self.iter()).finish()
     }
 }
 
index e6cdb88d3e1746eb90872a1fb7a2a896a06b4e4f..e90e6c065a2c282f19a80b0220a5e0552c4d07fd 100644 (file)
 //! This module defines a container which uses an efficient bit mask
 //! representation to hold C-like enum variants.
 
+#![unstable(feature = "enumset",
+            reason = "matches collection reform specification, \
+                      waiting for dust to settle")]
+
 use core::prelude::*;
 use core::marker;
 use core::fmt;
 use core::iter::{FromIterator};
 use core::ops::{Sub, BitOr, BitAnd, BitXor};
 
-// FIXME(contentions): implement union family of methods? (general design may be wrong here)
+// FIXME(contentions): implement union family of methods? (general design may be
+// wrong here)
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
 /// A specialized set implementation to use enum types.
 ///
-/// It is a logic error for an item to be modified in such a way that the transformation of the
-/// item to or from a `usize`, as determined by the `CLike` trait, changes while the item is in the
-/// set. This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe
-/// code.
+/// It is a logic error for an item to be modified in such a way that the
+/// transformation of the item to or from a `usize`, as determined by the
+/// `CLike` trait, changes while the item is in the set. This is normally only
+/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct EnumSet<E> {
     // We must maintain the invariant that no bits are set
     // for which no variant exists
@@ -93,22 +98,16 @@ fn bit<E:CLike>(e: &E) -> usize {
 
 impl<E:CLike> EnumSet<E> {
     /// Returns an empty `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn new() -> EnumSet<E> {
         EnumSet {bits: 0, marker: marker::PhantomData}
     }
 
     /// Returns the number of elements in the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn len(&self) -> usize {
         self.bits.count_ones() as usize
     }
 
     /// Returns true if the `EnumSet` is empty.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_empty(&self) -> bool {
         self.bits == 0
     }
@@ -118,22 +117,16 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == 0
     }
 
     /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == other.bits
     }
 
     /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
         other.is_superset(self)
     }
@@ -151,8 +144,6 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn insert(&mut self, e: E) -> bool {
         let result = !self.contains(&e);
         self.bits |= bit(&e);
@@ -160,8 +151,6 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Removes an enum from the EnumSet
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn remove(&mut self, e: &E) -> bool {
         let result = self.contains(e);
         self.bits &= !bit(e);
@@ -169,15 +158,11 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Returns `true` if an `EnumSet` contains a given enum.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn contains(&self, e: &E) -> bool {
         (self.bits & bit(e)) != 0
     }
 
     /// Returns an iterator over an `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn iter(&self) -> Iter<E> {
         Iter::new(self.bits)
     }
@@ -288,3 +273,10 @@ impl<E:CLike> Extend<E> for EnumSet<E> {
         }
     }
 }
+
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, E: 'a + CLike + Copy> Extend<&'a E> for EnumSet<E> {
+    fn extend<I: IntoIterator<Item=&'a E>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
index 80fa6d397c82911852f24658c2ae572cbc80cb6f..72d0ca85357a4274ab9bda81b8823ae41fcae20f 100644 (file)
 //! provides some helper methods.
 //!
 //! Additionally, the return value of this function is `fmt::Result` which is a
-//! typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting
-//! implementations should ensure that they return errors from `write!`
+//! typedef to `Result<(), std::io::Error>` (also known as `std::io::Result<()>`).
+//! Formatting implementations should ensure that they return errors from `write!`
 //! correctly (propagating errors upward).
 //!
 //! An example of implementing the formatting traits would look
 //! like:
 //!
 //! ```
-//! # #![feature(core, std_misc)]
+//! # #![feature(fmt_flags)]
 //! use std::fmt;
-//! use std::f64;
 //!
 //! #[derive(Debug)]
 //! struct Vector2D {
 //! * `^` - the argument is center-aligned in `width` columns
 //! * `>` - the argument is right-aligned in `width` columns
 //!
+//! Note that alignment may not be implemented by some types. A good way
+//! to ensure padding is applied is to format your input, then use this
+//! resulting string to pad your output.
+//!
 //! ## Sign/#/0
 //!
 //! These can all be interpreted as flags for a particular formatter.
index ecbe9369e781f68ccdfd5c9b592a355f80c356aa..8d0f57de4c59585b70c79697c84c4fa4f661e692 100644 (file)
 
 //! Collection types.
 //!
-//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.
+//! See [std::collections](../std/collections) for a detailed discussion of
+//! collections in Rust.
 
 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "collections"]
-#![unstable(feature = "collections")]
 #![staged_api]
 #![crate_type = "rlib"]
+#![unstable(feature = "collections",
+            reason = "library is unlikely to be stabilized with the current \
+                      layout and name, use std::collections instead")]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
-       html_playground_url = "http://play.rust-lang.org/")]
-#![doc(test(no_crate_inject))]
+       html_playground_url = "http://play.rust-lang.org/",
+       test(no_crate_inject))]
 
 #![allow(trivial_casts)]
+#![cfg_attr(test, allow(deprecated))] // rand
+
 #![feature(alloc)]
-#![feature(box_syntax)]
 #![feature(box_patterns)]
+#![feature(box_raw)]
+#![feature(box_syntax)]
 #![feature(core)]
+#![feature(core_intrinsics)]
+#![feature(core_prelude)]
+#![feature(core_slice_ext)]
+#![feature(core_str_ext)]
+#![feature(heap_api)]
+#![feature(iter_cmp)]
+#![feature(iter_idx)]
+#![feature(iter_order)]
+#![feature(iter_arith)]
+#![feature(iter_arith)]
 #![feature(lang_items)]
+#![feature(num_bits_bytes)]
+#![feature(oom)]
+#![feature(pattern)]
+#![feature(ptr_as_ref)]
+#![feature(raw)]
+#![feature(slice_patterns)]
 #![feature(staged_api)]
+#![feature(step_by)]
+#![feature(str_char)]
+#![feature(str_match_indices)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
-#![feature(step_by)]
-#![feature(str_char)]
-#![feature(str_words)]
-#![feature(slice_patterns)]
-#![feature(debug_builders)]
 #![feature(utf8_error)]
-#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections,
-                          collections_drain, collections_range))]
-#![cfg_attr(test, allow(deprecated))] // rand
+#![cfg_attr(test, feature(rand, test))]
+#![cfg_attr(not(test), feature(str_words))]
 
 #![feature(no_std)]
 #![no_std]
@@ -90,14 +109,12 @@ pub mod vec;
 pub mod vec_deque;
 pub mod vec_map;
 
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 pub mod bit_vec {
     pub use bit::{BitVec, Iter};
 }
 
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitset", reason = "RFC 509")]
 pub mod bit_set {
     pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
     pub use bit::SetIter as Iter;
@@ -116,6 +133,7 @@ pub mod btree_set {
 
 // FIXME(#14344) this shouldn't be necessary
 #[doc(hidden)]
+#[unstable(feature = "issue_14344_fixme")]
 pub fn fixme_14344_be_sure_to_link_to_collections() {}
 
 #[cfg(not(test))]
@@ -124,6 +142,7 @@ mod std {
 }
 
 /// An endpoint of a range of keys.
+#[unstable(feature = "collections_bound")]
 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
 pub enum Bound<T> {
     /// An inclusive bound.
index 9aae6192317f1b514f54a7f1a448f9f5b23bd53c..a02cb44896ad3d6406334b60d2c204d144200960 100644 (file)
@@ -104,19 +104,23 @@ impl<T> Rawlink<T> {
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve_immut<'a>(&self) -> Option<&'a T> {
-        unsafe {
-            mem::transmute(self.p.as_ref())
-        }
+    ///
+    /// **unsafe** because:
+    ///
+    /// - Dereference of raw pointer.
+    /// - Returns reference of arbitrary lifetime.
+    unsafe fn resolve<'a>(&self) -> Option<&'a T> {
+        self.p.as_ref()
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve<'a>(&mut self) -> Option<&'a mut T> {
-        if self.p.is_null() {
-            None
-        } else {
-            Some(unsafe { mem::transmute(self.p) })
-        }
+    ///
+    /// **unsafe** because:
+    ///
+    /// - Dereference of raw pointer.
+    /// - Returns reference of arbitrary lifetime.
+    unsafe fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
+        self.p.as_mut()
     }
 
     /// Return the `Rawlink` and replace with `Rawlink::none()`
@@ -125,6 +129,15 @@ impl<T> Rawlink<T> {
     }
 }
 
+impl<'a, T> From<&'a mut Link<T>> for Rawlink<Node<T>> {
+    fn from(node: &'a mut Link<T>) -> Self {
+        match node.as_mut() {
+            None => Rawlink::none(),
+            Some(ptr) => Rawlink::some(ptr),
+        }
+    }
+}
+
 impl<T> Clone for Rawlink<T> {
     #[inline]
     fn clone(&self) -> Rawlink<T> {
@@ -136,12 +149,21 @@ impl<T> Node<T> {
     fn new(v: T) -> Node<T> {
         Node{value: v, next: None, prev: Rawlink::none()}
     }
+
+    /// Update the `prev` link on `next`, then set self's next pointer.
+    ///
+    /// `self.next` should be `None` when you call this
+    /// (otherwise a Node is probably being dropped by mistake).
+    fn set_next(&mut self, mut next: Box<Node<T>>) {
+        debug_assert!(self.next.is_none());
+        next.prev = Rawlink::some(self);
+        self.next = Some(next);
+    }
 }
 
-/// Set the .prev field on `next`, then return `Some(next)`
-fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
-                  -> Link<T> {
-    next.prev = prev;
+/// Clear the .prev field on `next`, then return `Some(next)`
+fn link_no_prev<T>(mut next: Box<Node<T>>) -> Link<T> {
+    next.prev = Rawlink::none();
     Some(next)
 }
 
@@ -152,8 +174,8 @@ impl<T> LinkedList<T> {
     fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
         match self.list_head {
             None => {
-                self.list_tail = Rawlink::some(&mut *new_head);
-                self.list_head = link_with_prev(new_head, Rawlink::none());
+                self.list_head = link_no_prev(new_head);
+                self.list_tail = Rawlink::from(&mut self.list_head);
             }
             Some(ref mut head) => {
                 new_head.prev = Rawlink::none();
@@ -171,7 +193,7 @@ impl<T> LinkedList<T> {
         self.list_head.take().map(|mut front_node| {
             self.length -= 1;
             match front_node.next.take() {
-                Some(node) => self.list_head = link_with_prev(node, Rawlink::none()),
+                Some(node) => self.list_head = link_no_prev(node),
                 None => self.list_tail = Rawlink::none()
             }
             front_node
@@ -180,12 +202,12 @@ impl<T> LinkedList<T> {
 
     /// Add a Node last in the list
     #[inline]
-    fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
-        match self.list_tail.resolve() {
+    fn push_back_node(&mut self, new_tail: Box<Node<T>>) {
+        match unsafe { self.list_tail.resolve_mut() } {
             None => return self.push_front_node(new_tail),
             Some(tail) => {
-                self.list_tail = Rawlink::some(&mut *new_tail);
-                tail.next = link_with_prev(new_tail, Rawlink::some(tail));
+                tail.set_next(new_tail);
+                self.list_tail = Rawlink::from(&mut tail.next);
             }
         }
         self.length += 1;
@@ -194,14 +216,16 @@ impl<T> LinkedList<T> {
     /// Remove the last Node and return it, or None if the list is empty
     #[inline]
     fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
-        self.list_tail.resolve().map_or(None, |tail| {
-            self.length -= 1;
-            self.list_tail = tail.prev;
-            match tail.prev.resolve() {
-                None => self.list_head.take(),
-                Some(tail_prev) => tail_prev.next.take()
-            }
-        })
+        unsafe {
+            self.list_tail.resolve_mut().and_then(|tail| {
+                self.length -= 1;
+                self.list_tail = tail.prev;
+                match tail.prev.resolve_mut() {
+                    None => self.list_head.take(),
+                    Some(tail_prev) => tail_prev.next.take()
+                }
+            })
+        }
     }
 }
 
@@ -230,7 +254,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut a = LinkedList::new();
@@ -242,14 +265,14 @@ impl<T> LinkedList<T> {
     ///
     /// a.append(&mut b);
     ///
-    /// for e in a.iter() {
+    /// for e in &a {
     ///     println!("{}", e); // prints 1, then 2, then 3, then 4
     /// }
     /// println!("{}", b.len()); // prints 0
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, other: &mut LinkedList<T>) {
-        match self.list_tail.resolve() {
+        match unsafe { self.list_tail.resolve_mut() } {
             None => {
                 self.length = other.length;
                 self.list_head = other.list_head.take();
@@ -262,7 +285,7 @@ impl<T> LinkedList<T> {
                 match other.list_head.take() {
                     None => return,
                     Some(node) => {
-                        tail.next = link_with_prev(node, self.list_tail);
+                        tail.set_next(node);
                         self.list_tail = o_tail;
                         self.length += o_length;
                     }
@@ -283,13 +306,9 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
-        let head_raw = match self.list_head {
-            Some(ref mut h) => Rawlink::some(&mut **h),
-            None => Rawlink::none(),
-        };
-        IterMut{
+        IterMut {
             nelem: self.len(),
-            head: head_raw,
+            head: Rawlink::from(&mut self.list_head),
             tail: self.list_tail,
             list: self
         }
@@ -436,7 +455,9 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
-        self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
+        unsafe {
+            self.list_tail.resolve().map(|tail| &tail.value)
+        }
     }
 
     /// Provides a mutable reference to the back element, or `None` if the list
@@ -463,7 +484,9 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
-        self.list_tail.resolve().map(|tail| &mut tail.value)
+        unsafe {
+            self.list_tail.resolve_mut().map(|tail| &mut tail.value)
+        }
     }
 
     /// Adds an element first in the list.
@@ -473,7 +496,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut dl = LinkedList::new();
@@ -521,7 +543,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -540,7 +561,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -566,7 +586,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -610,44 +629,42 @@ impl<T> LinkedList<T> {
             iter.tail
         };
 
-        let mut splitted_list = LinkedList {
-            list_head: None,
+        // The split node is the new tail node of the first part and owns
+        // the head of the second part.
+        let mut second_part_head;
+
+        unsafe {
+            second_part_head = split_node.resolve_mut().unwrap().next.take();
+            match second_part_head {
+                None => {}
+                Some(ref mut head) => head.prev = Rawlink::none(),
+            }
+        }
+
+        let second_part = LinkedList {
+            list_head: second_part_head,
             list_tail: self.list_tail,
             length: len - at
         };
 
-        // Swap split_node.next with list_head (which is None), nulling out split_node.next,
-        // as it is the new tail.
-        mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
-        // Null out list_head.prev. Note this `unwrap` won't fail because if at == len
-        // we already branched out at the top of the fn to return the empty list.
-        splitted_list.list_head.as_mut().unwrap().prev = Rawlink::none();
-        // Fix the tail ptr
+        // Fix the tail ptr of the first part
         self.list_tail = split_node;
         self.length = at;
 
-        splitted_list
+        second_part
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for LinkedList<T> {
     fn drop(&mut self) {
-        // Dissolve the linked_list in backwards direction
+        // Dissolve the linked_list in a loop.
         // Just dropping the list_head can lead to stack exhaustion
         // when length is >> 1_000_000
-        let mut tail = self.list_tail;
-        loop {
-            match tail.resolve() {
-                None => break,
-                Some(prev) => {
-                    prev.next.take(); // release Box<Node<T>>
-                    tail = prev.prev;
-                }
-            }
+        while let Some(mut head_) = self.list_head.take() {
+            self.list_head = head_.next.take();
         }
         self.length = 0;
-        self.list_head = None;
         self.list_tail = Rawlink::none();
     }
 }
@@ -681,11 +698,13 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.tail.resolve_immut().as_ref().map(|prev| {
-            self.nelem -= 1;
-            self.tail = prev.prev;
-            &prev.value
-        })
+        unsafe {
+            self.tail.resolve().map(|prev| {
+                self.nelem -= 1;
+                self.tail = prev.prev;
+                &prev.value
+            })
+        }
     }
 }
 
@@ -700,14 +719,13 @@ impl<'a, A> Iterator for IterMut<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.head.resolve().map(|next| {
-            self.nelem -= 1;
-            self.head = match next.next {
-                Some(ref mut node) => Rawlink::some(&mut **node),
-                None => Rawlink::none(),
-            };
-            &mut next.value
-        })
+        unsafe {
+            self.head.resolve_mut().map(|next| {
+                self.nelem -= 1;
+                self.head = Rawlink::from(&mut next.next);
+                &mut next.value
+            })
+        }
     }
 
     #[inline]
@@ -723,11 +741,13 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.tail.resolve().map(|prev| {
-            self.nelem -= 1;
-            self.tail = prev.prev;
-            &mut prev.value
-        })
+        unsafe {
+            self.tail.resolve_mut().map(|prev| {
+                self.nelem -= 1;
+                self.tail = prev.prev;
+                &mut prev.value
+            })
+        }
     }
 }
 
@@ -741,16 +761,16 @@ impl<'a, A> IterMut<'a, A> {
         // previously yielded element and self.head.
         //
         // The inserted node will not appear in further iteration.
-        match self.head.resolve() {
+        match unsafe { self.head.resolve_mut() } {
             None => { self.list.push_back_node(ins_node); }
             Some(node) => {
-                let prev_node = match node.prev.resolve() {
+                let prev_node = match unsafe { node.prev.resolve_mut() } {
                     None => return self.list.push_front_node(ins_node),
                     Some(prev) => prev,
                 };
                 let node_own = prev_node.next.take().unwrap();
-                ins_node.next = link_with_prev(node_own, Rawlink::some(&mut *ins_node));
-                prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node));
+                ins_node.set_next(node_own);
+                prev_node.set_next(ins_node);
                 self.list.length += 1;
             }
         }
@@ -764,7 +784,7 @@ impl<'a, A> IterMut<'a, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(linked_list_extras)]
     /// use std::collections::LinkedList;
     ///
     /// let mut list: LinkedList<_> = vec![1, 3, 4].into_iter().collect();
@@ -781,7 +801,7 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "linked_list_extras",
                reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn insert_next(&mut self, elt: A) {
         self.insert_next_node(box Node::new(elt))
@@ -792,7 +812,7 @@ impl<'a, A> IterMut<'a, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(linked_list_extras)]
     /// use std::collections::LinkedList;
     ///
     /// let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();
@@ -804,13 +824,15 @@ impl<'a, A> IterMut<'a, A> {
     /// assert_eq!(it.next().unwrap(), &2);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "linked_list_extras",
                reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn peek_next(&mut self) -> Option<&mut A> {
         if self.nelem == 0 {
             return None
         }
-        self.head.resolve().map(|head| &mut head.value)
+        unsafe {
+            self.head.resolve_mut().map(|head| &mut head.value)
+        }
     }
 }
 
@@ -882,6 +904,13 @@ impl<A> Extend<A> for LinkedList<A> {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
+    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialEq> PartialEq for LinkedList<A> {
     fn eq(&self, other: &LinkedList<A>) -> bool {
@@ -923,7 +952,7 @@ impl<A: Clone> Clone for LinkedList<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish()
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
@@ -940,7 +969,7 @@ impl<A: Hash> Hash for LinkedList<A> {
 #[cfg(test)]
 mod tests {
     use std::clone::Clone;
-    use std::iter::{Iterator, IntoIterator};
+    use std::iter::{Iterator, IntoIterator, Extend};
     use std::option::Option::{Some, None, self};
     use std::__rand::{thread_rng, Rng};
     use std::thread;
@@ -962,7 +991,7 @@ mod tests {
             Some(ref node) => node_ptr = &**node,
         }
         loop {
-            match (last_ptr, node_ptr.prev.resolve_immut()) {
+            match unsafe { (last_ptr, node_ptr.prev.resolve()) } {
                 (None   , None      ) => {}
                 (None   , _         ) => panic!("prev link for list_head"),
                 (Some(p), Some(pptr)) => {
@@ -1108,6 +1137,26 @@ mod tests {
         assert_eq!(v1.iter().collect::<Vec<_>>().len(), 3);
     }
 
+    #[test]
+    fn test_split_off() {
+        let mut v1 = LinkedList::new();
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+
+        // test all splits
+        for ix in 0..1 + v1.len() {
+            let mut a = v1.clone();
+            let b = a.split_off(ix);
+            check_links(&a);
+            check_links(&b);
+            a.extend(b);
+            assert_eq!(v1, a);
+        }
+    }
+
+
     #[cfg(test)]
     fn fuzz_test(sz: i32) {
         let mut m: LinkedList<_> = LinkedList::new();
@@ -1140,7 +1189,7 @@ mod tests {
         check_links(&m);
 
         let mut i = 0;
-        for (a, &b) in m.into_iter().zip(v.iter()) {
+        for (a, &b) in m.into_iter().zip(&v) {
             i += 1;
             assert_eq!(a, b);
         }
index 6ab143998d299f5222057e8372b58a083ad916be..f37c4aede6a1af8a24252868fa507166f7ef952c 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-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(feature = "collections_range", reason = "was just added")]
 
 //! Range syntax.
index d5a069b194a5de3535c7fdc4664faf70ea095733..d49463911e66e3c057cc9c81921be78d40d9e730 100644 (file)
@@ -11,7 +11,8 @@
 //! Utilities for slice manipulation
 //!
 //! The `slice` module contains useful code to help work with slice values.
-//! Slices are a view into a block of memory represented as a pointer and a length.
+//! Slices are a view into a block of memory represented as a pointer and a
+//! length.
 //!
 //! ```
 //! // slicing a Vec
@@ -69,8 +70,9 @@
 //! }
 //! ```
 //!
-//! This iterator yields mutable references to the slice's elements, so while the element
-//! type of the slice is `i32`, the element type of the iterator is `&mut i32`.
+//! This iterator yields mutable references to the slice's elements, so while
+//! the element type of the slice is `i32`, the element type of the iterator is
+//! `&mut i32`.
 //!
 //! * `.iter()` and `.iter_mut()` are the explicit methods to return the default
 //!   iterators.
 #![doc(primitive = "slice")]
 #![stable(feature = "rust1", since = "1.0.0")]
 
+// Many of the usings in this module are only used in the test configuration.
+// It's cleaner to just turn off the unused_imports warning than to fix them.
+#![allow(unused_imports)]
+
 use alloc::boxed::Box;
 use core::clone::Clone;
 use core::cmp::Ordering::{self, Greater, Less};
@@ -145,6 +151,7 @@ mod hack {
         }
     }
 
+    #[allow(deprecated)]
     pub fn permutations<T>(s: &[T]) -> Permutations<T> where T: Clone {
         Permutations{
             swaps: ElementSwaps::new(s.len()),
@@ -221,208 +228,110 @@ mod hack {
 #[cfg(not(test))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> [T] {
-    /// Sorts the slice, in place, using `compare` to compare
-    /// elements.
-    ///
-    /// This sort is `O(n log n)` worst-case and stable, but allocates
-    /// approximately `2 * n`, where `n` is the length of `self`.
-    ///
-    /// # Examples
+    /// Returns the number of elements in the slice.
     ///
-    /// ```rust
-    /// let mut v = [5, 4, 1, 3, 2];
-    /// v.sort_by(|a, b| a.cmp(b));
-    /// assert!(v == [1, 2, 3, 4, 5]);
+    /// # Example
     ///
-    /// // reverse sorting
-    /// v.sort_by(|a, b| b.cmp(a));
-    /// assert!(v == [5, 4, 3, 2, 1]);
+    /// ```
+    /// let a = [1, 2, 3];
+    /// assert_eq!(a.len(), 3);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
-        merge_sort(self, compare)
+    pub fn len(&self) -> usize {
+        core_slice::SliceExt::len(self)
     }
 
-    /// Consumes `src` and moves as many elements as it can into `self`
-    /// from the range [start,end).
-    ///
-    /// Returns the number of elements copied (the shorter of `self.len()`
-    /// and `end - start`).
-    ///
-    /// # Arguments
-    ///
-    /// * src - A mutable vector of `T`
-    /// * start - The index into `src` to start copying from
-    /// * end - The index into `src` to stop copying from
+    /// Returns true if the slice has a length of 0
     ///
-    /// # Examples
+    /// # Example
     ///
-    /// ```rust
-    /// # #![feature(collections)]
-    /// let mut a = [1, 2, 3, 4, 5];
-    /// let b = vec![6, 7, 8];
-    /// let num_moved = a.move_from(b, 0, 3);
-    /// assert_eq!(num_moved, 3);
-    /// assert!(a == [6, 7, 8, 4, 5]);
     /// ```
-    #[unstable(feature = "collections",
-               reason = "uncertain about this API approach")]
+    /// let a = [1, 2, 3];
+    /// assert!(!a.is_empty());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn move_from(&mut self, mut src: Vec<T>, start: usize, end: usize) -> usize {
-        for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) {
-            mem::swap(a, b);
-        }
-        cmp::min(self.len(), end-start)
+    pub fn is_empty(&self) -> bool {
+        core_slice::SliceExt::is_empty(self)
     }
 
-    /// Divides one slice into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// Panics if `mid > len`.
+    /// Returns the first element of a slice, or `None` if it is empty.
     ///
     /// # Examples
     ///
     /// ```
-    /// let v = [10, 40, 30, 20, 50];
-    /// let (v1, v2) = v.split_at(2);
-    /// assert_eq!([10, 40], v1);
-    /// assert_eq!([30, 20, 50], v2);
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&10), v.first());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.first());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
-        core_slice::SliceExt::split_at(self, mid)
+    pub fn first(&self) -> Option<&T> {
+        core_slice::SliceExt::first(self)
     }
 
-    /// Returns an iterator over the slice.
+    /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn iter(&self) -> Iter<T> {
-        core_slice::SliceExt::iter(self)
+    pub fn first_mut(&mut self) -> Option<&mut T> {
+        core_slice::SliceExt::first_mut(self)
     }
 
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`.  The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`,
-    /// `[20]`, `[50]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.split(|num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Returns all but the first element of a slice.
+    #[unstable(feature = "slice_extras", reason = "likely to be renamed")]
     #[inline]
-    pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::split(self, pred)
+    pub fn tail(&self) -> &[T] {
+        core_slice::SliceExt::tail(self)
     }
 
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items.  The matched element is
-    /// not contained in the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
-    /// `[20, 60, 50]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.splitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Returns all but the first element of a mutable slice
+    #[unstable(feature = "slice_extras",
+               reason = "likely to be renamed or removed")]
     #[inline]
-    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::splitn(self, n, pred)
+    pub fn tail_mut(&mut self) -> &mut [T] {
+        core_slice::SliceExt::tail_mut(self)
     }
 
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards.  The matched element is not contained in
-    /// the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once, starting from the end, by numbers divisible
-    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Returns all but the last element of a slice.
+    #[unstable(feature = "slice_extras", reason = "likely to be renamed")]
     #[inline]
-    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F> where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::rsplitn(self, n, pred)
+    pub fn init(&self) -> &[T] {
+        core_slice::SliceExt::init(self)
     }
 
-    /// Returns an iterator over all contiguous windows of length
-    /// `size`. The windows overlap. If the slice is shorter than
-    /// `size`, the iterator returns no values.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `size` is 0.
+    /// Returns all but the last element of a mutable slice
+    #[unstable(feature = "slice_extras",
+               reason = "likely to be renamed or removed")]
+    #[inline]
+    pub fn init_mut(&mut self) -> &mut [T] {
+        core_slice::SliceExt::init_mut(self)
+    }
+
+    /// Returns the last element of a slice, or `None` if it is empty.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`,
-    /// `[3,4]`):
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&30), v.last());
     ///
-    /// ```rust
-    /// let v = &[1, 2, 3, 4];
-    /// for win in v.windows(2) {
-    ///     println!("{:?}", win);
-    /// }
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.last());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn windows(&self, size: usize) -> Windows<T> {
-        core_slice::SliceExt::windows(self, size)
+    pub fn last(&self) -> Option<&T> {
+        core_slice::SliceExt::last(self)
     }
 
-    /// Returns an iterator over `size` elements of the slice at a
-    /// time. The chunks do not overlap. If `size` does not divide the
-    /// length of the slice, then the last chunk will not have length
-    /// `size`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `size` is 0.
-    ///
-    /// # Example
-    ///
-    /// Print the slice two elements at a time (i.e. `[1,2]`,
-    /// `[3,4]`, `[5]`):
-    ///
-    /// ```rust
-    /// let v = &[1, 2, 3, 4, 5];
-    /// for win in v.chunks(2) {
-    ///     println!("{:?}", win);
-    /// }
-    /// ```
+    /// Returns a mutable pointer to the last item in the slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn chunks(&self, size: usize) -> Chunks<T> {
-        core_slice::SliceExt::chunks(self, size)
+    pub fn last_mut(&mut self) -> Option<&mut T> {
+        core_slice::SliceExt::last_mut(self)
     }
 
     /// Returns the element of a slice at the given index, or `None` if the
@@ -441,63 +350,43 @@ impl<T> [T] {
         core_slice::SliceExt::get(self, index)
     }
 
-    /// Returns the first element of a slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&10), v.first());
-    ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.first());
-    /// ```
+    /// Returns a mutable reference to the element at the given index,
+    /// or `None` if the index is out of bounds
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn first(&self) -> Option<&T> {
-        core_slice::SliceExt::first(self)
+    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
+        core_slice::SliceExt::get_mut(self, index)
     }
 
-    /// Returns all but the first element of a slice.
-    #[unstable(feature = "collections", reason = "likely to be renamed")]
+    /// Returns a pointer to the element at the given index, without doing
+    /// bounds checking.
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn tail(&self) -> &[T] {
-        core_slice::SliceExt::tail(self)
+    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
+        core_slice::SliceExt::get_unchecked(self, index)
     }
 
-    /// Returns all but the last element of a slice.
-    #[unstable(feature = "collections", reason = "likely to be renamed")]
+    /// Returns an unsafe mutable pointer to the element in index
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn init(&self) -> &[T] {
-        core_slice::SliceExt::init(self)
+    pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
+        core_slice::SliceExt::get_unchecked_mut(self, index)
     }
 
-    /// Returns the last element of a slice, or `None` if it is empty.
-    ///
-    /// # Examples
+    /// Returns an raw pointer to the slice's buffer
     ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&30), v.last());
+    /// The caller must ensure that the slice outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
     ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.last());
-    /// ```
+    /// Modifying the slice may cause its buffer to be reallocated, which
+    /// would also make any pointers to it invalid.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn last(&self) -> Option<&T> {
-        core_slice::SliceExt::last(self)
-    }
-
-    /// Returns a pointer to the element at the given index, without doing
-    /// bounds checking.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
-        core_slice::SliceExt::get_unchecked(self, index)
+    pub fn as_ptr(&self) -> *const T {
+        core_slice::SliceExt::as_ptr(self)
     }
 
-    /// Returns an unsafe pointer to the slice's buffer
+    /// Returns an unsafe mutable pointer to the slice's buffer.
     ///
     /// The caller must ensure that the slice outlives the pointer this
     /// function returns, or else it will end up pointing to garbage.
@@ -506,82 +395,54 @@ impl<T> [T] {
     /// would also make any pointers to it invalid.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn as_ptr(&self) -> *const T {
-        core_slice::SliceExt::as_ptr(self)
+    pub fn as_mut_ptr(&mut self) -> *mut T {
+        core_slice::SliceExt::as_mut_ptr(self)
     }
 
-    /// Binary search a sorted slice with a comparator function.
-    ///
-    /// The comparator function should implement an order consistent
-    /// with the sort order of the underlying slice, returning an
-    /// order code that indicates whether its argument is `Less`,
-    /// `Equal` or `Greater` the desired target.
-    ///
-    /// If a matching value is found then returns `Ok`, containing
-    /// the index for the matched element; if no match is found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// Swaps two elements in a slice.
     ///
-    /// # Example
+    /// # Arguments
     ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1,4]`.
+    /// * a - The index of the first element
+    /// * b - The index of the second element
     ///
-    /// ```rust
-    /// # #![feature(core)]
-    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    /// # Panics
     ///
-    /// let seek = 13;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
-    /// let seek = 4;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
-    /// let seek = 100;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
-    /// let seek = 1;
-    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn binary_search_by<F>(&self, f: F) -> Result<usize, usize> where F: FnMut(&T) -> Ordering {
-        core_slice::SliceExt::binary_search_by(self, f)
-    }
-
-    /// Returns the number of elements in the slice.
+    /// Panics if `a` or `b` are out of bounds.
     ///
     /// # Example
     ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert_eq!(a.len(), 3);
+    /// ```rust
+    /// let mut v = ["a", "b", "c", "d"];
+    /// v.swap(1, 3);
+    /// assert!(v == ["a", "d", "c", "b"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn len(&self) -> usize {
-        core_slice::SliceExt::len(self)
+    pub fn swap(&mut self, a: usize, b: usize) {
+        core_slice::SliceExt::swap(self, a, b)
     }
 
-    /// Returns true if the slice has a length of 0
+    /// Reverse the order of elements in a slice, in place.
     ///
     /// # Example
     ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert!(!a.is_empty());
+    /// ```rust
+    /// let mut v = [1, 2, 3];
+    /// v.reverse();
+    /// assert!(v == [3, 2, 1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_empty(&self) -> bool {
-        core_slice::SliceExt::is_empty(self)
+    pub fn reverse(&mut self) {
+        core_slice::SliceExt::reverse(self)
     }
 
-    /// Returns a mutable reference to the element at the given index,
-    /// or `None` if the index is out of bounds
+    /// Returns an iterator over the slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
-        core_slice::SliceExt::get_mut(self, index)
+    pub fn iter(&self) -> Iter<T> {
+        core_slice::SliceExt::iter(self)
     }
 
     /// Returns an iterator that allows modifying each value
@@ -591,69 +452,55 @@ impl<T> [T] {
         core_slice::SliceExt::iter_mut(self)
     }
 
-    /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn first_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::first_mut(self)
-    }
-
-    /// Returns all but the first element of a mutable slice
-    #[unstable(feature = "collections",
-               reason = "likely to be renamed or removed")]
-    #[inline]
-    pub fn tail_mut(&mut self) -> &mut [T] {
-        core_slice::SliceExt::tail_mut(self)
-    }
-
-    /// Returns all but the last element of a mutable slice
-    #[unstable(feature = "collections",
-               reason = "likely to be renamed or removed")]
-    #[inline]
-    pub fn init_mut(&mut self) -> &mut [T] {
-        core_slice::SliceExt::init_mut(self)
-    }
-
-    /// Returns a mutable pointer to the last item in the slice.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn last_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::last_mut(self)
-    }
-
-    /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`.  The matched element is not contained in the subslices.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::split_mut(self, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items.  The matched element is
-    /// not contained in the subslices.
+    /// Returns an iterator over all contiguous windows of length
+    /// `size`. The windows overlap. If the slice is shorter than
+    /// `size`, the iterator returns no values.
     ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
+    /// # Panics
+    ///
+    /// Panics if `size` is 0.
+    ///
+    /// # Example
+    ///
+    /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`,
+    /// `[3,4]`):
+    ///
+    /// ```rust
+    /// let v = &[1, 2, 3, 4];
+    /// for win in v.windows(2) {
+    ///     println!("{:?}", win);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
-                         where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::splitn_mut(self, n, pred)
+    pub fn windows(&self, size: usize) -> Windows<T> {
+        core_slice::SliceExt::windows(self, size)
     }
 
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards.  The matched element is not contained in
-    /// the subslices.
+    /// Returns an iterator over `size` elements of the slice at a
+    /// time. The chunks do not overlap. If `size` does not divide the
+    /// length of the slice, then the last chunk will not have length
+    /// `size`.
     ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
+    /// # Panics
+    ///
+    /// Panics if `size` is 0.
+    ///
+    /// # Example
+    ///
+    /// Print the slice two elements at a time (i.e. `[1,2]`,
+    /// `[3,4]`, `[5]`):
+    ///
+    /// ```rust
+    /// let v = &[1, 2, 3, 4, 5];
+    /// for win in v.chunks(2) {
+    ///     println!("{:?}", win);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn rsplitn_mut<F>(&mut self,  n: usize, pred: F) -> RSplitNMut<T, F>
-                      where F: FnMut(&T) -> bool {
-        core_slice::SliceExt::rsplitn_mut(self, n, pred)
+    pub fn chunks(&self, size: usize) -> Chunks<T> {
+        core_slice::SliceExt::chunks(self, size)
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -670,28 +517,26 @@ impl<T> [T] {
         core_slice::SliceExt::chunks_mut(self, chunk_size)
     }
 
-    /// Swaps two elements in a slice.
-    ///
-    /// # Arguments
-    ///
-    /// * a - The index of the first element
-    /// * b - The index of the second element
+    /// Divides one slice into two at an index.
     ///
-    /// # Panics
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
-    /// Panics if `a` or `b` are out of bounds.
+    /// Panics if `mid > len`.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
-    /// let mut v = ["a", "b", "c", "d"];
-    /// v.swap(1, 3);
-    /// assert!(v == ["a", "d", "c", "b"]);
+    /// ```
+    /// let v = [10, 40, 30, 20, 50];
+    /// let (v1, v2) = v.split_at(2);
+    /// assert_eq!([10, 40], v1);
+    /// assert_eq!([30, 20, 50], v2);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn swap(&mut self, a: usize, b: usize) {
-        core_slice::SliceExt::swap(self, a, b)
+    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
+        core_slice::SliceExt::split_at(self, mid)
     }
 
     /// Divides one `&mut` into two at an index.
@@ -734,121 +579,166 @@ impl<T> [T] {
         core_slice::SliceExt::split_at_mut(self, mid)
     }
 
-    /// Reverse the order of elements in a slice, in place.
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`.  The matched element is not contained in the subslices.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
-    /// let mut v = [1, 2, 3];
-    /// v.reverse();
-    /// assert!(v == [3, 2, 1]);
+    /// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`,
+    /// `[20]`, `[50]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    /// for group in v.split(|num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn reverse(&mut self) {
-        core_slice::SliceExt::reverse(self)
+    pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::split(self, pred)
     }
 
-    /// Returns an unsafe mutable pointer to the element in index
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`.  The matched element is not contained in the subslices.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
-        core_slice::SliceExt::get_unchecked_mut(self, index)
+    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::split_mut(self, pred)
     }
 
-    /// Returns an unsafe mutable pointer to the slice's buffer.
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items.  The matched element is
+    /// not contained in the subslices.
     ///
-    /// The caller must ensure that the slice outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the slice may cause its buffer to be reallocated, which
-    /// would also make any pointers to it invalid.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_mut_ptr(&mut self) -> *mut T {
-        core_slice::SliceExt::as_mut_ptr(self)
-    }
-
-    /// Copies `self` into a new `Vec`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_vec(&self) -> Vec<T> where T: Clone {
-        // NB see hack module in this file
-        hack::to_vec(self)
-    }
-
-    /// Creates an iterator that yields every possible permutation of the
-    /// vector in succession.
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     ///
     /// # Examples
     ///
-    /// ```rust
-    /// # #![feature(collections)]
-    /// let v = [1, 2, 3];
-    /// let mut perms = v.permutations();
+    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
+    /// `[20, 60, 50]`):
     ///
-    /// for p in perms {
-    ///   println!("{:?}", p);
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    /// for group in v.splitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
     /// }
     /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::splitn(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items.  The matched element is
+    /// not contained in the subslices.
     ///
-    /// Iterating through permutations one by one.
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
+                         where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::splitn_mut(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards.  The matched element is not contained in
+    /// the subslices.
     ///
-    /// ```rust
-    /// # #![feature(collections)]
-    /// let v = [1, 2, 3];
-    /// let mut perms = v.permutations();
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     ///
-    /// assert_eq!(Some(vec![1, 2, 3]), perms.next());
-    /// assert_eq!(Some(vec![1, 3, 2]), perms.next());
-    /// assert_eq!(Some(vec![3, 1, 2]), perms.next());
+    /// # Examples
+    ///
+    /// Print the slice split once, starting from the end, by numbers divisible
+    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
     /// ```
-    #[unstable(feature = "collections")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn permutations(&self) -> Permutations<T> where T: Clone {
-        // NB see hack module in this file
-        hack::permutations(self)
+    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F> where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::rsplitn(self, n, pred)
     }
 
-    /// Copies as many elements from `src` as it can into `self` (the
-    /// shorter of `self.len()` and `src.len()`). Returns the number
-    /// of elements copied.
-    ///
-    /// # Example
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards.  The matched element is not contained in
+    /// the subslices.
     ///
-    /// ```rust
-    /// # #![feature(collections)]
-    /// let mut dst = [0, 0, 0];
-    /// let src = [1, 2];
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn_mut<F>(&mut self,  n: usize, pred: F) -> RSplitNMut<T, F>
+                      where F: FnMut(&T) -> bool {
+        core_slice::SliceExt::rsplitn_mut(self, n, pred)
+    }
+
+    /// Returns true if the slice contains an element with the given value.
     ///
-    /// assert!(dst.clone_from_slice(&src) == 2);
-    /// assert!(dst == [1, 2, 0]);
+    /// # Examples
     ///
-    /// let src2 = [3, 4, 5, 6];
-    /// assert!(dst.clone_from_slice(&src2) == 3);
-    /// assert!(dst == [3, 4, 5]);
     /// ```
-    #[unstable(feature = "collections")]
-    pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone {
-        core_slice::SliceExt::clone_from_slice(self, src)
+    /// let v = [10, 40, 30];
+    /// assert!(v.contains(&30));
+    /// assert!(!v.contains(&50));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn contains(&self, x: &T) -> bool where T: PartialEq {
+        core_slice::SliceExt::contains(self, x)
     }
 
-    /// Sorts the slice, in place.
-    ///
-    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+    /// Returns true if `needle` is a prefix of the slice.
     ///
     /// # Examples
     ///
-    /// ```rust
-    /// let mut v = [-5, 4, 1, -3, 2];
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.starts_with(&[10]));
+    /// assert!(v.starts_with(&[10, 40]));
+    /// assert!(!v.starts_with(&[50]));
+    /// assert!(!v.starts_with(&[10, 50]));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        core_slice::SliceExt::starts_with(self, needle)
+    }
+
+    /// Returns true if `needle` is a suffix of the slice.
+    ///
+    /// # Examples
     ///
-    /// v.sort();
-    /// assert!(v == [-5, -3, 1, 2, 4]);
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.ends_with(&[30]));
+    /// assert!(v.ends_with(&[40, 30]));
+    /// assert!(!v.ends_with(&[50]));
+    /// assert!(!v.ends_with(&[50, 30]));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn sort(&mut self) where T: Ord {
-        self.sort_by(|a, b| a.cmp(b))
+    pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        core_slice::SliceExt::ends_with(self, needle)
+    }
+
+    /// Find the first index containing a matching value.
+    #[unstable(feature = "slice_position_elem")]
+    pub fn position_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
+        core_slice::SliceExt::position_elem(self, t)
+    }
+
+    /// Find the last index containing a matching value.
+    #[unstable(feature = "slice_position_elem")]
+    pub fn rposition_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
+        core_slice::SliceExt::rposition_elem(self, t)
     }
 
     /// Binary search a sorted slice for a given element.
@@ -865,7 +755,6 @@ impl<T> [T] {
     /// found; the fourth could match any position in `[1,4]`.
     ///
     /// ```rust
-    /// # #![feature(core)]
     /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
     ///
     /// assert_eq!(s.binary_search(&13),  Ok(9));
@@ -879,6 +768,119 @@ impl<T> [T] {
         core_slice::SliceExt::binary_search(self, x)
     }
 
+    /// Binary search a sorted slice with a comparator function.
+    ///
+    /// The comparator function should implement an order consistent
+    /// with the sort order of the underlying slice, returning an
+    /// order code that indicates whether its argument is `Less`,
+    /// `Equal` or `Greater` the desired target.
+    ///
+    /// If a matching value is found then returns `Ok`, containing
+    /// the index for the matched element; if no match is found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Example
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1,4]`.
+    ///
+    /// ```rust
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    ///
+    /// let seek = 13;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
+    /// let seek = 4;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
+    /// let seek = 100;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
+    /// let seek = 1;
+    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn binary_search_by<F>(&self, f: F) -> Result<usize, usize> where F: FnMut(&T) -> Ordering {
+        core_slice::SliceExt::binary_search_by(self, f)
+    }
+
+    /// Sorts the slice, in place.
+    ///
+    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut v = [-5, 4, 1, -3, 2];
+    ///
+    /// v.sort();
+    /// assert!(v == [-5, -3, 1, 2, 4]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn sort(&mut self) where T: Ord {
+        self.sort_by(|a, b| a.cmp(b))
+    }
+
+    /// Sorts the slice, in place, using `compare` to compare
+    /// elements.
+    ///
+    /// This sort is `O(n log n)` worst-case and stable, but allocates
+    /// approximately `2 * n`, where `n` is the length of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut v = [5, 4, 1, 3, 2];
+    /// v.sort_by(|a, b| a.cmp(b));
+    /// assert!(v == [1, 2, 3, 4, 5]);
+    ///
+    /// // reverse sorting
+    /// v.sort_by(|a, b| b.cmp(a));
+    /// assert!(v == [5, 4, 3, 2, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
+        merge_sort(self, compare)
+    }
+
+    /// Creates an iterator that yields every possible permutation of the
+    /// vector in succession.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(permutations)]
+    /// let v = [1, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// for p in perms {
+    ///   println!("{:?}", p);
+    /// }
+    /// ```
+    ///
+    /// Iterating through permutations one by one.
+    ///
+    /// ```rust
+    /// # #![feature(permutations)]
+    /// let v = [1, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// assert_eq!(Some(vec![1, 2, 3]), perms.next());
+    /// assert_eq!(Some(vec![1, 3, 2]), perms.next());
+    /// assert_eq!(Some(vec![3, 1, 2]), perms.next());
+    /// ```
+    #[allow(deprecated)]
+    #[unstable(feature = "permutations")]
+    #[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
+    #[inline]
+    pub fn permutations(&self) -> Permutations<T> where T: Clone {
+        // NB see hack module in this file
+        hack::permutations(self)
+    }
+
     /// Mutates the slice to the next lexicographic permutation.
     ///
     /// Returns `true` if successful and `false` if the slice is at the
@@ -887,7 +889,7 @@ impl<T> [T] {
     /// # Example
     ///
     /// ```rust
-    /// # #![feature(collections)]
+    /// # #![feature(permutations)]
     /// let v: &mut [_] = &mut [0, 1, 2];
     /// v.next_permutation();
     /// let b: &mut [_] = &mut [0, 2, 1];
@@ -896,8 +898,10 @@ impl<T> [T] {
     /// let b: &mut [_] = &mut [1, 0, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable(feature = "collections",
+    #[allow(deprecated)]
+    #[unstable(feature = "permutations",
                reason = "uncertain if this merits inclusion in std")]
+    #[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
     pub fn next_permutation(&mut self) -> bool where T: Ord {
         core_slice::SliceExt::next_permutation(self)
     }
@@ -910,7 +914,7 @@ impl<T> [T] {
     /// # Example
     ///
     /// ```rust
-    /// # #![feature(collections)]
+    /// # #![feature(permutations)]
     /// let v: &mut [_] = &mut [1, 0, 2];
     /// v.prev_permutation();
     /// let b: &mut [_] = &mut [0, 2, 1];
@@ -919,68 +923,75 @@ impl<T> [T] {
     /// let b: &mut [_] = &mut [0, 1, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable(feature = "collections",
+    #[allow(deprecated)]
+    #[unstable(feature = "permutations",
                reason = "uncertain if this merits inclusion in std")]
+    #[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
     pub fn prev_permutation(&mut self) -> bool where T: Ord {
         core_slice::SliceExt::prev_permutation(self)
     }
 
-    /// Find the first index containing a matching value.
-    #[unstable(feature = "collections")]
-    pub fn position_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
-        core_slice::SliceExt::position_elem(self, t)
-    }
-
-    /// Find the last index containing a matching value.
-    #[unstable(feature = "collections")]
-    pub fn rposition_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
-        core_slice::SliceExt::rposition_elem(self, t)
-    }
-
-    /// Returns true if the slice contains an element with the given value.
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
     ///
-    /// # Examples
+    /// # Example
     ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.contains(&30));
-    /// assert!(!v.contains(&50));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains(&self, x: &T) -> bool where T: PartialEq {
-        core_slice::SliceExt::contains(self, x)
-    }
-
-    /// Returns true if `needle` is a prefix of the slice.
+    /// ```rust
+    /// # #![feature(clone_from_slice)]
+    /// let mut dst = [0, 0, 0];
+    /// let src = [1, 2];
     ///
-    /// # Examples
+    /// assert!(dst.clone_from_slice(&src) == 2);
+    /// assert!(dst == [1, 2, 0]);
     ///
+    /// let src2 = [3, 4, 5, 6];
+    /// assert!(dst.clone_from_slice(&src2) == 3);
+    /// assert!(dst == [3, 4, 5]);
     /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.starts_with(&[10]));
-    /// assert!(v.starts_with(&[10, 40]));
-    /// assert!(!v.starts_with(&[50]));
-    /// assert!(!v.starts_with(&[10, 50]));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        core_slice::SliceExt::starts_with(self, needle)
+    #[unstable(feature = "clone_from_slice")]
+    pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone {
+        core_slice::SliceExt::clone_from_slice(self, src)
     }
 
-    /// Returns true if `needle` is a suffix of the slice.
+    /// Consumes `src` and moves as many elements as it can into `self`
+    /// from the range [start,end).
+    ///
+    /// Returns the number of elements copied (the shorter of `self.len()`
+    /// and `end - start`).
+    ///
+    /// # Arguments
+    ///
+    /// * src - A mutable vector of `T`
+    /// * start - The index into `src` to start copying from
+    /// * end - The index into `src` to stop copying from
     ///
     /// # Examples
     ///
+    /// ```rust
+    /// # #![feature(move_from)]
+    /// let mut a = [1, 2, 3, 4, 5];
+    /// let b = vec![6, 7, 8];
+    /// let num_moved = a.move_from(b, 0, 3);
+    /// assert_eq!(num_moved, 3);
+    /// assert!(a == [6, 7, 8, 4, 5]);
     /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.ends_with(&[30]));
-    /// assert!(v.ends_with(&[40, 30]));
-    /// assert!(!v.ends_with(&[50]));
-    /// assert!(!v.ends_with(&[50, 30]));
-    /// ```
+    #[unstable(feature = "move_from",
+               reason = "uncertain about this API approach")]
+    #[inline]
+    pub fn move_from(&mut self, mut src: Vec<T>, start: usize, end: usize) -> usize {
+        for (a, b) in self.iter_mut().zip(&mut src[start .. end]) {
+            mem::swap(a, b);
+        }
+        cmp::min(self.len(), end-start)
+    }
+
+    /// Copies `self` into a new `Vec`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        core_slice::SliceExt::ends_with(self, needle)
+    #[inline]
+    pub fn to_vec(&self) -> Vec<T> where T: Clone {
+        // NB see hack module in this file
+        hack::to_vec(self)
     }
 
     /// Converts `self` into a vector without clones or allocation.
@@ -995,10 +1006,12 @@ impl<T> [T] {
 ////////////////////////////////////////////////////////////////////////////////
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
-#[unstable(feature = "collections", reason = "recently changed")]
+#[unstable(feature = "slice_concat_ext",
+           reason = "trait should not have to exist")]
 /// An extension trait for concatenating slices
 pub trait SliceConcatExt<T: ?Sized> {
-    #[unstable(feature = "collections", reason = "recently changed")]
+    #[unstable(feature = "slice_concat_ext",
+               reason = "trait should not have to exist")]
     /// The resulting type after concatenation
     type Output;
 
@@ -1012,8 +1025,8 @@ pub trait SliceConcatExt<T: ?Sized> {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn concat(&self) -> Self::Output;
 
-    /// Flattens a slice of `T` into a single value `Self::Output`, placing a given separator
-    /// between each.
+    /// Flattens a slice of `T` into a single value `Self::Output`, placing a
+    /// given separator between each.
     ///
     /// # Examples
     ///
@@ -1058,8 +1071,10 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
 ///
 /// The last generated swap is always (0, 1), and it returns the
 /// sequence to its initial order.
-#[unstable(feature = "collections")]
+#[allow(deprecated)]
+#[unstable(feature = "permutations")]
 #[derive(Clone)]
+#[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
 pub struct ElementSwaps {
     sdir: Vec<SizeDirection>,
     /// If `true`, emit the last swap that returns the sequence to initial
@@ -1068,9 +1083,11 @@ pub struct ElementSwaps {
     swaps_made : usize,
 }
 
+#[allow(deprecated)]
 impl ElementSwaps {
     /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "permutations")]
+    #[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
     pub fn new(length: usize) -> ElementSwaps {
         // Initialize `sdir` with a direction that position should move in
         // (all negative at the beginning) and the `size` of the
@@ -1126,6 +1143,7 @@ struct SizeDirection {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl Iterator for ElementSwaps {
     type Item = (usize, usize);
 
@@ -1192,13 +1210,16 @@ impl Iterator for ElementSwaps {
 /// swap applied.
 ///
 /// Generates even and odd permutations alternately.
-#[unstable(feature = "collections")]
+#[unstable(feature = "permutations")]
+#[deprecated(since = "1.2.0", reason = "not clear this should be in the stdlib")]
+#[allow(deprecated)]
 pub struct Permutations<T> {
     swaps: ElementSwaps,
     v: Vec<T>,
 }
 
-#[unstable(feature = "collections", reason = "trait is unstable")]
+#[unstable(feature = "permutations", reason = "trait is unstable")]
+#[allow(deprecated)]
 impl<T: Clone> Iterator for Permutations<T> {
     type Item = Vec<T>;
 
index 198627ad2fc3a266b9e491a08ca17514c3d5aafe..5e8a9bca342b0680c695ac803d84f1c2e007edcb 100644 (file)
@@ -30,7 +30,7 @@
 //! You can get a non-`'static` `&str` by taking a slice of a `String`:
 //!
 //! ```
-//! let some_string = "Hello, world.".to_string();
+//! let some_string = "Hello, world.".to_string();
 //! let s = &some_string;
 //! ```
 //!
 #![doc(primitive = "str")]
 #![stable(feature = "rust1", since = "1.0.0")]
 
+// Many of the usings in this module are only used in the test configuration.
+// It's cleaner to just turn off the unused_imports warning than to fix them.
+#![allow(unused_imports)]
+
 use self::RecompositionState::*;
 use self::DecompositionType::*;
 
@@ -362,7 +366,7 @@ impl<'a> Iterator for Recompositions<'a> {
 ///
 /// For use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable(feature = "collections")]
+#[unstable(feature = "str_utf16")]
 pub struct Utf16Units<'a> {
     encoder: Utf16Encoder<Chars<'a>>
 }
@@ -424,631 +428,463 @@ Section: Trait implementations
 #[cfg(not(test))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl str {
-    /// Escapes each char in `s` with `char::escape_default`.
-    #[unstable(feature = "collections",
-               reason = "return type may change to be an iterator")]
-    pub fn escape_default(&self) -> String {
-        self.chars().flat_map(|c| c.escape_default()).collect()
-    }
-
-    /// Escapes each char in `s` with `char::escape_unicode`.
-    #[unstable(feature = "collections",
-               reason = "return type may change to be an iterator")]
-    pub fn escape_unicode(&self) -> String {
-        self.chars().flat_map(|c| c.escape_unicode()).collect()
-    }
-
-    /// Replaces all occurrences of one string with another.
-    ///
-    /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a
-    /// second `&str` to
-    /// replace it with. If the original `&str` isn't found, no change occurs.
+    /// Returns the length of `self` in bytes.
     ///
     /// # Examples
     ///
     /// ```
-    /// let s = "this is old";
-    ///
-    /// assert_eq!(s.replace("old", "new"), "this is new");
-    /// ```
-    ///
-    /// When a `&str` isn't found:
-    ///
-    /// ```
-    /// let s = "this is old";
-    /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
+    /// assert_eq!("foo".len(), 3);
+    /// assert_eq!("ƒoo".len(), 4); // fancy f!
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    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) {
-            result.push_str(unsafe { self.slice_unchecked(last_end, start) });
-            result.push_str(to);
-            last_end = end;
-        }
-        result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
-        result
-    }
-
-    /// Returns an iterator over the string in Unicode Normalization Form D
-    /// (canonical decomposition).
-    #[allow(deprecated)]
-    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
-             since = "1.0.0")]
-    #[inline]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may be replaced with a more generic \
-                         unicode crate on crates.io")]
-    pub fn nfd_chars(&self) -> Decompositions {
-        Decompositions {
-            iter: self[..].chars(),
-            buffer: Vec::new(),
-            sorted: false,
-            kind: Canonical
-        }
-    }
-
-    /// Returns an iterator over the string in Unicode Normalization Form KD
-    /// (compatibility decomposition).
-    #[allow(deprecated)]
-    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
-             since = "1.0.0")]
     #[inline]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may be replaced with a more generic \
-                         unicode crate on crates.io")]
-    pub fn nfkd_chars(&self) -> Decompositions {
-        Decompositions {
-            iter: self[..].chars(),
-            buffer: Vec::new(),
-            sorted: false,
-            kind: Compatible
-        }
+    pub fn len(&self) -> usize {
+        core_str::StrExt::len(self)
     }
 
-    /// An Iterator over the string in Unicode Normalization Form C
-    /// (canonical decomposition followed by canonical composition).
-    #[allow(deprecated)]
-    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
-             since = "1.0.0")]
+    /// Returns true if this slice has a length of zero bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!("".is_empty());
+    /// ```
     #[inline]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may be replaced with a more generic \
-                         unicode crate on crates.io")]
-    pub fn nfc_chars(&self) -> Recompositions {
-        Recompositions {
-            iter: self.nfd_chars(),
-            state: Composing,
-            buffer: VecDeque::new(),
-            composee: None,
-            last_ccc: None
-        }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_empty(&self) -> bool {
+        core_str::StrExt::is_empty(self)
     }
 
-    /// An Iterator over the string in Unicode Normalization Form KC
-    /// (compatibility decomposition followed by canonical composition).
-    #[allow(deprecated)]
-    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
-             since = "1.0.0")]
-    #[inline]
+    /// Returns a string's displayed width in columns.
+    ///
+    /// Control characters have zero width.
+    ///
+    /// `is_cjk` determines behavior for characters in the Ambiguous category:
+    /// if `is_cjk` is
+    /// `true`, these are 2 columns wide; otherwise, they are 1.
+    /// In CJK locales, `is_cjk` should be
+    /// `true`, else it should be `false`.
+    /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
+    /// recommends that these
+    /// characters be treated as 1 column (i.e., `is_cjk = false`) if the
+    /// locale is unknown.
+    #[deprecated(reason = "use the crates.io `unicode-width` library instead",
+                 since = "1.0.0")]
     #[unstable(feature = "unicode",
-               reason = "this functionality may be replaced with a more generic \
-                         unicode crate on crates.io")]
-    pub fn nfkc_chars(&self) -> Recompositions {
-        Recompositions {
-            iter: self.nfkd_chars(),
-            state: Composing,
-            buffer: VecDeque::new(),
-            composee: None,
-            last_ccc: None
-        }
+               reason = "this functionality may only be provided by libunicode")]
+    pub fn width(&self, is_cjk: bool) -> usize {
+        UnicodeStr::width(self, is_cjk)
     }
 
-    /// Returns `true` if `self` contains another `&str`.
+    /// Checks that `index`-th byte lies at the start and/or end of a
+    /// UTF-8 code point sequence.
+    ///
+    /// The start and end of the string (when `index == self.len()`) are
+    /// considered to be
+    /// boundaries.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `index` is greater than `self.len()`.
     ///
     /// # Examples
     ///
     /// ```
-    /// assert!("bananas".contains("nana"));
+    /// # #![feature(str_char)]
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert!(s.is_char_boundary(0));
+    /// // start of `老`
+    /// assert!(s.is_char_boundary(6));
+    /// assert!(s.is_char_boundary(s.len()));
     ///
-    /// assert!(!"bananas".contains("foobar"));
+    /// // second byte of `ö`
+    /// assert!(!s.is_char_boundary(2));
+    ///
+    /// // third byte of `老`
+    /// assert!(!s.is_char_boundary(8));
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::contains(&self[..], pat)
+    #[unstable(feature = "str_char",
+               reason = "it is unclear whether this method pulls its weight \
+                         with the existence of the char_indices iterator or \
+                         this method may want to be replaced with checked \
+                         slicing")]
+    pub fn is_char_boundary(&self, index: usize) -> bool {
+        core_str::StrExt::is_char_boundary(self, index)
     }
 
-    /// An iterator over the codepoints of `self`.
+    /// Converts `self` to a byte slice.
     ///
     /// # Examples
     ///
     /// ```
-    /// let v: Vec<char> = "abc åäö".chars().collect();
-    ///
-    /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
+    /// assert_eq!("bors".as_bytes(), b"bors");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn chars(&self) -> Chars {
-        core_str::StrExt::chars(&self[..])
+    #[inline(always)]
+    pub fn as_bytes(&self) -> &[u8] {
+        core_str::StrExt::as_bytes(self)
     }
 
-    /// An iterator over the bytes of `self`.
+    /// Returns a raw pointer to the `&str`'s buffer.
+    ///
+    /// The caller must ensure that the string outlives this pointer, and
+    /// that it is not
+    /// reallocated (e.g. by pushing to the string).
     ///
     /// # Examples
     ///
     /// ```
-    /// let v: Vec<u8> = "bors".bytes().collect();
-    ///
-    /// assert_eq!(v, b"bors".to_vec());
+    /// let s = "Hello";
+    /// let p = s.as_ptr();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn bytes(&self) -> Bytes {
-        core_str::StrExt::bytes(&self[..])
+    #[inline]
+    pub fn as_ptr(&self) -> *const u8 {
+        core_str::StrExt::as_ptr(self)
     }
 
-    /// An iterator over the characters of `self` and their byte offsets.
+    /// Takes a bytewise slice from a string.
+    ///
+    /// Returns the substring from [`begin`..`end`).
+    ///
+    /// # Unsafety
+    ///
+    /// Caller must check both UTF-8 character boundaries and the boundaries
+    /// of the entire slice as
+    /// well.
     ///
     /// # Examples
     ///
     /// ```
-    /// let v: Vec<(usize, char)> = "abc".char_indices().collect();
-    /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')];
+    /// let s = "Löwe 老虎 Léopard";
     ///
-    /// assert_eq!(v, b);
+    /// unsafe {
+    ///     assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard");
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn char_indices(&self) -> CharIndices {
-        core_str::StrExt::char_indices(&self[..])
+    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
+        core_str::StrExt::slice_unchecked(self, begin, end)
     }
 
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern.
+    /// Returns a slice of the string from the character range [`begin`..`end`).
     ///
-    /// 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.
+    /// That is, start at the `begin`-th code point of the string and continue
+    /// to the `end`-th code point. This does not detect or handle edge cases
+    /// such as leaving a combining character as the first code point of the
+    /// string.
     ///
-    /// # Iterator behavior
+    /// Due to the design of UTF-8, this operation is `O(end)`. Use slicing
+    /// syntax if you want to use byte indices rather than codepoint indices.
     ///
-    /// 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`.
+    /// # Panics
     ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, `rsplit()` can be used.
+    /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the
+    /// last character of the string.
     ///
     /// # Examples
     ///
-    /// Simple patterns:
-    ///
     /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    /// # #![feature(slice_chars)]
+    /// let s = "Löwe 老虎 Léopard";
     ///
-    /// let v: Vec<&str> = "".split('X').collect();
-    /// assert_eq!(v, [""]);
+    /// assert_eq!(s.slice_chars(0, 4), "Löwe");
+    /// assert_eq!(s.slice_chars(5, 7), "老虎");
+    /// ```
+    #[unstable(feature = "slice_chars",
+               reason = "may have yet to prove its worth")]
+    pub fn slice_chars(&self, begin: usize, end: usize) -> &str {
+        core_str::StrExt::slice_chars(self, begin, end)
+    }
+
+    /// Given a byte position, return the next char and its index.
     ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
-    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
+    /// This can be used to iterate over the Unicode characters of a string.
     ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    /// ```
+    /// # Panics
     ///
-    /// More complex patterns with closures:
+    /// If `i` is greater than or equal to the length of the string.
+    /// If `i` is not the index of the beginning of a valid UTF-8 character.
     ///
-    /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    /// # Examples
     ///
-    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    /// ```
-    #[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)
-    }
-
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern and yielded in reverse order.
-    ///
-    /// 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.
-    ///
-    /// # 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 same elements.
-    ///
-    /// For iterating from the front, `split()` can be used.
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```rust
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
-    ///
-    /// let v: Vec<&str> = "".rsplit('X').collect();
-    /// assert_eq!(v, [""]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
+    /// This example manually iterates through the characters of a string;
+    /// this should normally be
+    /// done by `.chars()` or `.char_indices()`.
     ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
     /// ```
+    /// # #![feature(str_char, core)]
+    /// use std::str::CharRange;
     ///
-    /// More complex patterns with closures:
+    /// let s = "中华Việt Nam";
+    /// let mut i = 0;
+    /// while i < s.len() {
+    ///     let CharRange {ch, next} = s.char_range_at(i);
+    ///     println!("{}: {}", i, ch);
+    ///     i = next;
+    /// }
+    /// ```
     ///
-    /// ```rust
-    /// let v: Vec<&str> = "abc1def2ghi".rsplit(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// This outputs:
     ///
-    /// let v: Vec<&str> = "lionXtigerXleopard".rsplit(char::is_uppercase).collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
+    /// ```text
+    /// 0: 中
+    /// 3: 华
+    /// 6: V
+    /// 7: i
+    /// 8: ệ
+    /// 11: t
+    /// 12:
+    /// 13: N
+    /// 14: a
+    /// 15: m
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit(&self[..], pat)
+    #[unstable(feature = "str_char",
+               reason = "often replaced by char_indices, this method may \
+                         be removed in favor of just char_at() or eventually \
+                         removed altogether")]
+    pub fn char_range_at(&self, start: usize) -> CharRange {
+        core_str::StrExt::char_range_at(self, start)
     }
 
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern.
-    ///
-    /// 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.
-    ///
-    /// Equivalent to `split`, except that the trailing substring
-    /// is skipped if empty.
+    /// Given a byte position, return the previous `char` and its position.
     ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
+    /// This function can be used to iterate over a Unicode string in reverse.
     ///
-    /// # Iterator behavior
+    /// Returns 0 for next index if called on start index 0.
     ///
-    /// 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`.
+    /// # Panics
     ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, `rsplit_terminator()` can be used.
+    /// If `i` is greater than the length of the string.
+    /// If `i` is not an index following a valid UTF-8 character.
     ///
     /// # Examples
     ///
-    /// Simple patterns:
+    /// This example manually iterates through the characters of a string;
+    /// this should normally be
+    /// done by `.chars().rev()` or `.char_indices()`.
     ///
     /// ```
-    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
-    /// assert_eq!(v, ["A", "B"]);
+    /// # #![feature(str_char, core)]
+    /// use std::str::CharRange;
     ///
-    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
-    /// assert_eq!(v, ["A", "", "B", ""]);
+    /// let s = "中华Việt Nam";
+    /// let mut i = s.len();
+    /// while i > 0 {
+    ///     let CharRange {ch, next} = s.char_range_at_reverse(i);
+    ///     println!("{}: {}", i, ch);
+    ///     i = next;
+    /// }
     /// ```
     ///
-    /// More complex patterns with closures:
+    /// This outputs:
     ///
+    /// ```text
+    /// 16: m
+    /// 15: a
+    /// 14: N
+    /// 13:
+    /// 12: t
+    /// 11: ệ
+    /// 8: i
+    /// 7: V
+    /// 6: 华
+    /// 3: 中
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
-        core_str::StrExt::split_terminator(&self[..], pat)
+    #[unstable(feature = "str_char",
+               reason = "often replaced by char_indices, this method may \
+                         be removed in favor of just char_at_reverse() or \
+                         eventually removed altogether")]
+    pub fn char_range_at_reverse(&self, start: usize) -> CharRange {
+        core_str::StrExt::char_range_at_reverse(self, start)
     }
 
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern and yielded in reverse order.
-    ///
-    /// 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.
-    ///
-    /// Equivalent to `split`, except that the trailing substring is
-    /// skipped if empty.
-    ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
-    ///
-    /// # Iterator behavior
+    /// Given a byte position, return the `char` at that position.
     ///
-    /// 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.
+    /// # Panics
     ///
-    /// For iterating from the front, `split_terminator()` can be used.
+    /// If `i` is greater than or equal to the length of the string.
+    /// If `i` is not the index of the beginning of a valid UTF-8 character.
     ///
     /// # Examples
     ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
-    /// assert_eq!(v, ["B", "A"]);
-    ///
-    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
-    /// assert_eq!(v, ["", "B", "", "A"]);
     /// ```
-    ///
-    /// More complex patterns with closures:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1def2ghi3".rsplit_terminator(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// # #![feature(str_char)]
+    /// let s = "abπc";
+    /// assert_eq!(s.char_at(1), 'b');
+    /// assert_eq!(s.char_at(2), 'π');
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit_terminator(&self[..], pat)
+    #[unstable(feature = "str_char",
+               reason = "frequently replaced by the chars() iterator, this \
+                         method may be removed or possibly renamed in the \
+                         future; it is normally replaced by chars/char_indices \
+                         iterators or by getting the first char from a \
+                         subslice")]
+    pub fn char_at(&self, i: usize) -> char {
+        core_str::StrExt::char_at(self, i)
     }
 
-    /// An iterator over substrings of `self`, separated by a pattern,
-    /// restricted to returning
-    /// at most `count` items.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// string.
-    /// 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.
-    ///
-    /// # Iterator behavior
+    /// Given a byte position, return the `char` at that position, counting
+    /// from the end.
     ///
-    /// The returned iterator will not be double ended, because it is
-    /// not efficient to support.
+    /// # Panics
     ///
-    /// If the pattern allows a reverse search, `rsplitn()` can be used.
+    /// If `i` is greater than the length of the string.
+    /// If `i` is not an index following a valid UTF-8 character.
     ///
     /// # Examples
     ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
-    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
-    ///
-    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
-    /// assert_eq!(v, ["abcXdef"]);
-    ///
-    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
-    /// assert_eq!(v, [""]);
-    /// ```
-    ///
-    /// More complex patterns with closures:
-    ///
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["abc", "def2ghi"]);
+    /// # #![feature(str_char)]
+    /// let s = "abπc";
+    /// assert_eq!(s.char_at_reverse(1), 'a');
+    /// assert_eq!(s.char_at_reverse(2), 'b');
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
-        core_str::StrExt::splitn(&self[..], count, pat)
+    #[unstable(feature = "str_char",
+               reason = "see char_at for more details, but reverse semantics \
+                         are also somewhat unclear, especially with which \
+                         cases generate panics")]
+    pub fn char_at_reverse(&self, i: usize) -> char {
+        core_str::StrExt::char_at_reverse(self, i)
     }
 
-    /// An iterator over substrings of `self`, separated by a pattern,
-    /// starting from the end of the string, restricted to returning
-    /// at most `count` items.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// string.
-    ///
-    /// 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.
-    ///
-    /// # Iterator behavior
+    /// Retrieves the first character from a `&str` and returns it.
     ///
-    /// The returned iterator will not be double ended, because it is not
-    /// efficient to support.
+    /// This does not allocate a new string; instead, it returns a slice that
+    /// points one character
+    /// beyond the character that was shifted.
     ///
-    /// `splitn()` can be used for splitting from the front.
+    /// If the slice does not contain any characters, None is returned instead.
     ///
     /// # Examples
     ///
-    /// Simple patterns:
-    ///
     /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
+    /// # #![feature(str_char)]
+    /// let s = "Löwe 老虎 Léopard";
+    /// let (c, s1) = s.slice_shift_char().unwrap();
     ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
-    /// assert_eq!(v, ["leopard", "lion::tiger"]);
-    /// ```
+    /// assert_eq!(c, 'L');
+    /// assert_eq!(s1, "öwe 老虎 Léopard");
     ///
-    /// More complex patterns with closures:
+    /// let (c, s2) = s1.slice_shift_char().unwrap();
     ///
+    /// assert_eq!(c, 'ö');
+    /// assert_eq!(s2, "we 老虎 Léopard");
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(2, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["ghi", "abc1def"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplitn(&self[..], count, pat)
+    #[unstable(feature = "str_char",
+               reason = "awaiting conventions about shifting and slices and \
+                         may not be warranted with the existence of the chars \
+                         and/or char_indices iterators")]
+    pub fn slice_shift_char(&self) -> Option<(char, &str)> {
+        core_str::StrExt::slice_shift_char(self)
     }
 
-    /// An iterator over the matches of a pattern within `self`.
+    /// Divide one string slice into two at an index.
     ///
-    /// 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 index `mid` is a byte offset from the start of the string
+    /// that must be on a character boundary.
     ///
-    /// # Iterator behavior
+    /// Return slices `&self[..mid]` and `&self[mid..]`.
     ///
-    /// 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`.
+    /// # Panics
     ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, `rmatches()` can be used.
+    /// Panics if `mid` is beyond the last character of the string,
+    /// or if it is not on a character boundary.
     ///
     /// # Examples
-    ///
     /// ```
     /// # #![feature(collections)]
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    /// let s = "Löwe 老虎 Léopard";
+    /// let first_space = s.find(' ').unwrap_or(s.len());
+    /// let (a, b) = s.split_at(first_space);
     ///
-    /// let v: Vec<&str> = "1abc2abc3".matches(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["1", "2", "3"]);
+    /// assert_eq!(a, "Löwe");
+    /// assert_eq!(b, " 老虎 Léopard");
     /// ```
-    #[unstable(feature = "collections",
-               reason = "method got recently added")]
-    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
-        core_str::StrExt::matches(&self[..], pat)
+    #[inline]
+    pub fn split_at(&self, mid: usize) -> (&str, &str) {
+        core_str::StrExt::split_at(self, mid)
     }
 
-    /// An iterator over the matches of a pattern within `self`, yielded in
-    /// reverse order.
-    ///
-    /// 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.
-    ///
-    /// # 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 same elements.
-    ///
-    /// For iterating from the front, `matches()` can be used.
+    /// An iterator over the codepoints of `self`.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    /// let v: Vec<char> = "abc åäö".chars().collect();
     ///
-    /// let v: Vec<&str> = "1abc2abc3".rmatches(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, ["3", "2", "1"]);
+    /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
     /// ```
-    #[unstable(feature = "collections",
-               reason = "method got recently added")]
-    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatches(&self[..], pat)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn chars(&self) -> Chars {
+        core_str::StrExt::chars(self)
     }
 
-    /// An iterator over the start and end indices of the disjoint matches
-    /// of a pattern within `self`.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// 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.
-    ///
-    /// # 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`.
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, `rmatch_indices()` can be used.
+    /// An iterator over the characters of `self` and their byte offsets.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
-    ///
-    /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, [(1, 4), (4, 7)]);
+    /// let v: Vec<(usize, char)> = "abc".char_indices().collect();
+    /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')];
     ///
-    /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, [(0, 3)]); // only the first `aba`
+    /// assert_eq!(v, b);
     /// ```
-    #[unstable(feature = "collections",
-               reason = "might have its iterator type changed")]
-    // NB: Right now MatchIndices yields `(usize, usize)`, but it would
-    // be more consistent with `matches` and `char_indices` to return `(usize, &str)`
-    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
-        core_str::StrExt::match_indices(&self[..], pat)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn char_indices(&self) -> CharIndices {
+        core_str::StrExt::char_indices(self)
     }
 
-    /// An iterator over the start and end indices of the disjoint matches of
-    /// a pattern within
-    /// `self`, yielded in reverse order.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// 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.
+    /// An iterator over the bytes of `self`.
     ///
-    /// # Iterator behavior
+    /// # Examples
     ///
-    /// 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.
+    /// ```
+    /// let v: Vec<u8> = "bors".bytes().collect();
     ///
-    /// For iterating from the front, `match_indices()` can be used.
+    /// assert_eq!(v, b"bors".to_vec());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn bytes(&self) -> Bytes {
+        core_str::StrExt::bytes(self)
+    }
+
+    /// An iterator over the non-empty substrings of `self` which contain no whitespace,
+    /// and which are separated by any amount of whitespace.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
+    /// let some_words = " Mary   had\ta little  \n\t lamb";
+    /// let v: Vec<&str> = some_words.split_whitespace().collect();
     ///
-    /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(4, 7), (1, 4)]);
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    /// ```
+    #[stable(feature = "split_whitespace", since = "1.1.0")]
+    pub fn split_whitespace(&self) -> SplitWhitespace {
+        UnicodeStr::split_whitespace(self)
+    }
+
+    /// An iterator over the non-empty substrings of `self` which contain no whitespace,
+    /// and which are separated by any amount of whitespace.
+    ///
+    /// # Examples
     ///
-    /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
-    /// assert_eq!(v, [(2, 5)]); // only the last `aba`
     /// ```
-    #[unstable(feature = "collections",
-               reason = "might have its iterator type changed")]
-    // NB: Right now RMatchIndices yields `(usize, usize)`, but it would
-    // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
-    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatch_indices(&self[..], pat)
+    /// # #![feature(str_words)]
+    /// # #![allow(deprecated)]
+    /// let some_words = " Mary   had\ta little  \n\t lamb";
+    /// let v: Vec<&str> = some_words.words().collect();
+    ///
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    /// ```
+    #[deprecated(reason = "words() will be removed. Use split_whitespace() instead",
+                 since = "1.1.0")]
+    #[unstable(feature = "str_words",
+               reason = "the precise algorithm to use is unclear")]
+    #[allow(deprecated)]
+    pub fn words(&self) -> Words {
+        UnicodeStr::words(self)
     }
 
     /// An iterator over the lines of a string, separated by `\n`.
@@ -1074,7 +910,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lines(&self) -> Lines {
-        core_str::StrExt::lines(&self[..])
+        core_str::StrExt::lines(self)
     }
 
     /// An iterator over the lines of a string, separated by either
@@ -1101,61 +937,155 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lines_any(&self) -> LinesAny {
-        core_str::StrExt::lines_any(&self[..])
+        core_str::StrExt::lines_any(self)
     }
-    /// Returns a slice of the string from the character range [`begin`..`end`).
-    ///
-    /// That is, start at the `begin`-th code point of the string and continue
-    /// to the `end`-th code point. This does not detect or handle edge cases
-    /// such as leaving a combining character as the first code point of the
-    /// string.
-    ///
-    /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`,
-    /// `slice_to` and `slice_from` for `O(1)` variants that use byte indices
-    /// rather than code point indices.
+
+    /// Returns an iterator over the string in Unicode Normalization Form D
+    /// (canonical decomposition).
+    #[allow(deprecated)]
+    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
+             since = "1.0.0")]
+    #[inline]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may be replaced with a more generic \
+                         unicode crate on crates.io")]
+    pub fn nfd_chars(&self) -> Decompositions {
+        Decompositions {
+            iter: self[..].chars(),
+            buffer: Vec::new(),
+            sorted: false,
+            kind: Canonical
+        }
+    }
+
+    /// Returns an iterator over the string in Unicode Normalization Form KD
+    /// (compatibility decomposition).
+    #[allow(deprecated)]
+    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
+             since = "1.0.0")]
+    #[inline]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may be replaced with a more generic \
+                         unicode crate on crates.io")]
+    pub fn nfkd_chars(&self) -> Decompositions {
+        Decompositions {
+            iter: self[..].chars(),
+            buffer: Vec::new(),
+            sorted: false,
+            kind: Compatible
+        }
+    }
+
+    /// An Iterator over the string in Unicode Normalization Form C
+    /// (canonical decomposition followed by canonical composition).
+    #[allow(deprecated)]
+    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
+             since = "1.0.0")]
+    #[inline]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may be replaced with a more generic \
+                         unicode crate on crates.io")]
+    pub fn nfc_chars(&self) -> Recompositions {
+        Recompositions {
+            iter: self.nfd_chars(),
+            state: Composing,
+            buffer: VecDeque::new(),
+            composee: None,
+            last_ccc: None
+        }
+    }
+
+    /// An Iterator over the string in Unicode Normalization Form KC
+    /// (compatibility decomposition followed by canonical composition).
+    #[allow(deprecated)]
+    #[deprecated(reason = "use the crates.io `unicode-normalization` library instead",
+             since = "1.0.0")]
+    #[inline]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may be replaced with a more generic \
+                         unicode crate on crates.io")]
+    pub fn nfkc_chars(&self) -> Recompositions {
+        Recompositions {
+            iter: self.nfkd_chars(),
+            state: Composing,
+            buffer: VecDeque::new(),
+            composee: None,
+            last_ccc: None
+        }
+    }
+
+    /// Returns an iterator over the [grapheme clusters][graphemes] of `self`.
     ///
-    /// # Panics
+    /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
     ///
-    /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the
-    /// last character of the string.
+    /// If `is_extended` is true, the iterator is over the
+    /// *extended grapheme clusters*;
+    /// otherwise, the iterator is over the *legacy grapheme clusters*.
+    /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
+    /// recommends extended grapheme cluster boundaries for general processing.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let s = "Löwe 老虎 Léopard";
+    /// # #![feature(unicode, core)]
+    /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>();
+    /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"];
     ///
-    /// assert_eq!(s.slice_chars(0, 4), "Löwe");
-    /// assert_eq!(s.slice_chars(5, 7), "老虎");
+    /// assert_eq!(&gr1[..], b);
+    ///
+    /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
+    /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
+    ///
+    /// assert_eq!(&gr2[..], b);
     /// ```
-    #[unstable(feature = "collections",
-               reason = "may have yet to prove its worth")]
-    pub fn slice_chars(&self, begin: usize, end: usize) -> &str {
-        core_str::StrExt::slice_chars(&self[..], begin, end)
+    #[deprecated(reason = "use the crates.io `unicode-segmentation` library instead",
+             since = "1.0.0")]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may only be provided by libunicode")]
+    pub fn graphemes(&self, is_extended: bool) -> Graphemes {
+        UnicodeStr::graphemes(self, is_extended)
     }
 
-    /// Takes a bytewise slice from a string.
+    /// Returns an iterator over the grapheme clusters of `self` and their
+    /// byte offsets. See
+    /// `graphemes()` for more information.
     ///
-    /// Returns the substring from [`begin`..`end`).
+    /// # Examples
     ///
-    /// # Unsafety
+    /// ```
+    /// # #![feature(unicode, core)]
+    /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>();
+    /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
     ///
-    /// Caller must check both UTF-8 character boundaries and the boundaries
-    /// of the entire slice as
-    /// well.
+    /// assert_eq!(&gr_inds[..], b);
+    /// ```
+    #[deprecated(reason = "use the crates.io `unicode-segmentation` library instead",
+             since = "1.0.0")]
+    #[unstable(feature = "unicode",
+               reason = "this functionality may only be provided by libunicode")]
+    pub fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
+        UnicodeStr::grapheme_indices(self, is_extended)
+    }
+
+    /// Returns an iterator of `u16` over the string encoded as UTF-16.
+    #[unstable(feature = "str_utf16",
+               reason = "this functionality may only be provided by libunicode")]
+    pub fn utf16_units(&self) -> Utf16Units {
+        Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
+    }
+
+    /// Returns `true` if `self` contains another `&str`.
     ///
     /// # Examples
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
+    /// assert!("bananas".contains("nana"));
     ///
-    /// unsafe {
-    ///     assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard");
-    /// }
+    /// assert!(!"bananas".contains("foobar"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
-        core_str::StrExt::slice_unchecked(&self[..], begin, end)
+    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        core_str::StrExt::contains(self, pat)
     }
 
     /// Returns `true` if the given `&str` is a prefix of the string.
@@ -1167,7 +1097,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::starts_with(&self[..], pat)
+        core_str::StrExt::starts_with(self, pat)
     }
 
     /// Returns true if the given `&str` is a suffix of the string.
@@ -1181,410 +1111,548 @@ impl str {
     pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
         where P::Searcher: ReverseSearcher<'a>
     {
-        core_str::StrExt::ends_with(&self[..], pat)
+        core_str::StrExt::ends_with(self, pat)
     }
 
-    /// Returns a string with all pre- and suffixes that match a pattern
-    /// repeatedly removed.
+    /// Returns the byte index of the first character of `self` that matches
+    /// the pattern, if it
+    /// exists.
+    ///
+    /// Returns `None` if it doesn't exist.
+    ///
+    /// The pattern can be a simple `&str`, `char`, or a closure that
+    /// determines the
+    /// split.
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find('L'), Some(0));
+    /// assert_eq!(s.find('é'), Some(14));
+    /// assert_eq!(s.find("Léopard"), Some(13));
+    ///
+    /// ```
+    ///
+    /// More complex patterns with closures:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find(char::is_whitespace), Some(5));
+    /// assert_eq!(s.find(char::is_lowercase), Some(1));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.find(x), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
+        core_str::StrExt::find(self, pat)
+    }
+
+    /// Returns the byte index of the last character of `self` that
+    /// matches the pattern, if it
+    /// exists.
+    ///
+    /// Returns `None` if it doesn't exist.
     ///
-    /// The pattern can be a simple `char`, or a closure that determines
-    /// the split.
+    /// The pattern can be a simple `&str`, `char`,
+    /// or a closure that determines the split.
     ///
     /// # Examples
     ///
     /// Simple patterns:
     ///
     /// ```
-    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+    /// let s = "Löwe 老虎 Léopard";
     ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+    /// assert_eq!(s.rfind('L'), Some(13));
+    /// assert_eq!(s.rfind('é'), Some(14));
     /// ```
     ///
     /// More complex patterns with closures:
     ///
     /// ```
-    /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.rfind(char::is_whitespace), Some(12));
+    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.rfind(x), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: DoubleEndedSearcher<'a>
+    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>
     {
-        core_str::StrExt::trim_matches(&self[..], pat)
+        core_str::StrExt::rfind(self, pat)
     }
 
-    /// Returns a string with all prefixes that match a pattern
-    /// repeatedly removed.
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// determines the split. 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`.
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, `rsplit()` can be used.
     ///
     /// # Examples
     ///
     /// Simple patterns:
     ///
     /// ```
-    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
     ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
-    /// ```
+    /// let v: Vec<&str> = "".split('X').collect();
+    /// assert_eq!(v, [""]);
     ///
-    /// More complex patterns with closures:
+    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
+    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
     ///
-    /// ```
-    /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
-        core_str::StrExt::trim_left_matches(&self[..], pat)
-    }
-
-    /// Returns a string with all suffixes that match a pattern
-    /// repeatedly removed.
+    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
     ///
-    /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
     ///
-    /// # Examples
+    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
+    /// ```
     ///
-    /// Simple patterns:
+    /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
     /// ```
     ///
-    /// More complex patterns with closures:
+    /// If a string contains multiple contiguous separators, you will end up
+    /// with empty strings in the output:
     ///
     /// ```
-    /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::trim_right_matches(&self[..], pat)
-    }
-
-    /// Checks that `index`-th byte lies at the start and/or end of a
-    /// UTF-8 code point sequence.
-    ///
-    /// The start and end of the string (when `index == self.len()`) are
-    /// considered to be
-    /// boundaries.
+    /// let x = "||||a||b|c".to_string();
+    /// let d: Vec<_> = x.split('|').collect();
     ///
-    /// # Panics
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+    /// ```
     ///
-    /// Panics if `index` is greater than `self.len()`.
+    /// This can lead to possibly surprising behavior when whitespace is used
+    /// as the separator. This code is correct:
     ///
-    /// # Examples
+    /// ```
+    /// let x = "    a  b c".to_string();
+    /// let d: Vec<_> = x.split(' ').collect();
     ///
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
     /// ```
-    /// # #![feature(str_char)]
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert!(s.is_char_boundary(0));
-    /// // start of `老`
-    /// assert!(s.is_char_boundary(6));
-    /// assert!(s.is_char_boundary(s.len()));
     ///
-    /// // second byte of `ö`
-    /// assert!(!s.is_char_boundary(2));
+    /// It does _not_ give you:
     ///
-    /// // third byte of `老`
-    /// assert!(!s.is_char_boundary(8));
+    /// ```rust,ignore
+    /// assert_eq!(d, &["a", "b", "c"]);
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "it is unclear whether this method pulls its weight \
-                         with the existence of the char_indices iterator or \
-                         this method may want to be replaced with checked \
-                         slicing")]
-    pub fn is_char_boundary(&self, index: usize) -> bool {
-        core_str::StrExt::is_char_boundary(&self[..], index)
+    #[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)
     }
 
-    /// Given a byte position, return the next char and its index.
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern and yielded in reverse order.
     ///
-    /// This can be used to iterate over the Unicode characters of a string.
+    /// 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.
     ///
-    /// # Panics
+    /// # Iterator behavior
     ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 character.
+    /// 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, `split()` can be used.
     ///
     /// # Examples
     ///
-    /// This example manually iterates through the characters of a string;
-    /// this should normally be
-    /// done by `.chars()` or `.char_indices()`.
+    /// Simple patterns:
     ///
-    /// ```
-    /// # #![feature(str_char, core)]
-    /// use std::str::CharRange;
+    /// ```rust
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
     ///
-    /// let s = "中华Việt Nam";
-    /// let mut i = 0;
-    /// while i < s.len() {
-    ///     let CharRange {ch, next} = s.char_range_at(i);
-    ///     println!("{}: {}", i, ch);
-    ///     i = next;
-    /// }
+    /// let v: Vec<&str> = "".rsplit('X').collect();
+    /// assert_eq!(v, [""]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
     /// ```
     ///
-    /// This outputs:
+    /// A more complex pattern, using a closure:
     ///
-    /// ```text
-    /// 0: 中
-    /// 3: 华
-    /// 6: V
-    /// 7: i
-    /// 8: ệ
-    /// 11: t
-    /// 12:
-    /// 13: N
-    /// 14: a
-    /// 15: m
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at() or eventually \
-                         removed altogether")]
-    pub fn char_range_at(&self, start: usize) -> CharRange {
-        core_str::StrExt::char_range_at(&self[..], start)
+    /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rsplit(self, pat)
     }
 
-    /// Given a byte position, return the previous `char` and its position.
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern.
     ///
-    /// This function can be used to iterate over a Unicode string in reverse.
+    /// 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.
     ///
-    /// Returns 0 for next index if called on start index 0.
+    /// Equivalent to `split`, except that the trailing substring
+    /// is skipped if empty.
     ///
-    /// # Panics
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
     ///
-    /// If `i` is greater than the length of the string.
-    /// If `i` is not an index following a valid UTF-8 character.
+    /// # Iterator behavior
     ///
-    /// # Examples
+    /// 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`.
     ///
-    /// This example manually iterates through the characters of a string;
-    /// this should normally be
-    /// done by `.chars().rev()` or `.char_indices()`.
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, `rsplit_terminator()` can be used.
     ///
-    /// ```
-    /// # #![feature(str_char, core)]
-    /// use std::str::CharRange;
+    /// # Examples
     ///
-    /// let s = "中华Việt Nam";
-    /// let mut i = s.len();
-    /// while i > 0 {
-    ///     let CharRange {ch, next} = s.char_range_at_reverse(i);
-    ///     println!("{}: {}", i, ch);
-    ///     i = next;
-    /// }
     /// ```
+    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
+    /// assert_eq!(v, ["A", "B"]);
     ///
-    /// This outputs:
-    ///
-    /// ```text
-    /// 16: m
-    /// 15: a
-    /// 14: N
-    /// 13:
-    /// 12: t
-    /// 11: ệ
-    /// 8: i
-    /// 7: V
-    /// 6: 华
-    /// 3: 中
+    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
+    /// assert_eq!(v, ["A", "", "B", ""]);
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at_reverse() or \
-                         eventually removed altogether")]
-    pub fn char_range_at_reverse(&self, start: usize) -> CharRange {
-        core_str::StrExt::char_range_at_reverse(&self[..], start)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
+        core_str::StrExt::split_terminator(self, pat)
     }
 
-    /// Given a byte position, return the `char` at that position.
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern and yielded in reverse order.
     ///
-    /// # Panics
+    /// 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.
+    ///
+    /// Equivalent to `split`, except that the trailing substring is
+    /// skipped if empty.
+    ///
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
+    ///
+    /// # 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 same elements.
     ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 character.
+    /// For iterating from the front, `split_terminator()` can be used.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(str_char)]
-    /// let s = "abπc";
-    /// assert_eq!(s.char_at(1), 'b');
-    /// assert_eq!(s.char_at(2), 'π');
+    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
+    /// assert_eq!(v, ["B", "A"]);
+    ///
+    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
+    /// assert_eq!(v, ["", "B", "", "A"]);
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "frequently replaced by the chars() iterator, this \
-                         method may be removed or possibly renamed in the \
-                         future; it is normally replaced by chars/char_indices \
-                         iterators or by getting the first char from a \
-                         subslice")]
-    pub fn char_at(&self, i: usize) -> char {
-        core_str::StrExt::char_at(&self[..], i)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rsplit_terminator(self, pat)
     }
 
-    /// Given a byte position, return the `char` at that position, counting
-    /// from the end.
+    /// An iterator over substrings of `self`, separated by a pattern,
+    /// restricted to returning
+    /// at most `count` items.
     ///
-    /// # Panics
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
+    /// 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.
     ///
-    /// If `i` is greater than the length of the string.
-    /// If `i` is not an index following a valid UTF-8 character.
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is
+    /// not efficient to support.
+    ///
+    /// If the pattern allows a reverse search, `rsplitn()` can be used.
     ///
     /// # Examples
     ///
+    /// Simple patterns:
+    ///
     /// ```
-    /// # #![feature(str_char)]
-    /// let s = "abπc";
-    /// assert_eq!(s.char_at_reverse(1), 'a');
-    /// assert_eq!(s.char_at_reverse(2), 'b');
+    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
+    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
+    ///
+    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
+    /// assert_eq!(v, ["abcXdef"]);
+    ///
+    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
+    /// assert_eq!(v, [""]);
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "see char_at for more details, but reverse semantics \
-                         are also somewhat unclear, especially with which \
-                         cases generate panics")]
-    pub fn char_at_reverse(&self, i: usize) -> char {
-        core_str::StrExt::char_at_reverse(&self[..], i)
-    }
-
-    /// Converts `self` to a byte slice.
     ///
-    /// # Examples
+    /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// assert_eq!("bors".as_bytes(), b"bors");
+    /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "defXghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn as_bytes(&self) -> &[u8] {
-        core_str::StrExt::as_bytes(&self[..])
+    pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
+        core_str::StrExt::splitn(self, count, pat)
     }
 
-    /// Returns the byte index of the first character of `self` that matches
-    /// the pattern, if it
-    /// exists.
+    /// An iterator over substrings of `self`, separated by a pattern,
+    /// starting from the end of the string, restricted to returning
+    /// at most `count` items.
     ///
-    /// Returns `None` if it doesn't exist.
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the
-    /// split.
+    /// determines the split.
+    /// Additional libraries might provide more complex patterns like
+    /// regular expressions.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is not
+    /// efficient to support.
+    ///
+    /// `splitn()` can be used for splitting from the front.
     ///
     /// # Examples
     ///
     /// Simple patterns:
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
-    /// assert_eq!(s.find('L'), Some(0));
-    /// assert_eq!(s.find('é'), Some(14));
-    /// assert_eq!(s.find("Léopard"), Some(13));
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
     ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
+    /// assert_eq!(v, ["leopard", "lion::tiger"]);
     /// ```
     ///
-    /// More complex patterns with closures:
+    /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5));
-    /// assert_eq!(s.find(char::is_lowercase), Some(1));
+    /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rsplitn(self, count, pat)
+    }
+
+    /// An iterator over the matches of a pattern within `self`.
     ///
-    /// Not finding the pattern:
+    /// 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.
+    ///
+    /// # 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`.
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, `rmatches()` can be used.
+    ///
+    /// # Examples
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
     ///
-    /// assert_eq!(s.find(x), None);
+    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
+    /// assert_eq!(v, ["1", "2", "3"]);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-        core_str::StrExt::find(&self[..], pat)
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
+        core_str::StrExt::matches(self, pat)
     }
 
-    /// Returns the byte index of the last character of `self` that
-    /// matches the pattern, if it
-    /// exists.
+    /// An iterator over the matches of a pattern within `self`, yielded in
+    /// reverse order.
     ///
-    /// Returns `None` if it doesn't exist.
+    /// 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 the split.
+    /// # Iterator behavior
     ///
-    /// # Examples
+    /// 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.
     ///
-    /// Simple patterns:
+    /// For iterating from the front, `matches()` can be used.
+    ///
+    /// # Examples
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
     ///
-    /// assert_eq!(s.rfind('L'), Some(13));
-    /// assert_eq!(s.rfind('é'), Some(14));
+    /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
+    /// assert_eq!(v, ["3", "2", "1"]);
     /// ```
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rmatches(self, pat)
+    }
+
+    /// An iterator over the start and end indices of the disjoint matches
+    /// of a pattern within `self`.
     ///
-    /// More complex patterns with closures:
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the first
+    /// match are returned.
     ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
+    /// 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.
     ///
-    /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12));
-    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
-    /// ```
+    /// # Iterator behavior
     ///
-    /// Not finding the pattern:
+    /// 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`.
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, `rmatch_indices()` can be used.
+    ///
+    /// # Examples
     ///
     /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
+    /// # #![feature(str_match_indices)]
+    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
+    /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
     ///
-    /// assert_eq!(s.rfind(x), None);
+    /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
+    /// assert_eq!(v, [(1, 4), (4, 7)]);
+    ///
+    /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
+    /// assert_eq!(v, [(0, 3)]); // only the first `aba`
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rfind(&self[..], pat)
+    #[unstable(feature = "str_match_indices",
+               reason = "might have its iterator type changed")]
+    // NB: Right now MatchIndices yields `(usize, usize)`, but it would
+    // be more consistent with `matches` and `char_indices` to return `(usize, &str)`
+    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
+        core_str::StrExt::match_indices(self, pat)
     }
 
-    /// Retrieves the first character from a `&str` and returns it.
+    /// An iterator over the start and end indices of the disjoint matches of
+    /// a pattern within
+    /// `self`, yielded in reverse order.
     ///
-    /// This does not allocate a new string; instead, it returns a slice that
-    /// points one character
-    /// beyond the character that was shifted.
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the last
+    /// match are returned.
     ///
-    /// If the slice does not contain any characters, None is returned instead.
+    /// 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.
+    ///
+    /// # 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 same elements.
+    ///
+    /// For iterating from the front, `match_indices()` can be used.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(str_char)]
-    /// let s = "Löwe 老虎 Léopard";
-    /// let (c, s1) = s.slice_shift_char().unwrap();
-    ///
-    /// assert_eq!(c, 'L');
-    /// assert_eq!(s1, "öwe 老虎 Léopard");
+    /// # #![feature(str_match_indices)]
+    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
     ///
-    /// let (c, s2) = s1.slice_shift_char().unwrap();
+    /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(4, 7), (1, 4)]);
     ///
-    /// assert_eq!(c, 'ö');
-    /// assert_eq!(s2, "we 老虎 Léopard");
+    /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
+    /// assert_eq!(v, [(2, 5)]); // only the last `aba`
     /// ```
-    #[unstable(feature = "str_char",
-               reason = "awaiting conventions about shifting and slices and \
-                         may not be warranted with the existence of the chars \
-                         and/or char_indices iterators")]
-    pub fn slice_shift_char(&self) -> Option<(char, &str)> {
-        core_str::StrExt::slice_shift_char(&self[..])
+    #[unstable(feature = "str_match_indices",
+               reason = "might have its iterator type changed")]
+    // NB: Right now RMatchIndices yields `(usize, usize)`, but it would
+    // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
+    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rmatch_indices(self, pat)
     }
 
     /// Returns the byte offset of an inner slice relative to an enclosing
@@ -1597,7 +1665,7 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(subslice_offset)]
     /// let string = "a\nb\nc";
     /// let lines: Vec<&str> = string.lines().collect();
     ///
@@ -1605,261 +1673,261 @@ impl str {
     /// assert!(string.subslice_offset(lines[1]) == 2); // &"b"
     /// assert!(string.subslice_offset(lines[2]) == 4); // &"c"
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "subslice_offset",
                reason = "awaiting convention about comparability of arbitrary slices")]
     pub fn subslice_offset(&self, inner: &str) -> usize {
-        core_str::StrExt::subslice_offset(&self[..], inner)
+        core_str::StrExt::subslice_offset(self, inner)
     }
 
-    /// Returns an unsafe pointer to the `&str`'s buffer.
-    ///
-    /// The caller must ensure that the string outlives this pointer, and
-    /// that it is not
-    /// reallocated (e.g. by pushing to the string).
+    /// Returns a `&str` with leading and trailing whitespace removed.
     ///
     /// # Examples
     ///
     /// ```
-    /// let s = "Hello";
-    /// let p = s.as_ptr();
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim(), "Hello\tworld");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_ptr(&self) -> *const u8 {
-        core_str::StrExt::as_ptr(&self[..])
-    }
-
-    /// Returns an iterator of `u16` over the string encoded as UTF-16.
-    #[unstable(feature = "collections",
-               reason = "this functionality may only be provided by libunicode")]
-    pub fn utf16_units(&self) -> Utf16Units {
-        Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
+    pub fn trim(&self) -> &str {
+        UnicodeStr::trim(self)
     }
 
-    /// Returns the length of `self` in bytes.
+    /// Returns a `&str` with leading whitespace removed.
     ///
     /// # Examples
     ///
     /// ```
-    /// assert_eq!("foo".len(), 3);
-    /// assert_eq!("ƒoo".len(), 4); // fancy f!
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim_left(), "Hello\tworld\t");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn len(&self) -> usize {
-        core_str::StrExt::len(&self[..])
+    pub fn trim_left(&self) -> &str {
+        UnicodeStr::trim_left(self)
     }
 
-    /// Returns true if this slice has a length of zero bytes.
+    /// Returns a `&str` with trailing whitespace removed.
     ///
     /// # Examples
     ///
     /// ```
-    /// assert!("".is_empty());
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim_right(), " Hello\tworld");
     /// ```
-    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool {
-        core_str::StrExt::is_empty(&self[..])
+    pub fn trim_right(&self) -> &str {
+        UnicodeStr::trim_right(self)
     }
 
-    /// Parses `self` into the specified type.
+    /// Returns a string with all pre- and suffixes that match a pattern
+    /// repeatedly removed.
     ///
-    /// # Failure
+    /// The pattern can be a simple `char`, or a closure that determines
+    /// the split.
     ///
-    /// Will return `Err` if it's not possible to parse `self` into the type.
+    /// # Examples
     ///
-    /// # Example
+    /// Simple patterns:
     ///
     /// ```
-    /// assert_eq!("4".parse::<u32>(), Ok(4));
+    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+    /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
     /// ```
     ///
-    /// Failing:
+    /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// assert!("j".parse::<u32>().is_err());
+    /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
     /// ```
-    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
-        core_str::StrExt::parse(&self[..])
+    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>
+    {
+        core_str::StrExt::trim_matches(self, pat)
     }
 
-    /// Returns an iterator over the [grapheme clusters][graphemes] of `self`.
-    ///
-    /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
+    /// Returns a string with all prefixes that match a pattern
+    /// repeatedly removed.
     ///
-    /// If `is_extended` is true, the iterator is over the
-    /// *extended grapheme clusters*;
-    /// otherwise, the iterator is over the *legacy grapheme clusters*.
-    /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
-    /// recommends extended grapheme cluster boundaries for general processing.
+    /// The pattern can be a simple `&str`, `char`, or a closure that
+    /// determines the split.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(unicode, core)]
-    /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>();
-    /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"];
-    ///
-    /// assert_eq!(&gr1[..], b);
-    ///
-    /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
-    /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
+    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
     ///
-    /// assert_eq!(&gr2[..], b);
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
     /// ```
-    #[deprecated(reason = "use the crates.io `unicode-segmentation` library instead",
-             since = "1.0.0")]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may only be provided by libunicode")]
-    pub fn graphemes(&self, is_extended: bool) -> Graphemes {
-        UnicodeStr::graphemes(&self[..], is_extended)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+        core_str::StrExt::trim_left_matches(self, pat)
     }
 
-    /// Returns an iterator over the grapheme clusters of `self` and their
-    /// byte offsets. See
-    /// `graphemes()` for more information.
+    /// Returns a string with all suffixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a simple `&str`, `char`, or a closure that
+    /// determines the split.
     ///
     /// # Examples
     ///
+    /// Simple patterns:
+    ///
     /// ```
-    /// # #![feature(unicode, core)]
-    /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>();
-    /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
+    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
     ///
-    /// assert_eq!(&gr_inds[..], b);
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
     /// ```
-    #[deprecated(reason = "use the crates.io `unicode-segmentation` library instead",
-             since = "1.0.0")]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may only be provided by libunicode")]
-    pub fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
-        UnicodeStr::grapheme_indices(&self[..], is_extended)
-    }
-
-    /// An iterator over the non-empty substrings of `self` which contain no whitespace,
-    /// and which are separated by any amount of whitespace.
     ///
-    /// # Examples
+    /// A more complex pattern, using a closure:
     ///
     /// ```
-    /// # #![feature(str_words)]
-    /// # #![allow(deprecated)]
-    /// let some_words = " Mary   had\ta little  \n\t lamb";
-    /// let v: Vec<&str> = some_words.words().collect();
-    ///
-    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    /// assert_eq!("1fooX".trim_left_matches(|c| c == '1' || c == 'X'), "fooX");
     /// ```
-    #[deprecated(reason = "words() will be removed. Use split_whitespace() instead",
-                 since = "1.1.0")]
-    #[unstable(feature = "str_words",
-               reason = "the precise algorithm to use is unclear")]
-    #[allow(deprecated)]
-    pub fn words(&self) -> Words {
-        UnicodeStr::words(&self[..])
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::trim_right_matches(self, pat)
     }
 
-    /// An iterator over the non-empty substrings of `self` which contain no whitespace,
-    /// and which are separated by any amount of whitespace.
-    ///
-    /// # Examples
+    /// Parses `self` into the specified type.
     ///
-    /// ```
-    /// let some_words = " Mary   had\ta little  \n\t lamb";
-    /// let v: Vec<&str> = some_words.split_whitespace().collect();
+    /// # Failure
     ///
-    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
-    /// ```
-    #[stable(feature = "split_whitespace", since = "1.1.0")]
-    pub fn split_whitespace(&self) -> SplitWhitespace {
-        UnicodeStr::split_whitespace(&self[..])
-    }
-
-    /// Returns a string's displayed width in columns.
+    /// Will return `Err` if it's not possible to parse `self` into the type.
     ///
-    /// Control characters have zero width.
+    /// # Example
     ///
-    /// `is_cjk` determines behavior for characters in the Ambiguous category:
-    /// if `is_cjk` is
-    /// `true`, these are 2 columns wide; otherwise, they are 1.
-    /// In CJK locales, `is_cjk` should be
-    /// `true`, else it should be `false`.
-    /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
-    /// recommends that these
-    /// characters be treated as 1 column (i.e., `is_cjk = false`) if the
-    /// locale is unknown.
-    #[deprecated(reason = "use the crates.io `unicode-width` library instead",
-                 since = "1.0.0")]
-    #[unstable(feature = "unicode",
-               reason = "this functionality may only be provided by libunicode")]
-    pub fn width(&self, is_cjk: bool) -> usize {
-        UnicodeStr::width(&self[..], is_cjk)
-    }
-
-    /// Returns a `&str` with leading and trailing whitespace removed.
+    /// ```
+    /// assert_eq!("4".parse::<u32>(), Ok(4));
+    /// ```
     ///
-    /// # Examples
+    /// Failing:
     ///
     /// ```
-    /// let s = " Hello\tworld\t";
-    /// assert_eq!(s.trim(), "Hello\tworld");
+    /// assert!("j".parse::<u32>().is_err());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim(&self) -> &str {
-        UnicodeStr::trim(&self[..])
+    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
+        core_str::StrExt::parse(self)
     }
 
-    /// Returns a `&str` with leading whitespace removed.
+    /// Replaces all occurrences of one string with another.
+    ///
+    /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a
+    /// second `&str` to
+    /// replace it with. If the original `&str` isn't found, no change occurs.
     ///
     /// # Examples
     ///
     /// ```
-    /// let s = " Hello\tworld\t";
-    /// assert_eq!(s.trim_left(), "Hello\tworld\t");
+    /// let s = "this is old";
+    ///
+    /// assert_eq!(s.replace("old", "new"), "this is new");
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left(&self) -> &str {
-        UnicodeStr::trim_left(&self[..])
-    }
-
-    /// Returns a `&str` with trailing whitespace removed.
     ///
-    /// # Examples
+    /// When a `&str` isn't found:
     ///
     /// ```
-    /// let s = " Hello\tworld\t";
-    /// assert_eq!(s.trim_right(), " Hello\tworld");
+    /// let s = "this is old";
+    /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right(&self) -> &str {
-        UnicodeStr::trim_right(&self[..])
+    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) {
+            result.push_str(unsafe { self.slice_unchecked(last_end, start) });
+            result.push_str(to);
+            last_end = end;
+        }
+        result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
+        result
     }
 
     /// Returns the lowercase equivalent of this string.
     ///
     /// # Examples
     ///
+    /// ```
+    /// #![feature(str_casing)]
+    ///
     /// let s = "HELLO";
     /// assert_eq!(s.to_lowercase(), "hello");
-    #[unstable(feature = "collections")]
+    /// ```
+    #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_lowercase(&self) -> String {
         let mut s = String::with_capacity(self.len());
-        s.extend(self[..].chars().flat_map(|c| c.to_lowercase()));
+        for (i, c) in self[..].char_indices() {
+            if c == 'Σ' {
+                // Σ maps to σ, except at the end of a word where it maps to ς.
+                // This is the only conditional (contextual) but language-independent mapping
+                // in `SpecialCasing.txt`,
+                // so hard-code it rather than have a generic "condition" mechanim.
+                // See https://github.com/rust-lang/rust/issues/26035
+                map_uppercase_sigma(self, i, &mut s)
+            } else {
+                s.extend(c.to_lowercase());
+            }
+        }
         return s;
+
+        fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) {
+            // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
+            // for the definition of `Final_Sigma`.
+            debug_assert!('Σ'.len_utf8() == 2);
+            let is_word_final =
+                case_ignoreable_then_cased(from[..i].chars().rev()) &&
+                !case_ignoreable_then_cased(from[i + 2..].chars());
+            to.push_str(if is_word_final { "ς" } else { "σ" });
+        }
+
+        fn case_ignoreable_then_cased<I: Iterator<Item=char>>(iter: I) -> bool {
+            use rustc_unicode::derived_property::{Cased, Case_Ignorable};
+            match iter.skip_while(|&c| Case_Ignorable(c)).next() {
+                Some(c) => Cased(c),
+                None => false,
+            }
+        }
     }
 
     /// Returns the uppercase equivalent of this string.
     ///
     /// # Examples
     ///
+    /// ```
+    /// #![feature(str_casing)]
+    ///
     /// let s = "hello";
     /// assert_eq!(s.to_uppercase(), "HELLO");
-    #[unstable(feature = "collections")]
+    /// ```
+    #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_uppercase(&self) -> String {
         let mut s = String::with_capacity(self.len());
-        s.extend(self[..].chars().flat_map(|c| c.to_uppercase()));
+        s.extend(self.chars().flat_map(|c| c.to_uppercase()));
         return s;
     }
+
+    /// Escapes each char in `s` with `char::escape_default`.
+    #[unstable(feature = "str_escape",
+               reason = "return type may change to be an iterator")]
+    pub fn escape_default(&self) -> String {
+        self.chars().flat_map(|c| c.escape_default()).collect()
+    }
+
+    /// Escapes each char in `s` with `char::escape_unicode`.
+    #[unstable(feature = "str_escape",
+               reason = "return type may change to be an iterator")]
+    pub fn escape_unicode(&self) -> String {
+        self.chars().flat_map(|c| c.escape_unicode()).collect()
+    }
 }
index 28e476742911b77dbe8c251c39b929f77e8717c5..6e37a5731b384b82a60c78d4d1a8ce294cc37ca1 100644 (file)
@@ -88,13 +88,13 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, core)]
-    /// let s = String::from_str("hello");
+    /// # #![feature(collections)]
+    /// let s = String::from("hello");
     /// assert_eq!(&s[..], "hello");
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "needs investigation to see if to_string() can match perf")]
+    #[unstable(feature = "collections", reason = "use `String::from` instead")]
+    #[deprecated(since = "1.2.0", reason = "use `String::from` instead")]
     #[cfg(not(test))]
     pub fn from_str(string: &str) -> String {
         String { vec: <[_]>::to_vec(string.as_bytes()) }
@@ -121,9 +121,6 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    /// use std::str::Utf8Error;
-    ///
     /// let hello_vec = vec![104, 101, 108, 108, 111];
     /// let s = String::from_utf8(hello_vec).unwrap();
     /// assert_eq!(s, "hello");
@@ -346,8 +343,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let s = String::from_str("hello");
+    /// let s = String::from("hello");
     /// let bytes = s.into_bytes();
     /// assert_eq!(bytes, [104, 101, 108, 108, 111]);
     /// ```
@@ -370,8 +366,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("foo");
+    /// let mut s = String::from("foo");
     /// s.push_str("bar");
     /// assert_eq!(s, "foobar");
     /// ```
@@ -433,7 +428,7 @@ impl String {
     ///
     /// ```
     /// let mut s = String::new();
-    /// s.reserve(10);
+    /// s.reserve_exact(10);
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
@@ -447,8 +442,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("foo");
+    /// let mut s = String::from("foo");
     /// s.reserve(100);
     /// assert!(s.capacity() >= 100);
     /// s.shrink_to_fit();
@@ -465,8 +459,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("abc");
+    /// let mut s = String::from("abc");
     /// s.push('1');
     /// s.push('2');
     /// s.push('3');
@@ -475,24 +468,24 @@ impl String {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, ch: char) {
-        if (ch as u32) < 0x80 {
-            self.vec.push(ch as u8);
-            return;
-        }
+        match ch.len_utf8() {
+            1 => self.vec.push(ch as u8),
+            ch_len => {
+                let cur_len = self.len();
+                // This may use up to 4 bytes.
+                self.vec.reserve(ch_len);
 
-        let cur_len = self.len();
-        // This may use up to 4 bytes.
-        self.vec.reserve(4);
-
-        unsafe {
-            // Attempt to not use an intermediate buffer by just pushing bytes
-            // directly onto this string.
-            let slice = slice::from_raw_parts_mut (
-                self.vec.as_mut_ptr().offset(cur_len as isize),
-                4
-            );
-            let used = ch.encode_utf8(slice).unwrap_or(0);
-            self.vec.set_len(cur_len + used);
+                unsafe {
+                    // Attempt to not use an intermediate buffer by just pushing bytes
+                    // directly onto this string.
+                    let slice = slice::from_raw_parts_mut (
+                        self.vec.as_mut_ptr().offset(cur_len as isize),
+                        ch_len
+                    );
+                    let used = ch.encode_utf8(slice).unwrap_or(0);
+                    self.vec.set_len(cur_len + used);
+                }
+            }
         }
     }
 
@@ -501,10 +494,8 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let s = String::from_str("hello");
-    /// let b: &[_] = &[104, 101, 108, 108, 111];
-    /// assert_eq!(s.as_bytes(), b);
+    /// let s = String::from("hello");
+    /// assert_eq!(s.as_bytes(), [104, 101, 108, 108, 111]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -522,8 +513,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("hello");
+    /// let mut s = String::from("hello");
     /// s.truncate(2);
     /// assert_eq!(s, "he");
     /// ```
@@ -540,8 +530,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("foo");
+    /// let mut s = String::from("foo");
     /// assert_eq!(s.pop(), Some('o'));
     /// assert_eq!(s.pop(), Some('o'));
     /// assert_eq!(s.pop(), Some('f'));
@@ -578,8 +567,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("foo");
+    /// let mut s = String::from("foo");
     /// assert_eq!(s.remove(0), 'f');
     /// assert_eq!(s.remove(1), 'o');
     /// assert_eq!(s.remove(0), 'o');
@@ -641,8 +629,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut s = String::from_str("hello");
+    /// let mut s = String::from("hello");
     /// unsafe {
     ///     let vec = s.as_mut_vec();
     ///     assert!(vec == &[104, 101, 108, 108, 111]);
@@ -709,7 +696,7 @@ impl String {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections_drain)]
+    /// # #![feature(drain)]
     ///
     /// let mut s = String::from("α is alpha, β is beta");
     /// let beta_offset = s.find('β').unwrap_or(s.len());
@@ -723,7 +710,7 @@ impl String {
     /// s.drain(..);
     /// assert_eq!(s, "");
     /// ```
-    #[unstable(feature = "collections_drain",
+    #[unstable(feature = "drain",
                reason = "recently added, matches RFC")]
     pub fn drain<R>(&mut self, range: R) -> Drain where R: RangeArgument<usize> {
         // Memory safety
@@ -806,6 +793,13 @@ impl Extend<char> for String {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a> Extend<&'a char> for String {
+    fn extend<I: IntoIterator<Item=&'a char>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Extend<&'a str> for String {
     fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
@@ -981,10 +975,14 @@ impl ops::Deref for String {
 
 /// Wrapper type providing a `&String` reference via `Deref`.
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub struct DerefString<'a> {
     x: DerefVec<'a, u8>
 }
 
+#[allow(deprecated)]
 impl<'a> Deref for DerefString<'a> {
     type Target = String;
 
@@ -1011,11 +1009,14 @@ impl<'a> Deref for DerefString<'a> {
 /// string_consumer(&as_string("foo"));
 /// ```
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
     DerefString { x: as_vec(x.as_bytes()) }
 }
 
-/// Error returned from `String::from_str`
+/// Error returned from `String::from`
 #[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
                                                   Void if it ever exists")]
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -1026,7 +1027,7 @@ impl FromStr for String {
     type Err = ParseError;
     #[inline]
     fn from_str(s: &str) -> Result<String, ParseError> {
-        Ok(String::from_str(s))
+        Ok(String::from(s))
     }
 }
 
@@ -1140,7 +1141,7 @@ impl fmt::Write for String {
 }
 
 /// A draining iterator for `String`.
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 pub struct Drain<'a> {
     /// Will be used as &'a mut String in the destructor
     string: *mut String,
@@ -1155,7 +1156,7 @@ pub struct Drain<'a> {
 unsafe impl<'a> Sync for Drain<'a> {}
 unsafe impl<'a> Send for Drain<'a> {}
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> Drop for Drain<'a> {
     fn drop(&mut self) {
         unsafe {
@@ -1169,7 +1170,7 @@ impl<'a> Drop for Drain<'a> {
     }
 }
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> Iterator for Drain<'a> {
     type Item = char;
 
@@ -1183,7 +1184,7 @@ impl<'a> Iterator for Drain<'a> {
     }
 }
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> DoubleEndedIterator for Drain<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
index e35d81d3996b359e1e3a90f849b465105fcaa26d..4ea26509fd9e8afdff6f24a466e3fce441b6ebe1 100644 (file)
@@ -11,7 +11,8 @@
 //! A growable list type with heap-allocated contents, written `Vec<T>` but
 //! pronounced 'vector.'
 //!
-//! Vectors have `O(1)` indexing, push (to the end) and pop (from the end).
+//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and
+//! `O(1)` pop (from the end).
 //!
 //! # Examples
 //!
@@ -65,7 +66,7 @@ use core::cmp::max;
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{self, Hash};
-use core::intrinsics::assume;
+use core::intrinsics::{arith_offset, assume};
 use core::iter::{repeat, FromIterator};
 use core::marker::PhantomData;
 use core::mem;
@@ -82,14 +83,13 @@ use borrow::{Cow, IntoCow};
 use super::range::RangeArgument;
 
 // FIXME- fix places which assume the max vector allowed has memory usize::MAX.
-static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
+const MAX_MEMORY_SIZE: usize = isize::MAX as usize;
 
 /// A growable list type, written `Vec<T>` but pronounced 'vector.'
 ///
 /// # Examples
 ///
 /// ```
-/// # #![feature(collections)]
 /// let mut vec = Vec::new();
 /// vec.push(1);
 /// vec.push(2);
@@ -103,9 +103,9 @@ static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
 /// vec[0] = 7;
 /// assert_eq!(vec[0], 7);
 ///
-/// vec.push_all(&[1, 2, 3]);
+/// vec.extend([1, 2, 3].iter().cloned());
 ///
-/// for x in vec.iter() {
+/// for x in &vec {
 ///     println!("{}", x);
 /// }
 /// assert_eq!(vec, [7, 1, 2, 3]);
@@ -219,7 +219,7 @@ impl<T> Vec<T> {
         } else {
             let size = capacity.checked_mul(mem::size_of::<T>())
                                .expect("capacity overflow");
-            let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
+            let ptr = unsafe { allocate(size, mem::align_of::<T>()) };
             if ptr.is_null() { ::alloc::oom() }
             unsafe { Vec::from_raw_parts(ptr as *mut T, 0, capacity) }
         }
@@ -276,8 +276,10 @@ impl<T> Vec<T> {
     /// the buffer are copied into the vector without cloning, as if
     /// `ptr::read()` were called on them.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_from_raw_buf",
                reason = "may be better expressed via composition")]
+    #[deprecated(since = "1.2.0",
+                 reason = "use slice::from_raw_parts + .to_vec() instead")]
     pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
         dst.set_len(elts);
@@ -367,9 +369,8 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.push_all(&[1, 2, 3]);
+    /// vec.extend([1, 2, 3].iter().cloned());
     /// assert_eq!(vec.capacity(), 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
@@ -392,7 +393,7 @@ impl<T> Vec<T> {
                 let ptr = reallocate(*self.ptr as *mut u8,
                                      self.cap * mem::size_of::<T>(),
                                      self.len * mem::size_of::<T>(),
-                                     mem::min_align_of::<T>()) as *mut T;
+                                     mem::align_of::<T>()) as *mut T;
                 if ptr.is_null() { ::alloc::oom() }
                 self.ptr = Unique::new(ptr);
             }
@@ -423,7 +424,6 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.truncate(2);
     /// assert_eq!(vec, [1, 2]);
@@ -442,6 +442,8 @@ impl<T> Vec<T> {
     }
 
     /// Extracts a slice containing the entire vector.
+    ///
+    /// Equivalent to `&s[..]`.
     #[inline]
     #[unstable(feature = "convert",
                reason = "waiting on RFC revision")]
@@ -449,7 +451,9 @@ impl<T> Vec<T> {
         self
     }
 
-    /// Deprecated: use `&mut s[..]` instead.
+    /// Extracts a mutable slice of the entire vector.
+    ///
+    /// Equivalent to `&mut s[..]`.
     #[inline]
     #[unstable(feature = "convert",
                reason = "waiting on RFC revision")]
@@ -553,7 +557,6 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// let mut v = vec![1, 2, 3];
     /// assert_eq!(v.remove(1), 2);
     /// assert_eq!(v, [1, 3]);
@@ -695,7 +698,7 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(append)]
     /// let mut vec = vec![1, 2, 3];
     /// let mut vec2 = vec![4, 5, 6];
     /// vec.append(&mut vec2);
@@ -703,7 +706,7 @@ impl<T> Vec<T> {
     /// assert_eq!(vec2, []);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "new API, waiting for dust to settle")]
     pub fn append(&mut self, other: &mut Self) {
         if mem::size_of::<T>() == 0 {
@@ -741,7 +744,7 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections_drain, collections_range)]
+    /// # #![feature(drain)]
     ///
     /// // Draining using `..` clears the whole vector.
     /// let mut v = vec![1, 2, 3];
@@ -749,7 +752,7 @@ impl<T> Vec<T> {
     /// assert_eq!(v, &[]);
     /// assert_eq!(u, &[1, 2, 3]);
     /// ```
-    #[unstable(feature = "collections_drain",
+    #[unstable(feature = "drain",
                reason = "recently added, matches RFC")]
     pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
         // Memory safety
@@ -839,7 +842,7 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, core)]
+    /// # #![feature(map_in_place)]
     /// let v = vec![0, 1, 2];
     /// let w = v.map_in_place(|i| i + 3);
     /// assert_eq!(&w[..], &[3, 4, 5]);
@@ -850,7 +853,7 @@ impl<T> Vec<T> {
     /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
     /// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "map_in_place",
                reason = "API may change to provide stronger guarantees")]
     pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
         // FIXME: Assert statically that the types `T` and `U` have the same
@@ -863,9 +866,9 @@ impl<T> Vec<T> {
             // FIXME: Assert statically that the types `T` and `U` have the
             // same minimal alignment in case they are not zero-sized.
 
-            // These asserts are necessary because the `min_align_of` of the
+            // These asserts are necessary because the `align_of` of the
             // types are passed to the allocator by `Vec`.
-            assert!(mem::min_align_of::<T>() == mem::min_align_of::<U>());
+            assert!(mem::align_of::<T>() == mem::align_of::<U>());
 
             // This `as isize` cast is safe, because the size of the elements of the
             // vector is not 0, and:
@@ -1042,14 +1045,14 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(split_off)]
     /// let mut vec = vec![1,2,3];
     /// let vec2 = vec.split_off(1);
     /// assert_eq!(vec, [1]);
     /// assert_eq!(vec2, [2, 3]);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "new API, waiting for dust to settle")]
     pub fn split_off(&mut self, at: usize) -> Self {
         assert!(at <= self.len(), "`at` out of bounds");
@@ -1081,7 +1084,7 @@ impl<T: Clone> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vec_resize)]
     /// let mut vec = vec!["hello"];
     /// vec.resize(3, "world");
     /// assert_eq!(vec, ["hello", "world", "world"]);
@@ -1090,7 +1093,7 @@ impl<T: Clone> Vec<T> {
     /// vec.resize(2, 0);
     /// assert_eq!(vec, [1, 2]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_resize",
                reason = "matches collection reform specification; waiting for dust to settle")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
@@ -1110,13 +1113,13 @@ impl<T: Clone> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vec_push_all)]
     /// let mut vec = vec![1];
     /// vec.push_all(&[2, 3, 4]);
     /// assert_eq!(vec, [1, 2, 3, 4]);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_push_all",
                reason = "likely to be replaced by a more optimized extend")]
     pub fn push_all(&mut self, other: &[T]) {
         self.reserve(other.len());
@@ -1212,9 +1215,9 @@ impl<T: PartialEq> Vec<T> {
             // Duplicate, advance r. End of vec. Truncate to w.
 
             let ln = self.len();
-            if ln < 1 { return; }
+            if ln <= 1 { return; }
 
-            // Avoid bounds checks by using unsafe pointers.
+            // Avoid bounds checks by using raw pointers.
             let p = self.as_mut_ptr();
             let mut r: usize = 1;
             let mut w: usize = 1;
@@ -1266,9 +1269,9 @@ impl<T> Vec<T> {
 #[inline(never)]
 unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: usize, size: usize) -> *mut T {
     if old_size == 0 {
-        allocate(size, mem::min_align_of::<T>()) as *mut T
+        allocate(size, mem::align_of::<T>()) as *mut T
     } else {
-        reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<T>()) as *mut T
+        reallocate(ptr as *mut u8, old_size, size, mem::align_of::<T>()) as *mut T
     }
 }
 
@@ -1277,7 +1280,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
     if mem::size_of::<T>() != 0 {
         deallocate(ptr as *mut u8,
                    len * mem::size_of::<T>(),
-                   mem::min_align_of::<T>())
+                   mem::align_of::<T>())
     }
 }
 
@@ -1330,7 +1333,7 @@ impl<T:Clone> Clone for Vec<T> {
         }
 
         // reuse the contained values' allocations/resources.
-        for (place, thing) in self.iter_mut().zip(other.iter()) {
+        for (place, thing) in self.iter_mut().zip(other) {
             place.clone_from(thing)
         }
 
@@ -1468,42 +1471,26 @@ impl<T> ops::DerefMut for Vec<T> {
 impl<T> FromIterator<T> for Vec<T> {
     #[inline]
     fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Vec<T> {
+        // Unroll the first iteration, as the vector is going to be
+        // expanded on this iteration in every case when the iterable is not
+        // empty, but the loop in extend_desugared() is not going to see the
+        // vector being full in the few subsequent loop iterations.
+        // So we get better branch prediction and the possibility to
+        // construct the vector with initial estimated capacity.
         let mut iterator = iterable.into_iter();
-        let (lower, _) = iterator.size_hint();
-        let mut vector = Vec::with_capacity(lower);
-
-        // This function should be the moral equivalent of:
-        //
-        //      for item in iterator {
-        //          vector.push(item);
-        //      }
-        //
-        // This equivalent crucially runs the iterator precisely once. Below we
-        // actually in theory run the iterator twice (one without bounds checks
-        // and one with). To achieve the "moral equivalent", we use the `if`
-        // statement below to break out early.
-        //
-        // If the first loop has terminated, then we have one of two conditions.
-        //
-        // 1. The underlying iterator returned `None`. In this case we are
-        //    guaranteed that less than `vector.capacity()` elements have been
-        //    returned, so we break out early.
-        // 2. The underlying iterator yielded `vector.capacity()` elements and
-        //    has not yielded `None` yet. In this case we run the iterator to
-        //    its end below.
-        for element in iterator.by_ref().take(vector.capacity()) {
-            let len = vector.len();
-            unsafe {
-                ptr::write(vector.get_unchecked_mut(len), element);
-                vector.set_len(len + 1);
-            }
-        }
-
-        if vector.len() == vector.capacity() {
-            for element in iterator {
-                vector.push(element);
+        let mut vector = match iterator.next() {
+            None => return Vec::new(),
+            Some(element) => {
+                let (lower, _) = iterator.size_hint();
+                let mut vector = Vec::with_capacity(lower.saturating_add(1));
+                unsafe {
+                    ptr::write(vector.get_unchecked_mut(0), element);
+                    vector.set_len(1);
+                }
+                vector
             }
-        }
+        };
+        vector.extend_desugared(iterator);
         vector
     }
 }
@@ -1534,7 +1521,7 @@ impl<T> IntoIterator for Vec<T> {
             let cap = self.cap;
             let begin = ptr as *const T;
             let end = if mem::size_of::<T>() == 0 {
-                (ptr as usize + self.len()) as *const T
+                arith_offset(ptr as *const i8, self.len() as isize) as *const T
             } else {
                 ptr.offset(self.len() as isize) as *const T
             };
@@ -1568,15 +1555,39 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
 impl<T> Extend<T> for Vec<T> {
     #[inline]
     fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
-        let iterator = iterable.into_iter();
-        let (lower, _) = iterator.size_hint();
-        self.reserve(lower);
-        for element in iterator {
-            self.push(element)
+        self.extend_desugared(iterable.into_iter())
+    }
+}
+
+impl<T> Vec<T> {
+    fn extend_desugared<I: Iterator<Item=T>>(&mut self, mut iterator: I) {
+        // This function should be the moral equivalent of:
+        //
+        //      for item in iterator {
+        //          self.push(item);
+        //      }
+        while let Some(element) = iterator.next() {
+            let len = self.len();
+            if len == self.capacity() {
+                let (lower, _) = iterator.size_hint();
+                self.reserve(lower.saturating_add(1));
+            }
+            unsafe {
+                ptr::write(self.get_unchecked_mut(len), element);
+                // NB can't overflow since we would have had to alloc the address space
+                self.set_len(len + 1);
+            }
         }
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
+    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 __impl_slice_eq1! { Vec<A>, Vec<B> }
 __impl_slice_eq1! { Vec<A>, &'b [B] }
 __impl_slice_eq1! { Vec<A>, &'b mut [B] }
@@ -1631,7 +1642,7 @@ impl<T> Drop for Vec<T> {
         // zeroed (when moving out, because of #[unsafe_no_drop_flag]).
         if self.cap != 0 && self.cap != mem::POST_DROP_USIZE {
             unsafe {
-                for x in &*self {
+                for x in self.iter() {
                     ptr::read(x);
                 }
                 dealloc(*self.ptr, self.cap)
@@ -1699,12 +1710,14 @@ impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
     }
 }
 
+#[allow(deprecated)]
 impl<'a, T: 'a> IntoCow<'a, [T]> for Vec<T> where T: Clone {
     fn into_cow(self) -> Cow<'a, [T]> {
         Cow::Owned(self)
     }
 }
 
+#[allow(deprecated)]
 impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone {
     fn into_cow(self) -> Cow<'a, [T]> {
         Cow::Borrowed(self)
@@ -1730,7 +1743,7 @@ unsafe impl<T: Sync> Sync for IntoIter<T> { }
 impl<T> IntoIter<T> {
     #[inline]
     /// Drops all items that have not yet been moved and returns the empty vector.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "iter_to_vec")]
     pub fn into_inner(mut self) -> Vec<T> {
         unsafe {
             for _x in self.by_ref() { }
@@ -1755,7 +1768,7 @@ impl<T> Iterator for IntoIter<T> {
                     // purposefully don't use 'ptr.offset' because for
                     // vectors with 0-size elements this would return the
                     // same pointer.
-                    self.ptr = mem::transmute(self.ptr as usize + 1);
+                    self.ptr = arith_offset(self.ptr as *const i8, 1) as *const T;
 
                     // Use a non-null pointer value
                     Some(ptr::read(EMPTY as *mut T))
@@ -1793,7 +1806,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
             } else {
                 if mem::size_of::<T>() == 0 {
                     // See above for why 'ptr.offset' isn't used
-                    self.end = mem::transmute(self.end as usize - 1);
+                    self.end = arith_offset(self.end as *const i8, -1) as *const T;
 
                     // Use a non-null pointer value
                     Some(ptr::read(EMPTY as *mut T))
@@ -1824,7 +1837,7 @@ impl<T> Drop for IntoIter<T> {
 }
 
 /// A draining iterator for `Vec<T>`.
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 pub struct Drain<'a, T: 'a> {
     /// Index of tail to preserve
     tail_start: usize,
@@ -1899,12 +1912,17 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
 
 /// Wrapper type providing a `&Vec<T>` reference via `Deref`.
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
 pub struct DerefVec<'a, T:'a> {
     x: Vec<T>,
     l: PhantomData<&'a T>,
 }
 
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 impl<'a, T> Deref for DerefVec<'a, T> {
     type Target = Vec<T>;
 
@@ -1915,6 +1933,9 @@ impl<'a, T> Deref for DerefVec<'a, T> {
 
 // Prevent the inner `Vec<T>` from attempting to deallocate memory.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 impl<'a, T> Drop for DerefVec<'a, T> {
     fn drop(&mut self) {
         self.x.len = 0;
@@ -1940,6 +1961,9 @@ impl<'a, T> Drop for DerefVec<'a, T> {
 /// vec_consumer(&as_vec(&values));
 /// ```
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
     unsafe {
         DerefVec {
index f70906f84b8692b4e36f2d1145e197ba053d15f8..ed47c06e7cd0847374cc30ac743f8cd6224e2d7b 100644 (file)
@@ -67,7 +67,7 @@ impl<T> Drop for VecDeque<T> {
             if mem::size_of::<T>() != 0 {
                 heap::deallocate(*self.ptr as *mut u8,
                                  self.cap * mem::size_of::<T>(),
-                                 mem::min_align_of::<T>())
+                                 mem::align_of::<T>())
             }
         }
     }
@@ -172,7 +172,7 @@ impl<T> VecDeque<T> {
 
         let ptr = unsafe {
             if mem::size_of::<T>() != 0 {
-                let ptr = heap::allocate(size, mem::min_align_of::<T>())  as *mut T;;
+                let ptr = heap::allocate(size, mem::align_of::<T>())  as *mut T;;
                 if ptr.is_null() { ::alloc::oom() }
                 Unique::new(ptr)
             } else {
@@ -247,7 +247,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -275,7 +274,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::VecDeque;
     ///
     /// let buf: VecDeque<i32> = VecDeque::with_capacity(10);
@@ -299,7 +297,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
@@ -321,7 +318,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
@@ -344,7 +340,7 @@ impl<T> VecDeque<T> {
                     let ptr = heap::reallocate(*self.ptr as *mut u8,
                                                old,
                                                new,
-                                               mem::min_align_of::<T>()) as *mut T;
+                                               mem::align_of::<T>()) as *mut T;
                     if ptr.is_null() { ::alloc::oom() }
                     self.ptr = Unique::new(ptr);
                 }
@@ -464,7 +460,7 @@ impl<T> VecDeque<T> {
                     let ptr = heap::reallocate(*self.ptr as *mut u8,
                                                old,
                                                new_size,
-                                               mem::min_align_of::<T>()) as *mut T;
+                                               mem::align_of::<T>()) as *mut T;
                     if ptr.is_null() { ::alloc::oom() }
                     self.ptr = Unique::new(ptr);
                 }
@@ -484,7 +480,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(deque_extras)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -495,7 +491,7 @@ impl<T> VecDeque<T> {
     /// assert_eq!(buf.len(), 1);
     /// assert_eq!(Some(&5), buf.get(0));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn truncate(&mut self, len: usize) {
         for _ in len..self.len() {
@@ -508,7 +504,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -533,7 +528,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -558,7 +552,7 @@ impl<T> VecDeque<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_slices(&self) -> (&[T], &[T]) {
         unsafe {
@@ -578,7 +572,7 @@ impl<T> VecDeque<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
         unsafe {
@@ -635,7 +629,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(drain)]
     /// use std::collections::VecDeque;
     ///
     /// let mut v = VecDeque::new();
@@ -644,7 +638,7 @@ impl<T> VecDeque<T> {
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain {
@@ -874,7 +868,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(deque_extras)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -886,7 +880,7 @@ impl<T> VecDeque<T> {
     /// buf.push_back(10);
     /// assert_eq!(buf.swap_back_remove(1), Some(99));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "the naming of this function may be altered")]
     pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
         let length = self.len();
@@ -898,8 +892,8 @@ impl<T> VecDeque<T> {
         self.pop_back()
     }
 
-    /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first
-    /// element.
+    /// Removes an element from anywhere in the ringbuf and returns it,
+    /// replacing it with the first element.
     ///
     /// This does not preserve ordering, but is O(1).
     ///
@@ -908,7 +902,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(deque_extras)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -920,7 +914,7 @@ impl<T> VecDeque<T> {
     /// buf.push_back(20);
     /// assert_eq!(buf.swap_front_remove(3), Some(99));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "the naming of this function may be altered")]
     pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
         let length = self.len();
@@ -1316,7 +1310,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(split_off)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
@@ -1326,7 +1320,7 @@ impl<T> VecDeque<T> {
     /// assert_eq!(buf2.len(), 2);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "new API, waiting for dust to settle")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let len = self.len();
@@ -1379,7 +1373,7 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(append)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
@@ -1389,7 +1383,7 @@ impl<T> VecDeque<T> {
     /// assert_eq!(buf2.len(), 0);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "new API, waiting for dust to settle")]
     pub fn append(&mut self, other: &mut Self) {
         // naive impl
@@ -1440,7 +1434,7 @@ impl<T: Clone> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(deque_extras)]
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -1449,11 +1443,11 @@ impl<T: Clone> VecDeque<T> {
     /// buf.push_back(15);
     /// buf.resize(2, 0);
     /// buf.resize(6, 20);
-    /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) {
+    /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(&buf) {
     ///     assert_eq!(a, b);
     /// }
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
@@ -1536,6 +1530,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl<'a, T> RandomAccessIterator for Iter<'a, T> {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1641,7 +1636,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// A draining VecDeque iterator
-#[unstable(feature = "collections",
+#[unstable(feature = "drain",
            reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, T: 'a> {
     inner: &'a mut VecDeque<T>,
@@ -1687,7 +1682,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
 impl<A: PartialEq> PartialEq for VecDeque<A> {
     fn eq(&self, other: &VecDeque<A>) -> bool {
         self.len() == other.len() &&
-            self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
+            self.iter().zip(other).all(|(a, b)| a.eq(b))
     }
 }
 
@@ -1791,6 +1786,13 @@ impl<A> Extend<A> for VecDeque<A> {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> {
+    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
+    }
+}
+
 #[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 {
@@ -1807,7 +1809,7 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
 
 #[cfg(test)]
 mod tests {
-    use core::iter::{Iterator, self};
+    use core::iter::Iterator;
     use core::option::Option::Some;
 
     use test;
index aa0ab41b7455b05d4bba2192a4525a5d58af9f8a..685bb5dc4b4f397140f4914fd370d1bcb9a1e900 100644 (file)
@@ -12,6 +12,8 @@
 //! are O(highest integer key).
 
 #![allow(missing_docs)]
+#![unstable(feature = "vecmap",
+            reason = "may not be stabilized in the standard library")]
 
 use self::Entry::*;
 
@@ -33,7 +35,7 @@ use vec::Vec;
 /// # Examples
 ///
 /// ```
-/// # #![feature(collections)]
+/// # #![feature(vecmap)]
 /// use std::collections::VecMap;
 ///
 /// let mut months = VecMap::new();
@@ -54,7 +56,7 @@ use vec::Vec;
 /// assert_eq!(months.get(&3), Some(&"Venus"));
 ///
 /// // Print out all months
-/// for (key, value) in months.iter() {
+/// for (key, value) in &months {
 ///     println!("month {} is {}", key, value);
 /// }
 ///
@@ -133,7 +135,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::new();
     /// ```
@@ -146,7 +148,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::with_capacity(10);
     /// ```
@@ -161,7 +163,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     /// let map: VecMap<String> = VecMap::with_capacity(10);
     /// assert!(map.capacity() >= 10);
@@ -181,7 +183,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::new();
     /// map.reserve_len(10);
@@ -206,7 +208,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::new();
     /// map.reserve_len_exact(10);
@@ -246,7 +248,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -275,7 +277,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -287,7 +289,7 @@ impl<V> VecMap<V> {
     ///     *value = "x";
     /// }
     ///
-    /// for (key, value) in map.iter() {
+    /// for (key, value) in &map {
     ///     assert_eq!(value, &"x");
     /// }
     /// ```
@@ -305,7 +307,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap, append)]
     /// use std::collections::VecMap;
     ///
     /// let mut a = VecMap::new();
@@ -325,7 +327,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(a[3], "c");
     /// assert_eq!(a[4], "d");
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         self.extend(other.drain());
@@ -341,7 +343,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap, split_off)]
     /// use std::collections::VecMap;
     ///
     /// let mut a = VecMap::new();
@@ -358,7 +360,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(b[3], "c");
     /// assert_eq!(b[4], "d");
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let mut other = VecMap::new();
@@ -398,7 +400,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap, drain)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -410,7 +412,7 @@ impl<V> VecMap<V> {
     ///
     /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain<'a>(&'a mut self) -> Drain<'a, V> {
         fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
@@ -426,7 +428,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut a = VecMap::new();
@@ -444,7 +446,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut a = VecMap::new();
@@ -462,7 +464,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut a = VecMap::new();
@@ -478,7 +480,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -503,7 +505,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -522,7 +524,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -550,7 +552,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -576,7 +578,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -598,7 +600,7 @@ impl<V> VecMap<V> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap, entry)]
     /// use std::collections::VecMap;
     ///
     /// let mut count: VecMap<u32> = VecMap::new();
@@ -632,7 +634,7 @@ impl<V> VecMap<V> {
 
 
 impl<'a, V> Entry<'a, V> {
-    #[unstable(feature = "collections",
+    #[unstable(feature = "entry",
                reason = "will soon be replaced by or_insert")]
     #[deprecated(since = "1.0",
                 reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
@@ -644,10 +646,9 @@ impl<'a, V> Entry<'a, V> {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// a mutable reference to the value in the entry.
+    #[stable(feature = "vecmap_entry", since = "1.2.0")]
+    /// Ensures a value is in the entry by inserting the default if empty, and
+    /// returns a mutable reference to the value in the entry.
     pub fn or_insert(self, default: V) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -655,10 +656,10 @@ impl<'a, V> Entry<'a, V> {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns a mutable reference to the value in the entry.
+    #[stable(feature = "vecmap_entry", since = "1.2.0")]
+    /// Ensures a value is in the entry by inserting the result of the default
+    /// function if empty, and returns a mutable reference to the value in the
+    /// entry.
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -777,7 +778,7 @@ impl<T> IntoIterator for VecMap<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(vecmap)]
     /// use std::collections::VecMap;
     ///
     /// let mut map = VecMap::new();
@@ -828,6 +829,13 @@ impl<V> Extend<(usize, V)> for VecMap<V> {
     }
 }
 
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, V: Copy> Extend<(usize, &'a V)> for VecMap<V> {
+    fn extend<I: IntoIterator<Item=(usize, &'a V)>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().map(|(key, &value)| (key, value)));
+    }
+}
+
 impl<V> Index<usize> for VecMap<V> {
     type Output = V;
 
@@ -996,14 +1004,14 @@ pub struct IntoIter<V> {
     fn((usize, Option<V>)) -> Option<(usize, V)>>
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 pub struct Drain<'a, V:'a> {
     iter: FilterMap<
     Enumerate<vec::Drain<'a, Option<V>>>,
     fn((usize, Option<V>)) -> Option<(usize, V)>>
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 impl<'a, V> Iterator for Drain<'a, V> {
     type Item = (usize, V);
 
@@ -1011,7 +1019,7 @@ impl<'a, V> Iterator for Drain<'a, V> {
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 impl<'a, V> DoubleEndedIterator for Drain<'a, V> {
     fn next_back(&mut self) -> Option<(usize, V)> { self.iter.next_back() }
 }
index 47a366bb1e2e0dd937eac062be37bfd06c208391..303a0ce811df6f825d60eed5d87d763ea0937e2b 100644 (file)
@@ -217,3 +217,28 @@ fn test_drain() {
 
     assert!(q.is_empty());
 }
+
+#[test]
+fn test_extend_ref() {
+    let mut a = BinaryHeap::new();
+    a.push(1);
+    a.push(2);
+
+    a.extend(&[3, 4, 5]);
+
+    assert_eq!(a.len(), 5);
+    assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
+
+    let mut a = BinaryHeap::new();
+    a.push(1);
+    a.push(2);
+    let mut b = BinaryHeap::new();
+    b.push(3);
+    b.push(4);
+    b.push(5);
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 5);
+    assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]);
+}
index e6aa15608f03eb0297afcae622927e105a55c92d..8ab3eff0f4f6425e490adf4c09b6da257867e527 100644 (file)
@@ -448,6 +448,26 @@ fn test_bit_set_split_off() {
                                                             0b00101011, 0b10101101])));
 }
 
+#[test]
+fn test_bit_set_extend_ref() {
+    let mut a = BitSet::new();
+    a.insert(3);
+
+    a.extend(&[5, 7, 10]);
+
+    assert_eq!(a.len(), 4);
+    assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010101,0b00100000])));
+
+    let mut b = BitSet::new();
+    b.insert(11);
+    b.insert(15);
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 6);
+    assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010101,0b00110001])));
+}
+
 mod bench {
     use std::collections::{BitSet, BitVec};
     use std::__rand::{Rng, thread_rng, ThreadRng};
index a1d2eed0a8b5f13089c7923193a2fbdd2ca4d272..486a651e679fdf4014f120981c828e3b3c2f0da5 100644 (file)
@@ -625,11 +625,29 @@ fn test_bit_vec_grow() {
 fn test_bit_vec_extend() {
     let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
     let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]);
-    bit_vec.extend(ext.iter());
+    bit_vec.extend(&ext);
     assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111,
                                  0b01001001, 0b10010010, 0b10111101]));
 }
 
+#[test]
+fn test_bit_vecextend_ref() {
+    let mut bv = BitVec::from_bytes(&[0b10100011]);
+    bv.extend(&[true, false, true]);
+
+    assert_eq!(bv.len(), 11);
+    assert!(bv.eq_vec(&[true, false, true, false, false, false, true, true,
+                        true, false, true]));
+
+    let bw = BitVec::from_bytes(&[0b00010001]);
+    bv.extend(&bw);
+
+    assert_eq!(bv.len(), 19);
+    assert!(bv.eq_vec(&[true, false, true, false, false, false, true, true,
+                        true, false, true, false, false, false, true, false,
+                        false, false, true]));
+}
+
 #[test]
 fn test_bit_vec_append() {
     // Append to BitVec that holds a multiple of u32::BITS bits
index 720ee2751cda0cfedfd3c2d9492b5e79a6be5f66..62b46433da95748ae6ba7d5c2ea37a5046968f03 100644 (file)
@@ -278,6 +278,22 @@ fn test_entry(){
     assert_eq!(map.len(), 6);
 }
 
+#[test]
+fn test_extend_ref() {
+    let mut a = BTreeMap::new();
+    a.insert(1, "one");
+    let mut b = BTreeMap::new();
+    b.insert(2, "two");
+    b.insert(3, "three");
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 3);
+    assert_eq!(a[&1], "one");
+    assert_eq!(a[&2], "two");
+    assert_eq!(a[&3], "three");
+}
+
 mod bench {
     use std::collections::BTreeMap;
     use std::__rand::{Rng, thread_rng};
index 234cd6e0fd21ec23994810de197661005891dc0a..56257233aa55820de7dc37b081dc521edac6216f 100644 (file)
@@ -147,7 +147,7 @@ fn test_zip() {
 
     let x = x;
     let y = y;
-    let mut z = x.iter().zip(y.iter());
+    let mut z = x.iter().zip(&y);
 
     // FIXME: #5801: this needs a type hint to compile...
     let result: Option<(&usize, & &'static str)> = z.next();
@@ -184,3 +184,31 @@ fn test_show() {
     assert_eq!(set_str, "{1, 2}");
     assert_eq!(format!("{:?}", empty), "{}");
 }
+
+#[test]
+fn test_extend_ref() {
+    let mut a = BTreeSet::new();
+    a.insert(1);
+
+    a.extend(&[2, 3, 4]);
+
+    assert_eq!(a.len(), 4);
+    assert!(a.contains(&1));
+    assert!(a.contains(&2));
+    assert!(a.contains(&3));
+    assert!(a.contains(&4));
+
+    let mut b = BTreeSet::new();
+    b.insert(5);
+    b.insert(6);
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 6);
+    assert!(a.contains(&1));
+    assert!(a.contains(&2));
+    assert!(a.contains(&3));
+    assert!(a.contains(&4));
+    assert!(a.contains(&5));
+    assert!(a.contains(&6));
+}
index 0a1eb0bcfa8879cb801191d5e6532f65fda60f40..b073c2f3ae4dd307d99ef5e79a1b3e74c8044b32 100644 (file)
@@ -242,3 +242,25 @@ fn test_overflow() {
     let mut set = EnumSet::new();
     set.insert(Bar::V64);
 }
+
+#[test]
+fn test_extend_ref() {
+    let mut a = EnumSet::new();
+    a.insert(A);
+
+    a.extend(&[A, C]);
+
+    assert_eq!(a.len(), 2);
+    assert!(a.contains(&A));
+    assert!(a.contains(&C));
+
+    let mut b = EnumSet::new();
+    b.insert(B);
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 3);
+    assert!(a.contains(&A));
+    assert!(a.contains(&B));
+    assert!(a.contains(&C));
+}
index 9b50478472fa92d30ad3f3e5c63a2c7217b174ef..20a3625fe5add309152016c88fe1884042edfcc2 100644 (file)
@@ -8,22 +8,52 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(bit_set_append_split_off)]
+#![feature(append)]
 #![feature(bit_vec_append_split_off)]
+#![feature(bitset)]
+#![feature(bitvec)]
 #![feature(box_syntax)]
+#![feature(btree_range)]
 #![feature(collections)]
-#![feature(collections_drain)]
+#![feature(collections_bound)]
+#![feature(const_fn)]
 #![feature(core)]
-#![feature(hash)]
+#![feature(deque_extras)]
+#![feature(drain)]
+#![feature(enumset)]
+#![feature(hash_default)]
+#![feature(into_cow)]
+#![feature(iter_idx)]
+#![feature(iter_order)]
+#![feature(iter_arith)]
+#![feature(iter_to_vec)]
+#![feature(map_in_place)]
+#![feature(move_from)]
+#![feature(num_bits_bytes)]
+#![feature(pattern)]
+#![feature(permutations)]
 #![feature(rand)]
+#![feature(range_inclusive)]
 #![feature(rustc_private)]
+#![feature(slice_bytes)]
+#![feature(slice_chars)]
+#![feature(slice_extras)]
+#![feature(slice_position_elem)]
+#![feature(split_off)]
+#![feature(step_by)]
+#![feature(str_char)]
+#![feature(str_escape)]
+#![feature(str_match_indices)]
+#![feature(str_utf16)]
+#![feature(subslice_offset)]
 #![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(into_cow)]
-#![feature(step_by)]
-#![cfg_attr(test, feature(str_char))]
-#![cfg_attr(test, feature(vec_deque_retain))]
+#![feature(vec_deque_retain)]
+#![feature(vec_from_raw_buf)]
+#![feature(vec_push_all)]
+#![feature(vec_split_off)]
+#![feature(vecmap)]
 
 #[macro_use] extern crate log;
 
index fd73938095f09e4338679c1612ff19e101cbe537..d04ce574ed0a5ace60e5ba3a9575655fd7601f85 100644 (file)
@@ -321,6 +321,25 @@ fn test_show() {
     assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]");
 }
 
+#[test]
+fn test_extend_ref() {
+    let mut a = LinkedList::new();
+    a.push_back(1);
+
+    a.extend(&[2, 3, 4]);
+
+    assert_eq!(a.len(), 4);
+    assert_eq!(a, list_from(&[1, 2, 3, 4]));
+
+    let mut b = LinkedList::new();
+    b.push_back(5);
+    b.push_back(6);
+    a.extend(&b);
+
+    assert_eq!(a.len(), 6);
+    assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
+}
+
 #[bench]
 fn bench_collect_into(b: &mut test::Bencher) {
     let v = &[0; 64];
index 170f49ab15be553d5177122d4033da1e65bbaf85..3f32136bc263974c62a1dfd6dea73f9879d88183 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::cmp::Ordering::{Equal, Greater, Less};
-use std::str::{Utf8Error, from_utf8};
+use std::str::from_utf8;
 
 #[test]
 fn test_le() {
@@ -71,17 +71,17 @@ fn test_rfind() {
 
 #[test]
 fn test_collect() {
-    let empty = String::from_str("");
+    let empty = String::from("");
     let s: String = empty.chars().collect();
     assert_eq!(empty, s);
-    let data = String::from_str("ประเทศไทย中");
+    let data = String::from("ประเทศไทย中");
     let s: String = data.chars().collect();
     assert_eq!(data, s);
 }
 
 #[test]
 fn test_into_bytes() {
-    let data = String::from_str("asdf");
+    let data = String::from("asdf");
     let buf = data.into_bytes();
     assert_eq!(buf, b"asdf");
 }
@@ -98,7 +98,7 @@ fn test_find_str() {
     assert!(data[2..4].find("ab").is_none());
 
     let string = "ประเทศไทย中华Việt Nam";
-    let mut data = String::from_str(string);
+    let mut data = String::from(string);
     data.push_str(string);
     assert!(data.find("ไท华").is_none());
     assert_eq!(data[0..43].find(""), Some(0));
@@ -211,7 +211,7 @@ fn test_unsafe_slice() {
     }
     let letters = a_million_letter_a();
     assert!(half_a_million_letter_a() ==
-        unsafe {String::from_str(letters.slice_unchecked(
+        unsafe {String::from(letters.slice_unchecked(
                                  0,
                                  500000))});
 }
@@ -247,13 +247,13 @@ fn test_is_empty() {
 #[test]
 fn test_replace() {
     let a = "a";
-    assert_eq!("".replace(a, "b"), String::from_str(""));
-    assert_eq!("a".replace(a, "b"), String::from_str("b"));
-    assert_eq!("ab".replace(a, "b"), String::from_str("bb"));
+    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"));
     let test = "test";
     assert!(" test test ".replace(test, "toast") ==
-        String::from_str(" toast toast "));
-    assert_eq!(" test test ".replace(test, ""), String::from_str("   "));
+        String::from(" toast toast "));
+    assert_eq!(" test test ".replace(test, ""), String::from("   "));
 }
 
 #[test]
@@ -328,7 +328,7 @@ fn test_slice() {
     }
     let letters = a_million_letter_x();
     assert!(half_a_million_letter_x() ==
-        String::from_str(&letters[0..3 * 500000]));
+        String::from(&letters[0..3 * 500000]));
 }
 
 #[test]
@@ -581,7 +581,7 @@ fn test_as_bytes() {
 fn test_as_bytes_fail() {
     // Don't double free. (I'm not sure if this exercises the
     // original problem code path anymore.)
-    let s = String::from_str("");
+    let s = String::from("");
     let _bytes = s.as_bytes();
     panic!();
 }
@@ -623,10 +623,10 @@ fn test_subslice_offset_2() {
 
 #[test]
 fn vec_str_conversions() {
-    let s1: String = String::from_str("All mimsy were the borogoves");
+    let s1: String = String::from("All mimsy were the borogoves");
 
     let v: Vec<u8> = s1.as_bytes().to_vec();
-    let s2: String = String::from_str(from_utf8(&v).unwrap());
+    let s2: String = String::from(from_utf8(&v).unwrap());
     let mut i = 0;
     let n1 = s1.len();
     let n2 = v.len();
@@ -688,42 +688,62 @@ fn test_char_at_reverse() {
     }
 }
 
+#[test]
+fn test_split_at() {
+    let s = "ศไทย中华Việt Nam";
+    for (index, _) in s.char_indices() {
+        let (a, b) = s.split_at(index);
+        assert_eq!(&s[..a.len()], a);
+        assert_eq!(&s[a.len()..], b);
+    }
+    let (a, b) = s.split_at(s.len());
+    assert_eq!(a, s);
+    assert_eq!(b, "");
+}
+
+#[test]
+#[should_panic]
+fn test_split_at_boundscheck() {
+    let s = "ศไทย中华Việt Nam";
+    let (a, b) = s.split_at(1);
+}
+
 #[test]
 fn test_escape_unicode() {
     assert_eq!("abc".escape_unicode(),
-               String::from_str("\\u{61}\\u{62}\\u{63}"));
+               String::from("\\u{61}\\u{62}\\u{63}"));
     assert_eq!("a c".escape_unicode(),
-               String::from_str("\\u{61}\\u{20}\\u{63}"));
+               String::from("\\u{61}\\u{20}\\u{63}"));
     assert_eq!("\r\n\t".escape_unicode(),
-               String::from_str("\\u{d}\\u{a}\\u{9}"));
+               String::from("\\u{d}\\u{a}\\u{9}"));
     assert_eq!("'\"\\".escape_unicode(),
-               String::from_str("\\u{27}\\u{22}\\u{5c}"));
+               String::from("\\u{27}\\u{22}\\u{5c}"));
     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(),
-               String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}"));
+               String::from("\\u{0}\\u{1}\\u{fe}\\u{ff}"));
     assert_eq!("\u{100}\u{ffff}".escape_unicode(),
-               String::from_str("\\u{100}\\u{ffff}"));
+               String::from("\\u{100}\\u{ffff}"));
     assert_eq!("\u{10000}\u{10ffff}".escape_unicode(),
-               String::from_str("\\u{10000}\\u{10ffff}"));
+               String::from("\\u{10000}\\u{10ffff}"));
     assert_eq!("ab\u{fb00}".escape_unicode(),
-               String::from_str("\\u{61}\\u{62}\\u{fb00}"));
+               String::from("\\u{61}\\u{62}\\u{fb00}"));
     assert_eq!("\u{1d4ea}\r".escape_unicode(),
-               String::from_str("\\u{1d4ea}\\u{d}"));
+               String::from("\\u{1d4ea}\\u{d}"));
 }
 
 #[test]
 fn test_escape_default() {
-    assert_eq!("abc".escape_default(), String::from_str("abc"));
-    assert_eq!("a c".escape_default(), String::from_str("a c"));
-    assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t"));
-    assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\"));
+    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_str("\\u{100}\\u{ffff}"));
+               String::from("\\u{100}\\u{ffff}"));
     assert_eq!("\u{10000}\u{10ffff}".escape_default(),
-               String::from_str("\\u{10000}\\u{10ffff}"));
+               String::from("\\u{10000}\\u{10ffff}"));
     assert_eq!("ab\u{fb00}".escape_default(),
-               String::from_str("ab\\u{fb00}"));
+               String::from("ab\\u{fb00}"));
     assert_eq!("\u{1d4ea}\r".escape_default(),
-               String::from_str("\\u{1d4ea}\\r"));
+               String::from("\\u{1d4ea}\\r"));
 }
 
 #[test]
@@ -1490,12 +1510,12 @@ fn test_str_container() {
         v.iter().map(|x| x.len()).sum()
     }
 
-    let s = String::from_str("01234");
+    let s = String::from("01234");
     assert_eq!(5, sum_len(&["012", "", "34"]));
-    assert_eq!(5, sum_len(&[&String::from_str("01"),
-                            &String::from_str("2"),
-                            &String::from_str("34"),
-                            &String::from_str("")]));
+    assert_eq!(5, sum_len(&[&String::from("01"),
+                            &String::from("2"),
+                            &String::from("34"),
+                            &String::from("")]));
     assert_eq!(5, sum_len(&[&s]));
 }
 
@@ -1687,6 +1707,45 @@ fn trim_ws() {
                "");
 }
 
+#[test]
+fn to_lowercase() {
+    assert_eq!("".to_lowercase(), "");
+    assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
+
+    // https://github.com/rust-lang/rust/issues/26035
+    assert_eq!("ΑΣ".to_lowercase(), "ας");
+    assert_eq!("Α'Σ".to_lowercase(), "α'ς");
+    assert_eq!("Α''Σ".to_lowercase(), "α''ς");
+
+    assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
+    assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
+    assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
+
+    assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
+    assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
+
+    assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
+    assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
+
+    assert_eq!("Α Σ".to_lowercase(), "α σ");
+    assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
+    assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
+
+    assert_eq!("Σ".to_lowercase(), "σ");
+    assert_eq!("'Σ".to_lowercase(), "'σ");
+    assert_eq!("''Σ".to_lowercase(), "''σ");
+
+    assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
+    assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
+    assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
+}
+
+#[test]
+fn to_uppercase() {
+    assert_eq!("".to_uppercase(), "");
+    assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
+}
+
 mod pattern {
     use std::str::pattern::Pattern;
     use std::str::pattern::{Searcher, ReverseSearcher};
@@ -1694,6 +1753,7 @@ mod pattern {
 
     macro_rules! make_test {
         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
+            #[allow(unused_imports)]
             mod $name {
                 use std::str::pattern::SearchStep::{Match, Reject};
                 use super::{cmp_search_to_vec};
index d4e2ebf4fd137e31a49fb1caa967bae1347f1d8c..257caca4016df28e8cef0f826544a4d16649bceb 100644 (file)
 
 use std::borrow::{IntoCow, Cow};
 use std::iter::repeat;
-use std::str::Utf8Error;
+#[allow(deprecated)]
 use std::string::as_string;
 
 use test::Bencher;
 
 #[test]
+#[allow(deprecated)]
 fn test_as_string() {
     let x = "foo";
     assert_eq!(x, &**as_string(x));
@@ -37,11 +38,11 @@ fn test_unsized_to_string() {
 fn test_from_utf8() {
     let xs = b"hello".to_vec();
     assert_eq!(String::from_utf8(xs).unwrap(),
-               String::from_str("hello"));
+               String::from("hello"));
 
     let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
     assert_eq!(String::from_utf8(xs).unwrap(),
-               String::from_str("ศไทย中华Việt Nam"));
+               String::from("ศไทย中华Việt Nam"));
 
     let xs = b"hello\xFF".to_vec();
     let err = String::from_utf8(xs).err().unwrap();
@@ -60,44 +61,44 @@ fn test_from_utf8_lossy() {
 
     let xs = b"Hello\xC2 There\xFF Goodbye";
     assert_eq!(String::from_utf8_lossy(xs),
-               String::from_str("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
+               String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
 
     let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
     assert_eq!(String::from_utf8_lossy(xs),
-               String::from_str("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
+               String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
 
     let xs = b"\xF5foo\xF5\x80bar";
     assert_eq!(String::from_utf8_lossy(xs),
-               String::from_str("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
+               String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
 
     let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
     assert_eq!(String::from_utf8_lossy(xs),
-               String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
+               String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
 
     let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
     assert_eq!(String::from_utf8_lossy(xs),
-               String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
+               String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
 
     let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
-    assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\
+    assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\
                                            foo\u{10000}bar").into_cow());
 
     // surrogates
     let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
-    assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}foo\
+    assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\
                                            \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
 }
 
 #[test]
 fn test_from_utf16() {
     let pairs =
-        [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
+        [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
           vec![0xd800, 0xdf45, 0xd800, 0xdf3f,
             0xd800, 0xdf3b, 0xd800, 0xdf46,
             0xd800, 0xdf39, 0xd800, 0xdf3b,
             0xd800, 0xdf30, 0x000a]),
 
-         (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
+         (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
           vec![0xd801, 0xdc12, 0xd801,
             0xdc49, 0xd801, 0xdc2e, 0xd801,
             0xdc40, 0xd801, 0xdc32, 0xd801,
@@ -105,7 +106,7 @@ fn test_from_utf16() {
             0xd801, 0xdc32, 0xd801, 0xdc4d,
             0x000a]),
 
-         (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
+         (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
           vec![0xd800, 0xdf00, 0xd800, 0xdf16,
             0xd800, 0xdf0b, 0xd800, 0xdf04,
             0xd800, 0xdf11, 0xd800, 0xdf09,
@@ -114,7 +115,7 @@ fn test_from_utf16() {
             0xdf04, 0xd800, 0xdf0b, 0xd800,
             0xdf09, 0xd800, 0xdf11, 0x000a ]),
 
-         (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
+         (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
           vec![0xd801, 0xdc8b, 0xd801, 0xdc98,
             0xd801, 0xdc88, 0xd801, 0xdc91,
             0xd801, 0xdc9b, 0xd801, 0xdc92,
@@ -127,7 +128,7 @@ fn test_from_utf16() {
             0xd801, 0xdc95, 0xd801, 0xdc86,
             0x000a ]),
          // Issue #12318, even-numbered non-BMP planes
-         (String::from_str("\u{20000}"),
+         (String::from("\u{20000}"),
           vec![0xD840, 0xDC00])];
 
     for p in &pairs {
@@ -165,22 +166,22 @@ fn test_utf16_invalid() {
 fn test_from_utf16_lossy() {
     // completely positive cases tested above.
     // lead + eof
-    assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from_str("\u{FFFD}"));
+    assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
     // lead + lead
     assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
-               String::from_str("\u{FFFD}\u{FFFD}"));
+               String::from("\u{FFFD}\u{FFFD}"));
 
     // isolated trail
-    assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}"));
+    assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
 
     // general
     assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
-               String::from_str("\u{FFFD}𐒋\u{FFFD}"));
+               String::from("\u{FFFD}𐒋\u{FFFD}"));
 }
 
 #[test]
 fn test_push_bytes() {
-    let mut s = String::from_str("ABC");
+    let mut s = String::from("ABC");
     unsafe {
         let mv = s.as_mut_vec();
         mv.push_all(&[b'D']);
@@ -201,7 +202,7 @@ fn test_push_str() {
 
 #[test]
 fn test_push() {
-    let mut data = String::from_str("ประเทศไทย中");
+    let mut data = String::from("ประเทศไทย中");
     data.push('华');
     data.push('b'); // 1 byte
     data.push('¢'); // 2 byte
@@ -212,7 +213,7 @@ fn test_push() {
 
 #[test]
 fn test_pop() {
-    let mut data = String::from_str("ประเทศไทย中华b¢€𤭢");
+    let mut data = String::from("ประเทศไทย中华b¢€𤭢");
     assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
     assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
     assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
@@ -223,7 +224,7 @@ fn test_pop() {
 
 #[test]
 fn test_str_truncate() {
-    let mut s = String::from_str("12345");
+    let mut s = String::from("12345");
     s.truncate(5);
     assert_eq!(s, "12345");
     s.truncate(3);
@@ -231,7 +232,7 @@ fn test_str_truncate() {
     s.truncate(0);
     assert_eq!(s, "");
 
-    let mut s = String::from_str("12345");
+    let mut s = String::from("12345");
     let p = s.as_ptr();
     s.truncate(3);
     s.push_str("6");
@@ -242,20 +243,20 @@ fn test_str_truncate() {
 #[test]
 #[should_panic]
 fn test_str_truncate_invalid_len() {
-    let mut s = String::from_str("12345");
+    let mut s = String::from("12345");
     s.truncate(6);
 }
 
 #[test]
 #[should_panic]
 fn test_str_truncate_split_codepoint() {
-    let mut s = String::from_str("\u{FC}"); // ü
+    let mut s = String::from("\u{FC}"); // ü
     s.truncate(1);
 }
 
 #[test]
 fn test_str_clear() {
-    let mut s = String::from_str("12345");
+    let mut s = String::from("12345");
     s.clear();
     assert_eq!(s.len(), 0);
     assert_eq!(s, "");
@@ -263,7 +264,7 @@ fn test_str_clear() {
 
 #[test]
 fn test_str_add() {
-    let a = String::from_str("12345");
+    let a = String::from("12345");
     let b = a + "2";
     let b = b + "2";
     assert_eq!(b.len(), 7);
@@ -344,7 +345,7 @@ fn test_from_iterator() {
     assert_eq!(s, c);
 
     let mut d = t.to_string();
-    d.extend(vec![u].into_iter());
+    d.extend(vec![u]);
     assert_eq!(s, d);
 }
 
@@ -365,6 +366,14 @@ fn test_drain() {
     assert_eq!(t, "");
 }
 
+#[test]
+fn test_extend_ref() {
+    let mut a = "foo".to_string();
+    a.extend(&['b', 'a', 'r']);
+
+    assert_eq!(&a, "foobar");
+}
+
 #[bench]
 fn bench_with_capacity(b: &mut Bencher) {
     b.iter(|| {
@@ -473,7 +482,7 @@ fn bench_from_str(b: &mut Bencher) {
     let s = "Hello there, the quick brown fox jumped over the lazy dog! \
              Lorem ipsum dolor sit amet, consectetur. ";
     b.iter(|| {
-        String::from_str(s)
+        String::from(s)
     })
 }
 
index ac9cf198d6732b53c1488f9432a56576013f561f..df63fbc62fcf4f04169e054e823f7f6bc5e69a20 100644 (file)
@@ -10,6 +10,7 @@
 
 use std::iter::{FromIterator, repeat};
 use std::mem::size_of;
+#[allow(deprecated)]
 use std::vec::as_vec;
 
 use test::Bencher;
@@ -25,12 +26,14 @@ impl<'a> Drop for DropCounter<'a> {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_as_vec() {
     let xs = [1u8, 2u8, 3u8];
     assert_eq!(&**as_vec(&xs), xs);
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_as_vec_dtor() {
     let (mut count_x, mut count_y) = (0, 0);
     {
@@ -112,6 +115,21 @@ fn test_extend() {
     assert_eq!(v, w);
 }
 
+#[test]
+fn test_extend_ref() {
+    let mut v = vec![1, 2];
+    v.extend(&[3, 4, 5]);
+
+    assert_eq!(v.len(), 5);
+    assert_eq!(v, [1, 2, 3, 4, 5]);
+
+    let w = vec![6, 7];
+    v.extend(&w);
+
+    assert_eq!(v.len(), 7);
+    assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
+}
+
 #[test]
 fn test_slice_from_mut() {
     let mut values = vec![1, 2, 3, 4, 5];
@@ -399,7 +417,7 @@ fn test_map_in_place_zero_sized() {
 
 #[test]
 fn test_map_in_place_zero_drop_count() {
-    use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
     #[derive(Clone, PartialEq, Debug)]
     struct Nothing;
@@ -413,7 +431,7 @@ fn test_map_in_place_zero_drop_count() {
         }
     }
     const NUM_ELEMENTS: usize = 2;
-    static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
+    static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
 
     let v = repeat(Nothing).take(NUM_ELEMENTS).collect::<Vec<_>>();
 
@@ -684,7 +702,7 @@ fn do_bench_from_iter(b: &mut Bencher, src_len: usize) {
     b.bytes = src_len as u64;
 
     b.iter(|| {
-        let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter());
+        let dst: Vec<_> = FromIterator::from_iter(src.clone());
         assert_eq!(dst.len(), src_len);
         assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
     });
@@ -718,7 +736,7 @@ fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) {
 
     b.iter(|| {
         let mut dst = dst.clone();
-        dst.extend(src.clone().into_iter());
+        dst.extend(src.clone());
         assert_eq!(dst.len(), dst_len + src_len);
         assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
     });
@@ -816,7 +834,7 @@ fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) {
 
     b.iter(|| {
         let mut dst = dst.clone();
-        dst.extend(src.clone().into_iter());
+        dst.extend(src.clone());
         assert_eq!(dst.len(), dst_len + src_len);
         assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
     });
index 7870447281bc1335fc48b1c9e3c3b255f5488753..95368de3bf3d91bf2630c433204f69a6d08d0896 100644 (file)
@@ -537,8 +537,6 @@ fn test_drain() {
 
 #[test]
 fn test_from_iter() {
-    use std::iter;
-
     let v = vec!(1,2,3,4,5,6,7);
     let deq: VecDeque<_> = v.iter().cloned().collect();
     let u: Vec<_> = deq.iter().cloned().collect();
@@ -894,3 +892,29 @@ fn test_retain() {
     let v: Vec<_> = buf.into_iter().collect();
     assert_eq!(&v[..], &[2, 4]);
 }
+
+#[test]
+fn test_extend_ref() {
+    let mut v = VecDeque::new();
+    v.push_back(1);
+    v.extend(&[2, 3, 4]);
+
+    assert_eq!(v.len(), 4);
+    assert_eq!(v[0], 1);
+    assert_eq!(v[1], 2);
+    assert_eq!(v[2], 3);
+    assert_eq!(v[3], 4);
+
+    let mut w = VecDeque::new();
+    w.push_back(5);
+    w.push_back(6);
+    v.extend(&w);
+
+    assert_eq!(v.len(), 6);
+    assert_eq!(v[0], 1);
+    assert_eq!(v[1], 2);
+    assert_eq!(v[2], 3);
+    assert_eq!(v[3], 4);
+    assert_eq!(v[4], 5);
+    assert_eq!(v[5], 6);
+}
index 112b4c03e20e5c354b335d50e8fab0879c842a23..3ab32323603ca1bd096d9e2e9fdc4115b6187457 100644 (file)
@@ -493,6 +493,22 @@ fn test_entry(){
     assert_eq!(map.len(), 6);
 }
 
+#[test]
+fn test_extend_ref() {
+    let mut a = VecMap::new();
+    a.insert(1, "one");
+    let mut b = VecMap::new();
+    b.insert(2, "two");
+    b.insert(3, "three");
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 3);
+    assert_eq!(a[&1], "one");
+    assert_eq!(a[&2], "two");
+    assert_eq!(a[&3], "three");
+}
+
 mod bench {
     use std::collections::VecMap;
 
index a65394f52682ced3504e38f380fba4906654b166..f0c77ae866d599dcf374caf103c793893baa3c89 100644 (file)
@@ -92,7 +92,7 @@ use marker::{Reflect, Sized};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Any: Reflect + 'static {
     /// Gets the `TypeId` of `self`.
-    #[unstable(feature = "core",
+    #[unstable(feature = "get_type_id",
                reason = "this method will likely be replaced by an associated static")]
     fn get_type_id(&self) -> TypeId;
 }
index 91301ee558ca566315559f663a6948d11519f2ba..a9b240de30befe0175d12aa17d967ce0f2f25107 100644 (file)
 //! up to a certain length. Eventually we should able to generalize
 //! to all lengths.
 
-#![unstable(feature = "core")] // not yet reviewed
-
 #![doc(primitive = "array")]
+#![unstable(feature = "fixed_size_array",
+            reason = "traits and impls are better expressed through generic \
+                      integer constants")]
 
 use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
@@ -30,7 +31,6 @@ use slice::{Iter, IterMut, SliceExt};
 ///
 /// This trait can be used to implement other traits on fixed-size arrays
 /// without causing much metadata bloat.
-#[unstable(feature = "core")]
 pub trait FixedSizeArray<T> {
     /// Converts the array to immutable slice
     fn as_slice(&self) -> &[T];
@@ -42,7 +42,6 @@ pub trait FixedSizeArray<T> {
 macro_rules! array_impls {
     ($($N:expr)+) => {
         $(
-            #[unstable(feature = "core")]
             impl<T> FixedSizeArray<T> for [T; $N] {
                 #[inline]
                 fn as_slice(&self) -> &[T] {
@@ -54,8 +53,6 @@ macro_rules! array_impls {
                 }
             }
 
-            #[unstable(feature = "array_as_ref",
-                       reason = "should ideally be implemented for all fixed-sized arrays")]
             impl<T> AsRef<[T]> for [T; $N] {
                 #[inline]
                 fn as_ref(&self) -> &[T] {
@@ -63,8 +60,6 @@ macro_rules! array_impls {
                 }
             }
 
-            #[unstable(feature = "array_as_ref",
-                       reason = "should ideally be implemented for all fixed-sized arrays")]
             impl<T> AsMut<[T]> for [T; $N] {
                 #[inline]
                 fn as_mut(&mut self) -> &mut [T] {
index ec693f366912dd53ca871e5c305002590fdafc72..1b8ee8db5f47a1ac485fe286f925ab6ac7efe81b 100644 (file)
@@ -76,7 +76,6 @@ use marker::Sync;
 
 use intrinsics;
 use cell::UnsafeCell;
-use marker::PhantomData;
 
 use default::Default;
 
@@ -87,8 +86,8 @@ pub struct AtomicBool {
 }
 
 impl Default for AtomicBool {
-    fn default() -> AtomicBool {
-        ATOMIC_BOOL_INIT
+    fn default() -> Self {
+        Self::new(Default::default())
     }
 }
 
@@ -101,8 +100,8 @@ pub struct AtomicIsize {
 }
 
 impl Default for AtomicIsize {
-    fn default() -> AtomicIsize {
-        ATOMIC_ISIZE_INIT
+    fn default() -> Self {
+        Self::new(Default::default())
     }
 }
 
@@ -115,8 +114,8 @@ pub struct AtomicUsize {
 }
 
 impl Default for AtomicUsize {
-    fn default() -> AtomicUsize {
-        ATOMIC_USIZE_INIT
+    fn default() -> Self {
+        Self::new(Default::default())
     }
 }
 
@@ -125,8 +124,7 @@ unsafe impl Sync for AtomicUsize {}
 /// A raw pointer type which can be safely shared between threads.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct AtomicPtr<T> {
-    p: UnsafeCell<usize>,
-    _marker: PhantomData<*mut T>,
+    p: UnsafeCell<*mut T>,
 }
 
 impl<T> Default for AtomicPtr<T> {
@@ -175,16 +173,13 @@ pub enum Ordering {
 
 /// An `AtomicBool` initialized to `false`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const ATOMIC_BOOL_INIT: AtomicBool =
-        AtomicBool { v: UnsafeCell { value: 0 } };
+pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
 /// An `AtomicIsize` initialized to `0`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const ATOMIC_ISIZE_INIT: AtomicIsize =
-        AtomicIsize { v: UnsafeCell { value: 0 } };
+pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0);
 /// An `AtomicUsize` initialized to `0`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const ATOMIC_USIZE_INIT: AtomicUsize =
-        AtomicUsize { v: UnsafeCell { value: 0, } };
+pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0);
 
 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
 const UINT_TRUE: usize = !0;
@@ -202,9 +197,8 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(v: bool) -> AtomicBool {
-        let val = if v { UINT_TRUE } else { 0 };
-        AtomicBool { v: UnsafeCell::new(val) }
+    pub const fn new(v: bool) -> AtomicBool {
+        AtomicBool { v: UnsafeCell::new(-(v as isize) as usize) }
     }
 
     /// Loads a value from the bool.
@@ -222,7 +216,7 @@ impl AtomicBool {
     ///
     /// let some_bool = AtomicBool::new(true);
     ///
-    /// let value = some_bool.load(Ordering::Relaxed);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -242,6 +236,7 @@ impl AtomicBool {
     /// let some_bool = AtomicBool::new(true);
     ///
     /// some_bool.store(false, Ordering::Relaxed);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
     /// ```
     ///
     /// # Panics
@@ -266,7 +261,8 @@ impl AtomicBool {
     ///
     /// let some_bool = AtomicBool::new(true);
     ///
-    /// let value = some_bool.swap(false, Ordering::Relaxed);
+    /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -291,7 +287,11 @@ impl AtomicBool {
     ///
     /// let some_bool = AtomicBool::new(true);
     ///
-    /// let value = some_bool.store(false, Ordering::Relaxed);
+    /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
+    ///
+    /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -315,16 +315,16 @@ impl AtomicBool {
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_and(false, Ordering::SeqCst));
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_and(true, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     ///
     /// let foo = AtomicBool::new(false);
-    /// assert_eq!(false, foo.fetch_and(false, Ordering::SeqCst));
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -347,17 +347,17 @@ impl AtomicBool {
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_nand(false, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_nand(true, Ordering::SeqCst));
-    /// assert_eq!(0, foo.load(Ordering::SeqCst) as usize);
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     ///
     /// let foo = AtomicBool::new(false);
-    /// assert_eq!(false, foo.fetch_nand(false, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -380,16 +380,16 @@ impl AtomicBool {
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_or(false, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_or(true, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     ///
     /// let foo = AtomicBool::new(false);
-    /// assert_eq!(false, foo.fetch_or(false, Ordering::SeqCst));
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -412,16 +412,16 @@ impl AtomicBool {
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_xor(false, Ordering::SeqCst));
-    /// assert_eq!(true, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), true);
     ///
     /// let foo = AtomicBool::new(true);
-    /// assert_eq!(true, foo.fetch_xor(true, Ordering::SeqCst));
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     ///
     /// let foo = AtomicBool::new(false);
-    /// assert_eq!(false, foo.fetch_xor(false, Ordering::SeqCst));
-    /// assert_eq!(false, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
+    /// assert_eq!(foo.load(Ordering::SeqCst), false);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -445,7 +445,7 @@ impl AtomicIsize {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(v: isize) -> AtomicIsize {
+    pub const fn new(v: isize) -> AtomicIsize {
         AtomicIsize {v: UnsafeCell::new(v)}
     }
 
@@ -464,7 +464,7 @@ impl AtomicIsize {
     ///
     /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_isize.load(Ordering::Relaxed);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -484,6 +484,7 @@ impl AtomicIsize {
     /// let some_isize = AtomicIsize::new(5);
     ///
     /// some_isize.store(10, Ordering::Relaxed);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
     /// ```
     ///
     /// # Panics
@@ -506,7 +507,7 @@ impl AtomicIsize {
     ///
     /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_isize.swap(10, Ordering::Relaxed);
+    /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -529,7 +530,11 @@ impl AtomicIsize {
     ///
     /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_isize.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
+    ///
+    /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -545,8 +550,8 @@ impl AtomicIsize {
     /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
     /// let foo = AtomicIsize::new(0);
-    /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
-    /// assert_eq!(10, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -562,8 +567,8 @@ impl AtomicIsize {
     /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
     /// let foo = AtomicIsize::new(0);
-    /// assert_eq!(0, foo.fetch_sub(10, Ordering::SeqCst));
-    /// assert_eq!(-10, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
+    /// assert_eq!(foo.load(Ordering::SeqCst), -10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -579,8 +584,8 @@ impl AtomicIsize {
     /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
     /// let foo = AtomicIsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_and(&self, val: isize, order: Ordering) -> isize {
@@ -595,8 +600,8 @@ impl AtomicIsize {
     /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
     /// let foo = AtomicIsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_or(&self, val: isize, order: Ordering) -> isize {
@@ -611,8 +616,8 @@ impl AtomicIsize {
     /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
     /// let foo = AtomicIsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
@@ -633,7 +638,7 @@ impl AtomicUsize {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(v: usize) -> AtomicUsize {
+    pub const fn new(v: usize) -> AtomicUsize {
         AtomicUsize { v: UnsafeCell::new(v) }
     }
 
@@ -652,7 +657,7 @@ impl AtomicUsize {
     ///
     /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_usize.load(Ordering::Relaxed);
+    /// assert_eq!(some_usize.load(Ordering::Relaxed), 5);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -672,6 +677,7 @@ impl AtomicUsize {
     /// let some_usize = AtomicUsize::new(5);
     ///
     /// some_usize.store(10, Ordering::Relaxed);
+    /// assert_eq!(some_usize.load(Ordering::Relaxed), 10);
     /// ```
     ///
     /// # Panics
@@ -694,7 +700,8 @@ impl AtomicUsize {
     ///
     /// let some_usize= AtomicUsize::new(5);
     ///
-    /// let value = some_usize.swap(10, Ordering::Relaxed);
+    /// assert_eq!(some_usize.swap(10, Ordering::Relaxed), 5);
+    /// assert_eq!(some_usize.load(Ordering::Relaxed), 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -717,7 +724,11 @@ impl AtomicUsize {
     ///
     /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_usize.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// assert_eq!(some_usize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+    /// assert_eq!(some_usize.load(Ordering::Relaxed), 10);
+    ///
+    /// assert_eq!(some_usize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+    /// assert_eq!(some_usize.load(Ordering::Relaxed), 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -733,8 +744,8 @@ impl AtomicUsize {
     /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
     /// let foo = AtomicUsize::new(0);
-    /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
-    /// assert_eq!(10, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -750,8 +761,8 @@ impl AtomicUsize {
     /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
     /// let foo = AtomicUsize::new(10);
-    /// assert_eq!(10, foo.fetch_sub(10, Ordering::SeqCst));
-    /// assert_eq!(0, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 10);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -767,8 +778,8 @@ impl AtomicUsize {
     /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
     /// let foo = AtomicUsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_and(&self, val: usize, order: Ordering) -> usize {
@@ -783,8 +794,8 @@ impl AtomicUsize {
     /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
     /// let foo = AtomicUsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_or(&self, val: usize, order: Ordering) -> usize {
@@ -799,8 +810,8 @@ impl AtomicUsize {
     /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
     /// let foo = AtomicUsize::new(0b101101);
-    /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
-    /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
+    /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+    /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
@@ -821,9 +832,8 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(p: *mut T) -> AtomicPtr<T> {
-        AtomicPtr { p: UnsafeCell::new(p as usize),
-                    _marker: PhantomData }
+    pub const fn new(p: *mut T) -> AtomicPtr<T> {
+        AtomicPtr { p: UnsafeCell::new(p) }
     }
 
     /// Loads a value from the pointer.
@@ -848,7 +858,7 @@ impl<T> AtomicPtr<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> *mut T {
         unsafe {
-            atomic_load(self.p.get(), order) as *mut T
+            atomic_load(self.p.get() as *mut usize, order) as *mut T
         }
     }
 
@@ -875,7 +885,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
-        unsafe { atomic_store(self.p.get(), ptr as usize, order); }
+        unsafe { atomic_store(self.p.get() as *mut usize, ptr as usize, order); }
     }
 
     /// Stores a value into the pointer, returning the old value.
@@ -897,7 +907,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
-        unsafe { atomic_swap(self.p.get(), ptr as usize, order) as *mut T }
+        unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
 
     /// Stores a value into the pointer if the current value is the same as the expected value.
@@ -925,7 +935,7 @@ impl<T> AtomicPtr<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
         unsafe {
-            atomic_compare_and_swap(self.p.get(), old as usize,
+            atomic_compare_and_swap(self.p.get() as *mut usize, old as usize,
                                     new as usize, order) as *mut T
         }
     }
index 45a8012210417842edf6adb231defb94ebcb4410..37f37654c1fee8f903598fc8a5a410167c8b432c 100644 (file)
@@ -38,7 +38,7 @@
 //!
 //! * Introducing inherited mutability roots to shared types.
 //! * Implementation details of logically-immutable methods.
-//! * Mutating implementations of `clone`.
+//! * Mutating implementations of `Clone`.
 //!
 //! ## Introducing inherited mutability roots to shared types
 //!
 //! }
 //! ```
 //!
-//! ## Mutating implementations of `clone`
+//! ## Mutating implementations of `Clone`
 //!
 //! This is simply a special - but common - case of the previous: hiding mutability for operations
 //! that appear to be immutable. The `clone` method is expected to not change the source value, and
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use clone::Clone;
-use cmp::PartialEq;
+use cmp::{PartialEq, Eq};
 use default::Default;
 use marker::{Copy, Send, Sync, Sized};
-use ops::{Deref, DerefMut, Drop};
+use ops::{Deref, DerefMut, Drop, FnOnce};
 use option::Option;
 use option::Option::{None, Some};
 
@@ -170,7 +170,7 @@ impl<T:Copy> Cell<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn new(value: T) -> Cell<T> {
+    pub const fn new(value: T) -> Cell<T> {
         Cell {
             value: UnsafeCell::new(value),
         }
@@ -212,7 +212,7 @@ impl<T:Copy> Cell<T> {
         }
     }
 
-    /// Gets a reference to the underlying `UnsafeCell`.
+    /// Returns a reference to the underlying `UnsafeCell`.
     ///
     /// # Unsafety
     ///
@@ -221,7 +221,7 @@ impl<T:Copy> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
+    /// # #![feature(as_unsafe_cell)]
     /// use std::cell::Cell;
     ///
     /// let c = Cell::new(5);
@@ -229,7 +229,7 @@ impl<T:Copy> Cell<T> {
     /// let uc = unsafe { c.as_unsafe_cell() };
     /// ```
     #[inline]
-    #[unstable(feature = "core")]
+    #[unstable(feature = "as_unsafe_cell")]
     pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
         &self.value
     }
@@ -263,6 +263,9 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
     }
 }
 
+#[stable(feature = "cell_eq", since = "1.2.0")]
+impl<T:Eq + Copy> Eq for Cell<T> {}
+
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](index.html) for more.
@@ -273,8 +276,8 @@ pub struct RefCell<T: ?Sized> {
 }
 
 /// An enumeration of values returned from the `state` method on a `RefCell<T>`.
-#[derive(Copy, Clone, PartialEq, Debug)]
-#[unstable(feature = "std_misc")]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[unstable(feature = "borrow_state")]
 pub enum BorrowState {
     /// The cell is currently being read, there is at least one active `borrow`.
     Reading,
@@ -302,7 +305,7 @@ impl<T> RefCell<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn new(value: T) -> RefCell<T> {
+    pub const fn new(value: T) -> RefCell<T> {
         RefCell {
             value: UnsafeCell::new(value),
             borrow: Cell::new(UNUSED),
@@ -336,7 +339,7 @@ impl<T: ?Sized> RefCell<T> {
     ///
     /// The returned value can be dispatched on to determine if a call to
     /// `borrow` or `borrow_mut` would succeed.
-    #[unstable(feature = "std_misc")]
+    #[unstable(feature = "borrow_state")]
     #[inline]
     pub fn borrow_state(&self) -> BorrowState {
         match self.borrow.get() {
@@ -439,13 +442,13 @@ impl<T: ?Sized> RefCell<T> {
         }
     }
 
-    /// Gets a reference to the underlying `UnsafeCell`.
+    /// Returns a reference to the underlying `UnsafeCell`.
     ///
     /// This can be used to circumvent `RefCell`'s safety checks.
     ///
     /// This function is `unsafe` because `UnsafeCell`'s field is public.
     #[inline]
-    #[unstable(feature = "core")]
+    #[unstable(feature = "as_unsafe_cell")]
     pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
         &self.value
     }
@@ -479,6 +482,9 @@ impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
     }
 }
 
+#[stable(feature = "cell_eq", since = "1.2.0")]
+impl<T: ?Sized + Eq> Eq for RefCell<T> {}
+
 struct BorrowRef<'b> {
     _borrow: &'b Cell<BorrowFlag>,
 }
@@ -545,13 +551,167 @@ impl<'b, T: ?Sized> Deref for Ref<'b, T> {
 ///
 /// A `Clone` implementation would interfere with the widespread
 /// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
+#[deprecated(since = "1.2.0", reason = "moved to a `Ref::clone` associated function")]
 #[unstable(feature = "core",
            reason = "likely to be moved to a method, pending language changes")]
 #[inline]
 pub fn clone_ref<'b, T:Clone>(orig: &Ref<'b, T>) -> Ref<'b, T> {
-    Ref {
-        _value: orig._value,
-        _borrow: orig._borrow.clone(),
+    Ref::clone(orig)
+}
+
+impl<'b, T: ?Sized> Ref<'b, T> {
+    /// Copies a `Ref`.
+    ///
+    /// The `RefCell` is already immutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `Ref::clone(...)`.  A `Clone` implementation or a method would interfere
+    /// with the widespread use of `r.borrow().clone()` to clone the contents of
+    /// a `RefCell`.
+    #[unstable(feature = "cell_extras",
+               reason = "likely to be moved to a method, pending language changes")]
+    #[inline]
+    pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
+        Ref {
+            _value: orig._value,
+            _borrow: orig._borrow.clone(),
+        }
+    }
+
+    /// Make a new `Ref` for a component of the borrowed data.
+    ///
+    /// The `RefCell` is already immutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as `Ref::map(...)`.
+    /// A method would interfere with methods of the same name on the contents
+    /// of a `RefCell` used through `Deref`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # #![feature(cell_extras)]
+    /// use std::cell::{RefCell, Ref};
+    ///
+    /// let c = RefCell::new((5, 'b'));
+    /// let b1: Ref<(u32, char)> = c.borrow();
+    /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0);
+    /// assert_eq!(*b2, 5)
+    /// ```
+    #[unstable(feature = "cell_extras", reason = "recently added")]
+    #[inline]
+    pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
+        where F: FnOnce(&T) -> &U
+    {
+        Ref {
+            _value: f(orig._value),
+            _borrow: orig._borrow,
+        }
+    }
+
+    /// Make a new `Ref` for a optional component of the borrowed data, e.g. an
+    /// enum variant.
+    ///
+    /// The `RefCell` is already immutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `Ref::filter_map(...)`.  A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # #![feature(cell_extras)]
+    /// use std::cell::{RefCell, Ref};
+    ///
+    /// let c = RefCell::new(Ok(5));
+    /// let b1: Ref<Result<u32, ()>> = c.borrow();
+    /// let b2: Ref<u32> = Ref::filter_map(b1, |o| o.as_ref().ok()).unwrap();
+    /// assert_eq!(*b2, 5)
+    /// ```
+    #[unstable(feature = "cell_extras", reason = "recently added")]
+    #[inline]
+    pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>>
+        where F: FnOnce(&T) -> Option<&U>
+    {
+        f(orig._value).map(move |new| Ref {
+            _value: new,
+            _borrow: orig._borrow,
+        })
+    }
+}
+
+impl<'b, T: ?Sized> RefMut<'b, T> {
+    /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum
+    /// variant.
+    ///
+    /// The `RefCell` is already mutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `RefMut::map(...)`.  A method would interfere with methods of the same
+    /// name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # #![feature(cell_extras)]
+    /// use std::cell::{RefCell, RefMut};
+    ///
+    /// let c = RefCell::new((5, 'b'));
+    /// {
+    ///     let b1: RefMut<(u32, char)> = c.borrow_mut();
+    ///     let mut b2: RefMut<u32> = RefMut::map(b1, |t| &mut t.0);
+    ///     assert_eq!(*b2, 5);
+    ///     *b2 = 42;
+    /// }
+    /// assert_eq!(*c.borrow(), (42, 'b'));
+    /// ```
+    #[unstable(feature = "cell_extras", reason = "recently added")]
+    #[inline]
+    pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
+        where F: FnOnce(&mut T) -> &mut U
+    {
+        RefMut {
+            _value: f(orig._value),
+            _borrow: orig._borrow,
+        }
+    }
+
+    /// Make a new `RefMut` for a optional component of the borrowed data, e.g.
+    /// an enum variant.
+    ///
+    /// The `RefCell` is already mutably borrowed, so this cannot fail.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `RefMut::filter_map(...)`.  A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # #![feature(cell_extras)]
+    /// use std::cell::{RefCell, RefMut};
+    ///
+    /// let c = RefCell::new(Ok(5));
+    /// {
+    ///     let b1: RefMut<Result<u32, ()>> = c.borrow_mut();
+    ///     let mut b2: RefMut<u32> = RefMut::filter_map(b1, |o| {
+    ///         o.as_mut().ok()
+    ///     }).unwrap();
+    ///     assert_eq!(*b2, 5);
+    ///     *b2 = 42;
+    /// }
+    /// assert_eq!(*c.borrow(), Ok(42));
+    /// ```
+    #[unstable(feature = "cell_extras", reason = "recently added")]
+    #[inline]
+    pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>>
+        where F: FnOnce(&mut T) -> Option<&mut U>
+    {
+        let RefMut { _value, _borrow } = orig;
+        f(_value).map(move |new| RefMut {
+            _value: new,
+            _borrow: _borrow,
+        })
     }
 }
 
@@ -641,6 +801,8 @@ pub struct UnsafeCell<T: ?Sized> {
     ///
     /// This field should not be accessed directly, it is made public for static
     /// initializers.
+    #[deprecated(since = "1.2.0", reason = "use `get` to access the wrapped \
+        value or `new` to initialize `UnsafeCell` in statics")]
     #[unstable(feature = "core")]
     pub value: T,
 }
@@ -663,7 +825,8 @@ impl<T> UnsafeCell<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn new(value: T) -> UnsafeCell<T> {
+    pub const fn new(value: T) -> UnsafeCell<T> {
+        #![allow(deprecated)]
         UnsafeCell { value: value }
     }
 
@@ -671,8 +834,8 @@ impl<T> UnsafeCell<T> {
     ///
     /// # Unsafety
     ///
-    /// This function is unsafe because there is no guarantee that this or other threads are
-    /// currently inspecting the inner value.
+    /// This function is unsafe because this thread or another thread may currently be
+    /// inspecting the inner value.
     ///
     /// # Examples
     ///
@@ -685,7 +848,10 @@ impl<T> UnsafeCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub unsafe fn into_inner(self) -> T { self.value }
+    pub unsafe fn into_inner(self) -> T {
+        #![allow(deprecated)]
+        self.value
+    }
 }
 
 impl<T: ?Sized> UnsafeCell<T> {
@@ -705,6 +871,7 @@ impl<T: ?Sized> UnsafeCell<T> {
     pub fn get(&self) -> *mut T {
         // FIXME(#23542) Replace with type ascription.
         #![allow(trivial_casts)]
+        #![allow(deprecated)]
         &self.value as *const T as *mut T
     }
 }
index 48d9869f72ae4c70d7c2acc6e5139e8ba85fcc0c..12aa06667a1dd3fb740203cebdaad306e0867bd5 100644 (file)
@@ -14,6 +14,7 @@
 
 #![allow(non_snake_case)]
 #![doc(primitive = "char")]
+#![stable(feature = "core_char", since = "1.2.0")]
 
 use iter::Iterator;
 use mem::transmute;
@@ -74,17 +75,8 @@ pub const MAX: char = '\u{10ffff}';
 /// ```
 /// use std::char;
 ///
-/// let c = char::from_u32(10084); // produces `Some(❤)`
-/// assert_eq!(c, Some('❤'));
-/// ```
-///
-/// An invalid character:
-///
-/// ```
-/// use std::char;
-///
-/// let none = char::from_u32(1114112);
-/// assert_eq!(none, None);
+/// assert_eq!(char::from_u32(0x2764), Some('❤'));
+/// assert_eq!(char::from_u32(0x110000), None); // invalid character
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -140,6 +132,8 @@ pub fn from_digit(num: u32, radix: u32) -> Option<char> {
 // unicode/char.rs, not here
 #[allow(missing_docs)] // docs in libunicode/u_char.rs
 #[doc(hidden)]
+#[unstable(feature = "core_char_ext",
+           reason = "the stable interface is `impl char` in later crate")]
 pub trait CharExt {
     fn is_digit(self, radix: u32) -> bool;
     fn to_digit(self, radix: u32) -> Option<u32>;
@@ -152,10 +146,12 @@ pub trait CharExt {
 }
 
 impl CharExt for char {
+    #[inline]
     fn is_digit(self, radix: u32) -> bool {
         self.to_digit(radix).is_some()
     }
 
+    #[inline]
     fn to_digit(self, radix: u32) -> Option<u32> {
         if radix > 36 {
             panic!("to_digit: radix is too high (maximum 36)");
@@ -170,10 +166,12 @@ impl CharExt for char {
         else { None }
     }
 
+    #[inline]
     fn escape_unicode(self) -> EscapeUnicode {
         EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
     }
 
+    #[inline]
     fn escape_default(self) -> EscapeDefault {
         let init_state = match self {
             '\t' => EscapeDefaultState::Backslash('t'),
@@ -225,6 +223,9 @@ impl CharExt for char {
 /// If the buffer is not large enough, nothing will be written into it
 /// and a `None` will be returned.
 #[inline]
+#[unstable(feature = "char_internals",
+           reason = "this function should not be exposed publicly")]
+#[doc(hidden)]
 pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<usize> {
     // Marked #[inline] to allow llvm optimizing it away
     if code < MAX_ONE_B && !dst.is_empty() {
@@ -256,6 +257,9 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<usize> {
 /// If the buffer is not large enough, nothing will be written into it
 /// and a `None` will be returned.
 #[inline]
+#[unstable(feature = "char_internals",
+           reason = "this function should not be exposed publicly")]
+#[doc(hidden)]
 pub fn encode_utf16_raw(mut ch: u32, dst: &mut [u16]) -> Option<usize> {
     // Marked #[inline] to allow llvm optimizing it away
     if (ch & 0xFFFF) == ch && !dst.is_empty() {
index f11c01507dcd8aa22950cd7311c4e8abe552dc3f..a13160b3a19ee48d93582d57e548aef1f3411583 100644 (file)
@@ -89,29 +89,28 @@ clone_impl! { char }
 
 macro_rules! extern_fn_clone {
     ($($A:ident),*) => (
-        #[unstable(feature = "core",
-                   reason = "this may not be sufficient for fns with region parameters")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
             /// Returns a copy of a function pointer.
             #[inline]
             fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
         }
 
-        #[unstable(feature = "core", reason = "brand new")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<$($A,)* ReturnType> Clone for extern "C" fn($($A),*) -> ReturnType {
             /// Returns a copy of a function pointer.
             #[inline]
             fn clone(&self) -> extern "C" fn($($A),*) -> ReturnType { *self }
         }
 
-        #[unstable(feature = "core", reason = "brand new")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<$($A,)* ReturnType> Clone for unsafe extern "Rust" fn($($A),*) -> ReturnType {
             /// Returns a copy of a function pointer.
             #[inline]
             fn clone(&self) -> unsafe extern "Rust" fn($($A),*) -> ReturnType { *self }
         }
 
-        #[unstable(feature = "core", reason = "brand new")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<$($A,)* ReturnType> Clone for unsafe extern "C" fn($($A),*) -> ReturnType {
             /// Returns a copy of a function pointer.
             #[inline]
index dab549f784cf82bf68a175fa0d67b7423729b8c8..0269499ad5414ffd681b673d21dc1c515f1e004d 100644 (file)
 
 //! Functionality for ordering and comparison.
 //!
-//! This module defines both `PartialOrd` and `PartialEq` traits which are used by the compiler to
-//! implement comparison operators. Rust programs may implement `PartialOrd` to overload the `<`,
-//! `<=`, `>`, and `>=` operators, and may implement `PartialEq` to overload the `==` and `!=`
-//! operators.
+//! This module defines both `PartialOrd` and `PartialEq` traits which are used
+//! by the compiler to implement comparison operators. Rust programs may
+//! implement `PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators,
+//! and may implement `PartialEq` to overload the `==` and `!=` operators.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -22,29 +22,31 @@ use self::Ordering::*;
 use marker::Sized;
 use option::Option::{self, Some, None};
 
-/// Trait for equality comparisons which are [partial equivalence relations](
-/// http://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// Trait for equality comparisons which are [partial equivalence
+/// relations](http://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
-/// This trait allows for partial equality, for types that do not have a full equivalence relation.
-/// For example, in floating point numbers `NaN != NaN`, so floating point types implement
-/// `PartialEq` but not `Eq`.
+/// This trait allows for partial equality, for types that do not have a full
+/// equivalence relation.  For example, in floating point numbers `NaN != NaN`,
+/// so floating point types implement `PartialEq` but not `Eq`.
 ///
 /// Formally, the equality must be (for all `a`, `b` and `c`):
 ///
 /// - symmetric: `a == b` implies `b == a`; and
 /// - transitive: `a == b` and `b == c` implies `a == c`.
 ///
-/// Note that these requirements mean that the trait itself must be implemented symmetrically and
-/// transitively: if `T: PartialEq<U>` and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
-/// PartialEq<V>`.
+/// Note that these requirements mean that the trait itself must be implemented
+/// symmetrically and transitively: if `T: PartialEq<U>` and `U: PartialEq<V>`
+/// then `U: PartialEq<T>` and `T: PartialEq<V>`.
 ///
-/// PartialEq only requires the `eq` method to be implemented; `ne` is defined in terms of it by
-/// default. Any manual implementation of `ne` *must* respect the rule that `eq` is a strict
-/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
+/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
+/// in terms of it by default. Any manual implementation of `ne` *must* respect
+/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
+/// only if `a != b`.
 #[lang = "eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait PartialEq<Rhs: ?Sized = Self> {
-    /// This method tests for `self` and `other` values to be equal, and is used by `==`.
+    /// This method tests for `self` and `other` values to be equal, and is used
+    /// by `==`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq(&self, other: &Rhs) -> bool;
 
@@ -379,7 +381,7 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
 /// # Examples
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(cmp_partial)]
 /// use std::cmp;
 ///
 /// assert_eq!(Some(1), cmp::partial_min(1, 2));
@@ -389,14 +391,14 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
 /// When comparison is impossible:
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(cmp_partial)]
 /// use std::cmp;
 ///
 /// let result = cmp::partial_min(std::f64::NAN, 1.0);
 /// assert_eq!(result, None);
 /// ```
 #[inline]
-#[unstable(feature = "core")]
+#[unstable(feature = "cmp_partial")]
 pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
     match v1.partial_cmp(&v2) {
         Some(Less) | Some(Equal) => Some(v1),
@@ -412,7 +414,7 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
 /// # Examples
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(cmp_partial)]
 /// use std::cmp;
 ///
 /// assert_eq!(Some(2), cmp::partial_max(1, 2));
@@ -422,14 +424,14 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
 /// When comparison is impossible:
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(cmp_partial)]
 /// use std::cmp;
 ///
 /// let result = cmp::partial_max(std::f64::NAN, 1.0);
 /// assert_eq!(result, None);
 /// ```
 #[inline]
-#[unstable(feature = "core")]
+#[unstable(feature = "cmp_partial")]
 pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
     match v1.partial_cmp(&v2) {
         Some(Equal) | Some(Less) => Some(v2),
index f6987c1966493843c25c768fad1a9d5aaf8f1f7e..70868805299f3a910a7a5858f33a508606acb1cb 100644 (file)
 
 //! Traits for conversions between types.
 //!
-//! The traits in this module provide a general way to talk about conversions from one type to
-//! another. They follow the standard Rust conventions of `as`/`into`/`from`.
+//! The traits in this module provide a general way to talk about conversions
+//! from one type to another. They follow the standard Rust conventions of
+//! `as`/`into`/`from`.
 //!
-//! Like many traits, these are often used as bounds for generic functions, to support arguments of
-//! multiple types.
+//! Like many traits, these are often used as bounds for generic functions, to
+//! support arguments of multiple types.
 //!
 //! See each trait for usage examples.
 
index f61a7f2d30c62cd418b949bd0b301b2ee13a06d3..32d6aa19c64566e90212673866f8a25d573e23e8 100644 (file)
@@ -54,6 +54,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
 ///
 /// Constructed by the `Formatter::debug_struct` method.
 #[must_use]
+#[stable(feature = "debug_builders", since = "1.2.0")]
 pub struct DebugStruct<'a, 'b: 'a> {
     fmt: &'a mut fmt::Formatter<'b>,
     result: fmt::Result,
@@ -72,8 +73,8 @@ pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str)
 
 impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     /// Adds a new field to the generated struct output.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn field(mut self, name: &str, value: &fmt::Debug) -> DebugStruct<'a, 'b> {
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn field(&mut self, name: &str, value: &fmt::Debug) -> &mut DebugStruct<'a, 'b> {
         self.result = self.result.and_then(|_| {
             let prefix = if self.has_fields {
                 ","
@@ -93,10 +94,9 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
         self
     }
 
-    /// Consumes the `DebugStruct`, finishing output and returning any error
-    /// encountered.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn finish(mut self) -> fmt::Result {
+    /// Finishes output and returns any error encountered.
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn finish(&mut self) -> fmt::Result {
         if self.has_fields {
             self.result = self.result.and_then(|_| {
                 if self.is_pretty() {
@@ -118,6 +118,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
 ///
 /// Constructed by the `Formatter::debug_tuple` method.
 #[must_use]
+#[stable(feature = "debug_builders", since = "1.2.0")]
 pub struct DebugTuple<'a, 'b: 'a> {
     fmt: &'a mut fmt::Formatter<'b>,
     result: fmt::Result,
@@ -135,8 +136,8 @@ pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> D
 
 impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     /// Adds a new field to the generated tuple struct output.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn field(mut self, value: &fmt::Debug) -> DebugTuple<'a, 'b> {
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn field(&mut self, value: &fmt::Debug) -> &mut DebugTuple<'a, 'b> {
         self.result = self.result.and_then(|_| {
             let (prefix, space) = if self.has_fields {
                 (",", " ")
@@ -156,10 +157,9 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
         self
     }
 
-    /// Consumes the `DebugTuple`, finishing output and returning any error
-    /// encountered.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn finish(mut self) -> fmt::Result {
+    /// Finishes output and returns any error encountered.
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn finish(&mut self) -> fmt::Result {
         if self.has_fields {
             self.result = self.result.and_then(|_| {
                 if self.is_pretty() {
@@ -213,6 +213,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
 ///
 /// Constructed by the `Formatter::debug_set` method.
 #[must_use]
+#[stable(feature = "debug_builders", since = "1.2.0")]
 pub struct DebugSet<'a, 'b: 'a> {
     inner: DebugInner<'a, 'b>,
 }
@@ -230,16 +231,25 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b
 
 impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     /// Adds a new entry to the set output.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn entry(mut self, entry: &fmt::Debug) -> DebugSet<'a, 'b> {
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugSet<'a, 'b> {
         self.inner.entry(entry);
         self
     }
 
-    /// Consumes the `DebugSet`, finishing output and returning any error
-    /// encountered.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn finish(mut self) -> fmt::Result {
+    /// 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> {
+        for entry in entries {
+            self.entry(&entry);
+        }
+        self
+    }
+
+    /// Finishes output and returns any error encountered.
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn finish(&mut self) -> fmt::Result {
         self.inner.finish();
         self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
     }
@@ -249,6 +259,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
 ///
 /// Constructed by the `Formatter::debug_list` method.
 #[must_use]
+#[stable(feature = "debug_builders", since = "1.2.0")]
 pub struct DebugList<'a, 'b: 'a> {
     inner: DebugInner<'a, 'b>,
 }
@@ -265,17 +276,26 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a,
 }
 
 impl<'a, 'b: 'a> DebugList<'a, 'b> {
-    /// Adds a new entry to the set output.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn entry(mut self, entry: &fmt::Debug) -> DebugList<'a, 'b> {
+    /// Adds a new entry to the list output.
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugList<'a, 'b> {
         self.inner.entry(entry);
         self
     }
 
-    /// Consumes the `DebugSet`, finishing output and returning any error
-    /// encountered.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn finish(mut self) -> fmt::Result {
+    /// 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> {
+        for entry in entries {
+            self.entry(&entry);
+        }
+        self
+    }
+
+    /// Finishes output and returns any error encountered.
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn finish(&mut self) -> fmt::Result {
         self.inner.finish();
         self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
     }
@@ -285,6 +305,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
 ///
 /// Constructed by the `Formatter::debug_map` method.
 #[must_use]
+#[stable(feature = "debug_builders", since = "1.2.0")]
 pub struct DebugMap<'a, 'b: 'a> {
     fmt: &'a mut fmt::Formatter<'b>,
     result: fmt::Result,
@@ -302,8 +323,8 @@ pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b
 
 impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     /// Adds a new entry to the map output.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn entry(mut self, key: &fmt::Debug, value: &fmt::Debug) -> DebugMap<'a, 'b> {
+    #[stable(feature = "debug_builders", since = "1.2.0")]
+    pub fn entry(&mut self, key: &fmt::Debug, value: &fmt::Debug) -> &mut DebugMap<'a, 'b> {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
                 let mut writer = PadAdapter::new(self.fmt);
@@ -319,10 +340,19 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
         self
     }
 
-    /// Consumes the `DebugMap`, finishing output and returning any error
-    /// encountered.
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
-    pub fn finish(self) -> fmt::Result {
+    /// 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)> {
+        for (k, v) in entries {
+            self.entry(&k, &v);
+        }
+        self
+    }
+
+    /// 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 { "" };
         self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
     }
index a87f6619fe8772e7e36127d9b06f705856e0e8ac..343772c764f817b242c7856dd8b025c35cc2c949 100644 (file)
@@ -33,7 +33,7 @@ pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}
 mod num;
 mod builders;
 
-#[unstable(feature = "core", reason = "internal to format_args!")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
 #[doc(hidden)]
 pub mod rt {
     pub mod v1;
@@ -72,7 +72,7 @@ pub trait Write {
     ///
     /// # Errors
     ///
-    /// This function will return an instance of `FormatError` on error.
+    /// This function will return an instance of `Error` on error.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write_str(&mut self, s: &str) -> Result;
 
@@ -85,7 +85,7 @@ pub trait Write {
     ///
     /// # Errors
     ///
-    /// This function will return an instance of `FormatError` on error.
+    /// This function will return an instance of `Error` on error.
     #[stable(feature = "fmt_write_char", since = "1.1.0")]
     fn write_char(&mut self, c: char) -> Result {
         let mut utf_8 = [0u8; 4];
@@ -146,7 +146,7 @@ enum Void {}
 /// compile time it is ensured that the function and the value have the correct
 /// types, and then this struct is used to canonicalize arguments to one type.
 #[derive(Copy)]
-#[unstable(feature = "core", reason = "internal to format_args!")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
 #[doc(hidden)]
 pub struct ArgumentV1<'a> {
     value: &'a Void,
@@ -166,7 +166,7 @@ impl<'a> ArgumentV1<'a> {
     }
 
     #[doc(hidden)]
-    #[unstable(feature = "core", reason = "internal to format_args!")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
     pub fn new<'b, T>(x: &'b T,
                       f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> {
         unsafe {
@@ -178,7 +178,7 @@ impl<'a> ArgumentV1<'a> {
     }
 
     #[doc(hidden)]
-    #[unstable(feature = "core", reason = "internal to format_args!")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
     pub fn from_usize(x: &usize) -> ArgumentV1 {
         ArgumentV1::new(x, ArgumentV1::show_usize)
     }
@@ -201,7 +201,7 @@ impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
     #[doc(hidden)] #[inline]
-    #[unstable(feature = "core", reason = "internal to format_args!")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
     pub fn new_v1(pieces: &'a [&'a str],
                   args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
         Arguments {
@@ -218,7 +218,7 @@ impl<'a> Arguments<'a> {
     /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
-    #[unstable(feature = "core", reason = "internal to format_args!")]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!")]
     pub fn new_v1_formatted(pieces: &'a [&'a str],
                             args: &'a [ArgumentV1<'a>],
                             fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {
@@ -269,6 +269,50 @@ impl<'a> Display for Arguments<'a> {
 
 /// Format trait for the `:?` format. Useful for debugging, all types
 /// should implement this.
+///
+/// Generally speaking, you should just `derive` a `Debug` implementation.
+///
+/// # Examples
+///
+/// Deriving an implementation:
+///
+/// ```
+/// #[derive(Debug)]
+/// struct Point {
+///     x: i32,
+///     y: i32,
+/// }
+///
+/// let origin = Point { x: 0, y: 0 };
+///
+/// println!("The origin is: {:?}", origin);
+/// ```
+///
+/// Manually implementing:
+///
+/// ```
+/// use std::fmt;
+///
+/// struct Point {
+///     x: i32,
+///     y: i32,
+/// }
+///
+/// impl fmt::Debug for Point {
+///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+///         write!(f, "({}, {})", self.x, self.y)
+///     }
+/// }
+///
+/// let origin = Point { x: 0, y: 0 };
+///
+/// println!("The origin is: {:?}", origin);
+/// ```
+///
+/// There are a number of `debug_*` methods on `Formatter` to help you with manual
+/// implementations, such as [`debug_struct`][debug_struct].
+///
+/// [debug_struct]: ../std/fmt/struct.Formatter.html#method.debug_struct
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \
                             defined in your crate, add `#[derive(Debug)]` or \
@@ -698,19 +742,19 @@ impl<'a> Formatter<'a> {
     pub fn flags(&self) -> u32 { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
-    #[unstable(feature = "core", reason = "method was just created")]
+    #[unstable(feature = "fmt_flags", reason = "method was just created")]
     pub fn fill(&self) -> char { self.fill }
 
     /// Flag indicating what form of alignment was requested
-    #[unstable(feature = "core", reason = "method was just created")]
+    #[unstable(feature = "fmt_flags", reason = "method was just created")]
     pub fn align(&self) -> Alignment { self.align }
 
     /// Optionally specified integer width that the output should be
-    #[unstable(feature = "core", reason = "method was just created")]
+    #[unstable(feature = "fmt_flags", reason = "method was just created")]
     pub fn width(&self) -> Option<usize> { self.width }
 
     /// Optionally specified precision for numeric types
-    #[unstable(feature = "core", reason = "method was just created")]
+    #[unstable(feature = "fmt_flags", reason = "method was just created")]
     pub fn precision(&self) -> Option<usize> { self.precision }
 
     /// Creates a `DebugStruct` builder designed to assist with creation of
@@ -719,7 +763,6 @@ impl<'a> Formatter<'a> {
     /// # Examples
     ///
     /// ```rust
-    /// # #![feature(debug_builders, core)]
     /// use std::fmt;
     ///
     /// struct Foo {
@@ -739,7 +782,7 @@ impl<'a> Formatter<'a> {
     /// // prints "Foo { bar: 10, baz: "Hello World" }"
     /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
     /// ```
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
+    #[stable(feature = "debug_builders", since = "1.2.0")]
     #[inline]
     pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {
         builders::debug_struct_new(self, name)
@@ -751,7 +794,6 @@ impl<'a> Formatter<'a> {
     /// # Examples
     ///
     /// ```rust
-    /// # #![feature(debug_builders, core)]
     /// use std::fmt;
     ///
     /// struct Foo(i32, String);
@@ -768,7 +810,7 @@ impl<'a> Formatter<'a> {
     /// // prints "Foo(10, "Hello World")"
     /// println!("{:?}", Foo(10, "Hello World".to_string()));
     /// ```
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
+    #[stable(feature = "debug_builders", since = "1.2.0")]
     #[inline]
     pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {
         builders::debug_tuple_new(self, name)
@@ -780,21 +822,20 @@ impl<'a> Formatter<'a> {
     /// # Examples
     ///
     /// ```rust
-    /// # #![feature(debug_builders, core)]
     /// use std::fmt;
     ///
     /// struct Foo(Vec<i32>);
     ///
     /// impl fmt::Debug for Foo {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-    ///         self.0.iter().fold(fmt.debug_list(), |b, e| b.entry(e)).finish()
+    ///         fmt.debug_list().entries(self.0.iter()).finish()
     ///     }
     /// }
     ///
     /// // prints "[10, 11]"
     /// println!("{:?}", Foo(vec![10, 11]));
     /// ```
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
+    #[stable(feature = "debug_builders", since = "1.2.0")]
     #[inline]
     pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> {
         builders::debug_list_new(self)
@@ -806,21 +847,20 @@ impl<'a> Formatter<'a> {
     /// # Examples
     ///
     /// ```rust
-    /// # #![feature(debug_builders, core)]
     /// use std::fmt;
     ///
     /// struct Foo(Vec<i32>);
     ///
     /// impl fmt::Debug for Foo {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-    ///         self.0.iter().fold(fmt.debug_set(), |b, e| b.entry(e)).finish()
+    ///         fmt.debug_set().entries(self.0.iter()).finish()
     ///     }
     /// }
     ///
     /// // prints "{10, 11}"
     /// println!("{:?}", Foo(vec![10, 11]));
     /// ```
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
+    #[stable(feature = "debug_builders", since = "1.2.0")]
     #[inline]
     pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> {
         builders::debug_set_new(self)
@@ -832,27 +872,41 @@ impl<'a> Formatter<'a> {
     /// # Examples
     ///
     /// ```rust
-    /// # #![feature(debug_builders, core)]
     /// use std::fmt;
     ///
     /// struct Foo(Vec<(String, i32)>);
     ///
     /// impl fmt::Debug for Foo {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-    ///         self.0.iter().fold(fmt.debug_map(), |b, &(ref k, ref v)| b.entry(k, v)).finish()
+    ///         fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
     ///     }
     /// }
     ///
     /// // prints "{"A": 10, "B": 11}"
     /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
     /// ```
-    #[unstable(feature = "debug_builders", reason = "method was just created")]
+    #[stable(feature = "debug_builders", since = "1.2.0")]
     #[inline]
     pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> {
         builders::debug_map_new(self)
     }
 }
 
+#[stable(since = "1.2.0", feature = "formatter_write")]
+impl<'a> Write for Formatter<'a> {
+    fn write_str(&mut self, s: &str) -> Result {
+        self.buf.write_str(s)
+    }
+
+    fn write_char(&mut self, c: char) -> Result {
+        self.buf.write_char(c)
+    }
+
+    fn write_fmt(&mut self, args: Arguments) -> Result {
+        write(self.buf, args)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Display for Error {
     fn fmt(&self, f: &mut Formatter) -> Result {
@@ -926,10 +980,14 @@ impl Debug for char {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Display for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        let mut utf8 = [0; 4];
-        let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
-        let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
-        Display::fmt(s, f)
+        if f.width.is_none() && f.precision.is_none() {
+            f.write_char(*self)
+        } else {
+            let mut utf8 = [0; 4];
+            let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
+            let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
+            f.pad(s)
+        }
     }
 }
 
@@ -1120,7 +1178,7 @@ tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for [T] {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish()
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
index 122fffc5959056a99c3edbe3d97155ec878c0d66..fc49f87d107699c2defce051f06df1100f6c37ce 100644 (file)
@@ -127,7 +127,7 @@ radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
 
 /// A radix with in the range of `2..36`.
 #[derive(Clone, Copy, PartialEq)]
-#[unstable(feature = "core",
+#[unstable(feature = "fmt_radix",
            reason = "may be renamed or move to a different module")]
 pub struct Radix {
     base: u8,
@@ -152,7 +152,7 @@ impl GenericRadix for Radix {
 }
 
 /// A helper type for formatting radixes.
-#[unstable(feature = "core",
+#[unstable(feature = "fmt_radix",
            reason = "may be renamed or move to a different module")]
 #[derive(Copy, Clone)]
 pub struct RadixFmt<T, R>(T, R);
@@ -162,11 +162,11 @@ pub struct RadixFmt<T, R>(T, R);
 /// # Examples
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(fmt_radix)]
 /// use std::fmt::radix;
 /// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
 /// ```
-#[unstable(feature = "core",
+#[unstable(feature = "fmt_radix",
            reason = "may be renamed or move to a different module")]
 pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
     RadixFmt(x, Radix::new(base))
index 2afd8abeb31aa5810f414924a06e080ac2e357c6..033834dd5aaaa59dc7941eb5a82f06271782a599 100644 (file)
@@ -14,8 +14,6 @@
 //! These definitions are similar to their `ct` equivalents, but differ in that
 //! these can be statically allocated and are slightly optimized for the runtime
 
-#![unstable(feature = "core", reason = "internal to format_args!")]
-
 #[derive(Copy, Clone)]
 pub struct Argument {
     pub position: Position,
index e848a44e01ce0ef267e6f1d7df00c0e7df5c90ab..abf9e55a1f2fbaa1e10a18cbde5fcbd5151b3a40 100644 (file)
@@ -16,7 +16,7 @@
 //! # Examples
 //!
 //! ```rust
-//! # #![feature(hash)]
+//! # #![feature(hash_default)]
 //! use std::hash::{hash, Hash, SipHasher};
 //!
 //! #[derive(Hash)]
@@ -36,7 +36,7 @@
 //! the trait `Hash`:
 //!
 //! ```rust
-//! # #![feature(hash)]
+//! # #![feature(hash_default)]
 //! use std::hash::{hash, Hash, Hasher, SipHasher};
 //!
 //! struct Person {
@@ -89,7 +89,8 @@ pub trait Hash {
     fn hash<H: Hasher>(&self, state: &mut H);
 
     /// Feeds a slice of this type into the state provided.
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hash_slice",
+               reason = "module was recently redesigned")]
     fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
         for piece in data {
             piece.hash(state);
@@ -110,29 +111,29 @@ pub trait Hasher {
 
     /// Write a single `u8` into this hasher
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_u8(&mut self, i: u8) { self.write(&[i]) }
     /// Write a single `u16` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_u16(&mut self, i: u16) {
         self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
     }
     /// Write a single `u32` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_u32(&mut self, i: u32) {
         self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
     }
     /// Write a single `u64` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_u64(&mut self, i: u64) {
         self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
     }
     /// Write a single `usize` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_usize(&mut self, i: usize) {
         if cfg!(target_pointer_width = "32") {
             self.write_u32(i as u32)
@@ -143,23 +144,23 @@ pub trait Hasher {
 
     /// Write a single `i8` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
     /// Write a single `i16` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
     /// Write a single `i32` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
     /// Write a single `i64` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
     /// Write a single `isize` into this hasher.
     #[inline]
-    #[unstable(feature = "hash", reason = "module was recently redesigned")]
+    #[unstable(feature = "hasher_write", reason = "module was recently redesigned")]
     fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
 }
 
@@ -167,7 +168,9 @@ pub trait Hasher {
 ///
 /// The specified value will be hashed with this hasher and then the resulting
 /// hash will be returned.
-#[unstable(feature = "hash", reason = "module was recently redesigned")]
+#[unstable(feature = "hash_default",
+           reason = "not the most ergonomic interface unless `H` is defaulted \
+                     to SipHasher, but perhaps not ready to commit to that")]
 pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
     let mut h: H = Default::default();
     value.hash(&mut h);
index d94b8884112d66e35a113aeec90d5c619844edcc..455928077da462f1d17279d52353e3e617eda326 100644 (file)
 //!   guaranteed to happen in order. This is the standard mode for working
 //!   with atomic types and is equivalent to Java's `volatile`.
 
-#![unstable(feature = "core")]
+#![unstable(feature = "core_intrinsics",
+            reason = "intrinsics are unlikely to ever be stabilized, instead \
+                      they should be used through stabilized interfaces \
+                      in the rest of the standard library")]
 #![allow(missing_docs)]
 
 use marker::Sized;
 
 extern "rust-intrinsic" {
 
-    // NB: These intrinsics take unsafe pointers because they mutate aliased
+    // NB: These intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
 
     pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> T;
@@ -141,17 +144,13 @@ extern "rust-intrinsic" {
 
     /// A compiler-only memory barrier.
     ///
-    /// Memory accesses will never be reordered across this barrier by the compiler,
-    /// but no instructions will be emitted for it. This is appropriate for operations
-    /// on the same thread that may be preempted, such as when interacting with signal
-    /// handlers.
-    #[cfg(not(stage0))]     // SNAP 857ef6e
+    /// Memory accesses will never be reordered across this barrier by the
+    /// compiler, but no instructions will be emitted for it. This is
+    /// appropriate for operations on the same thread that may be preempted,
+    /// such as when interacting with signal handlers.
     pub fn atomic_singlethreadfence();
-    #[cfg(not(stage0))]     // SNAP 857ef6e
     pub fn atomic_singlethreadfence_acq();
-    #[cfg(not(stage0))]     // SNAP 857ef6e
     pub fn atomic_singlethreadfence_rel();
-    #[cfg(not(stage0))]     // SNAP 857ef6e
     pub fn atomic_singlethreadfence_acqrel();
 
     /// Aborts the execution of the process.
@@ -193,11 +192,8 @@ extern "rust-intrinsic" {
     pub fn min_align_of<T>() -> usize;
     pub fn pref_align_of<T>() -> usize;
 
-    #[cfg(not(stage0))]
     pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
-    #[cfg(not(stage0))]
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
-    #[cfg(not(stage0))]
     pub fn drop_in_place<T: ?Sized>(_: *mut T);
 
     /// Gets a static string slice containing the name of a type.
@@ -283,6 +279,19 @@ extern "rust-intrinsic" {
     /// returned value will result in undefined behavior.
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
 
+    /// Calculates the offset from a pointer, potentially wrapping.
+    ///
+    /// This is implemented as an intrinsic to avoid converting to and from an
+    /// integer, since the conversion inhibits certain optimizations.
+    ///
+    /// # Safety
+    ///
+    /// Unlike the `offset` intrinsic, this intrinsic does not restrict the
+    /// resulting pointer to point into or one byte past the end of an allocated
+    /// object, and it wraps with two's complement arithmetic. The resulting
+    /// value is not necessarily valid to be used to actually access memory.
+    pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
+
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
     /// and destination may *not* overlap.
     ///
@@ -302,7 +311,6 @@ extern "rust-intrinsic" {
     /// A safe swap function:
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::mem;
     /// use std::ptr;
     ///
@@ -342,7 +350,6 @@ extern "rust-intrinsic" {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// # #![feature(core)]
     /// use std::ptr;
     ///
     /// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
@@ -578,13 +585,6 @@ extern "rust-intrinsic" {
     /// Returns (a * b) mod 2^N, where N is the width of N in bits.
     pub fn overflowing_mul<T>(a: T, b: T) -> T;
 
-    /// Returns the value of the discriminant for the variant in 'v',
-    /// cast to a `u64`; if `T` has no discriminant, returns 0.
-    pub fn discriminant_value<T>(v: &T) -> u64;
-}
-
-#[cfg(not(stage0))]
-extern "rust-intrinsic" {
     /// Performs an unchecked signed division, which results in undefined behavior,
     /// in cases where y == 0, or x == int::MIN and y == -1
     pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
@@ -598,4 +598,8 @@ extern "rust-intrinsic" {
     /// Returns the remainder of an unchecked signed division, which results in
     /// undefined behavior, in cases where y == 0
     pub fn unchecked_srem<T>(x: T, y: T) -> T;
+
+    /// Returns the value of the discriminant for the variant in 'v',
+    /// cast to a `u64`; if `T` has no discriminant, returns 0.
+    pub fn discriminant_value<T>(v: &T) -> u64;
 }
index 091342226e0ece459a3b26804250148d5170dab7..3026f91e853eee34f69833a1615d05da56be928a 100644 (file)
@@ -51,8 +51,8 @@
 //! }
 //! ```
 //!
-//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be applied to any
-//! iterator over any type.
+//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be
+//! applied to any iterator over any type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -177,7 +177,7 @@ pub trait Iterator {
     /// ```
     /// let a = [0];
     /// let b = [1];
-    /// let mut it = a.iter().chain(b.iter());
+    /// let mut it = a.iter().chain(&b);
     /// assert_eq!(it.next(), Some(&0));
     /// assert_eq!(it.next(), Some(&1));
     /// assert!(it.next().is_none());
@@ -200,7 +200,7 @@ pub trait Iterator {
     /// ```
     /// let a = [0];
     /// let b = [1];
-    /// let mut it = a.iter().zip(b.iter());
+    /// let mut it = a.iter().zip(&b);
     /// assert_eq!(it.next(), Some((&0, &1)));
     /// assert!(it.next().is_none());
     /// ```
@@ -326,7 +326,6 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// let xs = [100, 200, 300];
     /// let mut it = xs.iter().cloned().peekable();
     /// assert_eq!(*it.peek().unwrap(), 100);
@@ -452,20 +451,19 @@ pub trait Iterator {
         Scan{iter: self, f: f, state: initial_state}
     }
 
-    /// Creates an iterator that maps each element to an iterator,
-    /// and yields the elements of the produced iterators.
+    /// Takes a function that maps each element to a new iterator and yields
+    /// all the elements of the produced iterators.
+    ///
+    /// This is useful for unraveling nested structures.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    /// let xs = [2, 3];
-    /// let ys = [0, 1, 0, 1, 2];
-    /// let it = xs.iter().flat_map(|&x| (0..).take(x));
-    /// // Check that `it` has the same elements as `ys`
-    /// for (i, x) in it.enumerate() {
-    ///     assert_eq!(x, ys[i]);
-    /// }
+    /// let words = ["alpha", "beta", "gamma"];
+    /// let merged: String = words.iter()
+    ///                           .flat_map(|s| s.chars())
+    ///                           .collect();
+    /// assert_eq!(merged, "alphabetagamma");
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -515,15 +513,13 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    ///
     /// let a = [1, 4, 2, 3, 8, 9, 6];
     /// let sum: i32 = a.iter()
     ///                 .map(|x| *x)
     ///                 .inspect(|&x| println!("filtering {}", x))
     ///                 .filter(|&x| x % 2 == 0)
     ///                 .inspect(|&x| println!("{} made it through", x))
-    ///                 .sum();
+    ///                 .fold(0, |sum, i| sum + i);
     /// println!("{}", sum);
     /// ```
     #[inline]
@@ -573,7 +569,6 @@ pub trait Iterator {
     /// do not.
     ///
     /// ```
-    /// # #![feature(core)]
     /// let vec = vec![1, 2, 3, 4];
     /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0);
     /// assert_eq!(even, [2, 4]);
@@ -590,9 +585,9 @@ pub trait Iterator {
 
         for x in self {
             if f(&x) {
-                left.extend(Some(x).into_iter())
+                left.extend(Some(x))
             } else {
-                right.extend(Some(x).into_iter())
+                right.extend(Some(x))
             }
         }
 
@@ -827,7 +822,7 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
+    /// # #![feature(iter_min_max)]
     /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax};
     ///
     /// let a: [i32; 0] = [];
@@ -842,7 +837,9 @@ pub trait Iterator {
     /// let a = [1, 1, 1, 1];
     /// assert_eq!(a.iter().min_max(), MinMax(&1, &1));
     /// ```
-    #[unstable(feature = "core", reason = "return type may change")]
+    #[unstable(feature = "iter_min_max",
+               reason = "return type may change or may wish to have a closure \
+                         based version as well")]
     fn min_max(mut self) -> MinMaxResult<Self::Item> where Self: Sized, Self::Item: Ord
     {
         let (mut min, mut max) = match self.next() {
@@ -897,13 +894,12 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    ///
+    /// # #![feature(iter_cmp)]
     /// let a = [-3_i32, 0, 1, 5, -10];
     /// assert_eq!(*a.iter().max_by(|x| x.abs()).unwrap(), -10);
     /// ```
     #[inline]
-    #[unstable(feature = "core",
+    #[unstable(feature = "iter_cmp",
                reason = "may want to produce an Ordering directly; see #15311")]
     fn max_by<B: Ord, F>(self, f: F) -> Option<Self::Item> where
         Self: Sized,
@@ -926,13 +922,12 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    ///
+    /// # #![feature(iter_cmp)]
     /// let a = [-3_i32, 0, 1, 5, -10];
     /// assert_eq!(*a.iter().min_by(|x| x.abs()).unwrap(), 0);
     /// ```
     #[inline]
-    #[unstable(feature = "core",
+    #[unstable(feature = "iter_cmp",
                reason = "may want to produce an Ordering directly; see #15311")]
     fn min_by<B: Ord, F>(self, f: F) -> Option<Self::Item> where
         Self: Sized,
@@ -972,7 +967,6 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// let a = [(1, 2), (3, 4)];
     /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
     /// assert_eq!(left, [1, 3]);
@@ -1002,15 +996,26 @@ pub trait Iterator {
         us.extend(SizeHint(lo, hi, marker::PhantomData));
 
         for (t, u) in self {
-            ts.extend(Some(t).into_iter());
-            us.extend(Some(u).into_iter());
+            ts.extend(Some(t));
+            us.extend(Some(u));
         }
 
         (ts, us)
     }
 
-    /// Creates an iterator that clones the elements it yields. Useful for
-    /// converting an Iterator<&T> to an Iterator<T>.
+    /// Creates an iterator that clones the elements it yields.
+    ///
+    /// This is useful for converting an Iterator<&T> to an Iterator<T>,
+    /// so it's a more convenient form of `map(|&x| x)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let a = [0, 1, 2];
+    /// let v_cloned: Vec<_> = a.iter().cloned().collect();
+    /// let v_map: Vec<_> = a.iter().map(|&x| x).collect();
+    /// assert_eq!(v_cloned, v_map);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn cloned<'a, T: 'a>(self) -> Cloned<Self>
         where Self: Sized + Iterator<Item=&'a T>, T: Clone
@@ -1038,6 +1043,8 @@ pub trait Iterator {
     /// Use an iterator to reverse a container in place.
     #[unstable(feature = "core",
                reason = "uncertain about placement or widespread use")]
+    #[deprecated(since = "1.2.0",
+                 reason = "not performant enough to justify inclusion")]
     fn reverse_in_place<'a, T: 'a>(&mut self) where
         Self: Sized + Iterator<Item=&'a mut T> + DoubleEndedIterator
     {
@@ -1054,13 +1061,12 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    ///
+    /// # #![feature(iter_arith)]
     /// let a = [1, 2, 3, 4, 5];
-    /// let mut it = a.iter().cloned();
+    /// let it = a.iter();
     /// assert_eq!(it.sum::<i32>(), 15);
     /// ```
-    #[unstable(feature="core")]
+    #[unstable(feature="iter_arith", reason = "bounds recently changed")]
     fn sum<S=<Self as Iterator>::Item>(self) -> S where
         S: Add<Self::Item, Output=S> + Zero,
         Self: Sized,
@@ -1073,8 +1079,7 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    ///
+    /// # #![feature(iter_arith)]
     /// fn factorial(n: u32) -> u32 {
     ///     (1..).take_while(|&i| i <= n).product()
     /// }
@@ -1082,7 +1087,7 @@ pub trait Iterator {
     /// assert_eq!(factorial(1), 1);
     /// assert_eq!(factorial(5), 120);
     /// ```
-    #[unstable(feature="core")]
+    #[unstable(feature="iter_arith", reason = "bounds recently changed")]
     fn product<P=<Self as Iterator>::Item>(self) -> P where
         P: Mul<Self::Item, Output=P> + One,
         Self: Sized,
@@ -1222,9 +1227,14 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
 /// `DoubleEndedIterator`.  Calling `next()` or `next_back()` on a
 /// `RandomAccessIterator` reduces the indexable range accordingly. That is,
 /// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called.
-#[unstable(feature = "core",
+#[unstable(feature = "iter_idx",
            reason = "not widely used, may be better decomposed into Index \
                      and ExactSizeIterator")]
+#[deprecated(since = "1.2.0",
+             reason = "trait has not proven itself as a widely useful \
+                       abstraction for iterators, and more time may be needed \
+                       for iteration on the design")]
+#[allow(deprecated)]
 pub trait RandomAccessIterator: Iterator {
     /// Returns the number of indexable elements. At most `std::usize::MAX`
     /// elements are indexable, even if the iterator represents a longer range.
@@ -1303,7 +1313,8 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Rev<I>
     where I: DoubleEndedIterator + RandomAccessIterator
 {
@@ -1323,7 +1334,7 @@ impl<I> RandomAccessIterator for Rev<I>
 /// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
 /// more detail.
 #[derive(Clone, PartialEq, Debug)]
-#[unstable(feature = "core",
+#[unstable(feature = "iter_min_max",
            reason = "unclear whether such a fine-grained result is widely useful")]
 pub enum MinMaxResult<T> {
     /// Empty iterator
@@ -1337,6 +1348,7 @@ pub enum MinMaxResult<T> {
     MinMax(T, T)
 }
 
+#[unstable(feature = "iter_min_max", reason = "type is unstable")]
 impl<T: Clone> MinMaxResult<T> {
     /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option`
     /// has variant `None` if and only if the `MinMaxResult` has variant
@@ -1347,7 +1359,7 @@ impl<T: Clone> MinMaxResult<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
+    /// # #![feature(iter_min_max)]
     /// use std::iter::MinMaxResult::{self, NoElements, OneElement, MinMax};
     ///
     /// let r: MinMaxResult<i32> = NoElements;
@@ -1359,7 +1371,6 @@ impl<T: Clone> MinMaxResult<T> {
     /// let r = MinMax(1, 2);
     /// assert_eq!(r.into_option(), Some((1, 2)));
     /// ```
-    #[unstable(feature = "core", reason = "type is unstable")]
     pub fn into_option(self) -> Option<(T,T)> {
         match self {
             NoElements => None,
@@ -1406,7 +1417,8 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
     where I: ExactSizeIterator<Item=&'a T>, T: Clone
 {}
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, I, T: 'a> RandomAccessIterator for Cloned<I>
     where I: RandomAccessIterator<Item=&'a T>, T: Clone
 {
@@ -1453,7 +1465,8 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Cycle<I> where
     I: Clone + RandomAccessIterator,
 {
@@ -1567,7 +1580,8 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<A, B> RandomAccessIterator for Chain<A, B> where
     A: RandomAccessIterator,
     B: RandomAccessIterator<Item = A::Item>,
@@ -1655,7 +1669,8 @@ impl<A, B> DoubleEndedIterator for Zip<A, B> where
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<A, B> RandomAccessIterator for Zip<A, B> where
     A: RandomAccessIterator,
     B: RandomAccessIterator
@@ -1709,7 +1724,8 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<B, I: RandomAccessIterator, F> RandomAccessIterator for Map<I, F> where
     F: FnMut(I::Item) -> B,
 {
@@ -1883,7 +1899,8 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Enumerate<I> where I: RandomAccessIterator {
     #[inline]
     fn indexable(&self) -> usize {
@@ -2133,7 +2150,8 @@ impl<I> Iterator for Skip<I> where I: Iterator {
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Skip<I> where I: RandomAccessIterator{
     #[inline]
     fn indexable(&self) -> usize {
@@ -2205,7 +2223,8 @@ impl<I> Iterator for Take<I> where I: Iterator{
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Take<I> where I: RandomAccessIterator{
     #[inline]
     fn indexable(&self) -> usize {
@@ -2235,7 +2254,8 @@ pub struct Scan<I, St, F> {
     f: F,
 
     /// The current internal state to be passed to the closure next.
-    #[unstable(feature = "core")]
+    #[unstable(feature = "scan_state",
+               reason = "public fields are otherwise rare in the stdlib")]
     pub state: St,
 }
 
@@ -2405,7 +2425,8 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
 }
 
 // Allow RandomAccessIterators to be fused without affecting random-access behavior
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I> RandomAccessIterator for Fuse<I> where I: RandomAccessIterator {
     #[inline]
     fn indexable(&self) -> usize {
@@ -2426,7 +2447,7 @@ impl<I> Fuse<I> {
     /// `.next_back()` will call the underlying iterator again even if it
     /// previously returned `None`.
     #[inline]
-    #[unstable(feature = "core", reason = "seems marginal")]
+    #[unstable(feature = "iter_reset_fuse", reason = "seems marginal")]
     pub fn reset_fuse(&mut self) {
         self.done = false
     }
@@ -2480,7 +2501,8 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
     }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
     where F: FnMut(&I::Item),
 {
@@ -2503,7 +2525,7 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
 /// An iterator that yields sequential Fibonacci numbers, and stops on overflow.
 ///
 /// ```
-/// #![feature(core)]
+/// #![feature(iter_unfold)]
 /// use std::iter::Unfold;
 ///
 /// // This iterator will yield up to the last Fibonacci number before the max
@@ -2530,16 +2552,24 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
 ///     println!("{}", i);
 /// }
 /// ```
-#[unstable(feature = "core")]
+#[unstable(feature = "iter_unfold")]
 #[derive(Clone)]
+#[deprecated(since = "1.2.0",
+             reason = "has gained enough traction to retain its position \
+                       in the standard library")]
+#[allow(deprecated)]
 pub struct Unfold<St, F> {
     f: F,
     /// Internal state that will be passed to the closure on the next iteration
-    #[unstable(feature = "core")]
+    #[unstable(feature = "iter_unfold")]
     pub state: St,
 }
 
-#[unstable(feature = "core")]
+#[unstable(feature = "iter_unfold")]
+#[deprecated(since = "1.2.0",
+             reason = "has gained enough traction to retain its position \
+                       in the standard library")]
+#[allow(deprecated)]
 impl<A, St, F> Unfold<St, F> where F: FnMut(&mut St) -> Option<A> {
     /// Creates a new iterator with the specified closure as the "iterator
     /// function" and an initial state to eventually pass to the closure
@@ -2553,6 +2583,7 @@ impl<A, St, F> Unfold<St, F> where F: FnMut(&mut St) -> Option<A> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl<A, St, F> Iterator for Unfold<St, F> where F: FnMut(&mut St) -> Option<A> {
     type Item = A;
 
@@ -2720,7 +2751,7 @@ impl<A: Step> ops::Range<A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(step_by, core)]
+    /// # #![feature(step_by)]
     /// for i in (0..10).step_by(2) {
     ///     println!("{}", i);
     /// }
@@ -2766,7 +2797,7 @@ impl<A> Iterator for StepBy<A, RangeFrom<A>> where
 
 /// An iterator over the range [start, stop]
 #[derive(Clone)]
-#[unstable(feature = "core",
+#[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters")]
 pub struct RangeInclusive<A> {
     range: ops::Range<A>,
@@ -2775,7 +2806,7 @@ pub struct RangeInclusive<A> {
 
 /// Returns an iterator over the range [start, stop].
 #[inline]
-#[unstable(feature = "core",
+#[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters")]
 pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
     where A: Step + One + Clone
@@ -2786,7 +2817,7 @@ pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
     }
 }
 
-#[unstable(feature = "core",
+#[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters")]
 impl<A> Iterator for RangeInclusive<A> where
     A: PartialEq + Step + One + Clone,
@@ -2819,7 +2850,7 @@ impl<A> Iterator for RangeInclusive<A> where
     }
 }
 
-#[unstable(feature = "core",
+#[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters")]
 impl<A> DoubleEndedIterator for RangeInclusive<A> where
     A: PartialEq + Step + One + Clone,
@@ -2961,7 +2992,7 @@ impl<A: Clone> Iterator for Repeat<A> {
     type Item = A;
 
     #[inline]
-    fn next(&mut self) -> Option<A> { self.idx(0) }
+    fn next(&mut self) -> Option<A> { Some(self.element.clone()) }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) }
 }
@@ -2969,10 +3000,11 @@ impl<A: Clone> Iterator for Repeat<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Clone> DoubleEndedIterator for Repeat<A> {
     #[inline]
-    fn next_back(&mut self) -> Option<A> { self.idx(0) }
+    fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<A: Clone> RandomAccessIterator for Repeat<A> {
     #[inline]
     fn indexable(&self) -> usize { usize::MAX }
@@ -2984,12 +3016,20 @@ type IterateState<T, F> = (F, Option<T>, bool);
 
 /// An iterator that repeatedly applies a given function, starting
 /// from a given seed value.
-#[unstable(feature = "core")]
+#[unstable(feature = "iter_iterate")]
+#[deprecated(since = "1.2.0",
+             reason = "has gained enough traction to retain its position \
+                       in the standard library")]
+#[allow(deprecated)]
 pub type Iterate<T, F> = Unfold<IterateState<T, F>, fn(&mut IterateState<T, F>) -> Option<T>>;
 
 /// Creates a new iterator that produces an infinite sequence of
 /// repeated applications of the given function `f`.
-#[unstable(feature = "core")]
+#[unstable(feature = "iter_iterate")]
+#[deprecated(since = "1.2.0",
+             reason = "has gained enough traction to retain its position \
+                       in the standard library")]
+#[allow(deprecated)]
 pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where
     T: Clone,
     F: FnMut(T) -> T,
@@ -3020,6 +3060,101 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
     Repeat{element: elt}
 }
 
+/// An iterator that yields nothing.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+pub struct Empty<T>(marker::PhantomData<T>);
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Iterator for Empty<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        None
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>){
+        (0, Some(0))
+    }
+}
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> DoubleEndedIterator for Empty<T> {
+    fn next_back(&mut self) -> Option<T> {
+        None
+    }
+}
+
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> ExactSizeIterator for Empty<T> {
+    fn len(&self) -> usize {
+        0
+    }
+}
+
+// not #[derive] because that adds a Clone bound on T,
+// which isn't necessary.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Clone for Empty<T> {
+    fn clone(&self) -> Empty<T> {
+        Empty(marker::PhantomData)
+    }
+}
+
+// not #[derive] because that adds a Default bound on T,
+// which isn't necessary.
+#[stable(feature = "iter_empty", since = "1.2.0")]
+impl<T> Default for Empty<T> {
+    fn default() -> Empty<T> {
+        Empty(marker::PhantomData)
+    }
+}
+
+/// Creates an iterator that yields nothing.
+#[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.
+#[derive(Clone)]
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub struct Once<T> {
+    inner: ::option::IntoIter<T>
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> Iterator for Once<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.inner.next()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> DoubleEndedIterator for Once<T> {
+    fn next_back(&mut self) -> Option<T> {
+        self.inner.next_back()
+    }
+}
+
+#[stable(feature = "iter_once", since = "1.2.0")]
+impl<T> ExactSizeIterator for Once<T> {
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
+}
+
+/// Creates an iterator that yields an element exactly once.
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub fn once<T>(value: T) -> Once<T> {
+    Once { inner: Some(value).into_iter() }
+}
+
 /// Functions for lexicographical ordering of sequences.
 ///
 /// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires
@@ -3027,7 +3162,7 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
 ///
 /// If two sequences are equal up until the point where one ends,
 /// the shorter sequence compares less.
-#[unstable(feature = "core", reason = "needs review and revision")]
+#[unstable(feature = "iter_order", reason = "needs review and revision")]
 pub mod order {
     use cmp;
     use cmp::{Eq, Ord, PartialOrd, PartialEq};
@@ -3114,7 +3249,7 @@ pub mod order {
     }
 
     /// Returns `a` < `b` lexicographically (Using partial order, `PartialOrd`)
-    pub fn lt<R: Iterator, L: Iterator>(mut a: L, mut b: R) -> bool where
+    pub fn lt<L: Iterator, R: Iterator>(mut a: L, mut b: R) -> bool where
         L::Item: PartialOrd<R::Item>,
     {
         loop {
index dd06c3d0987d98b7e0da0444eaaebf21f932093e..392eaf7801a9140bed68ae7c2956a2eeb9c44a37 100644 (file)
 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "core"]
-#![unstable(feature = "core")]
+#![unstable(feature = "core",
+            reason = "the libcore library has not yet been scrutinized for \
+                      stabilization in terms of structure and naming")]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![doc(test(no_crate_inject))]
@@ -63,7 +65,9 @@
 #![allow(raw_pointer_derive)]
 #![deny(missing_docs)]
 
-#![feature(intrinsics, lang_items)]
+#![feature(associated_type_defaults)]
+#![feature(intrinsics)]
+#![feature(lang_items)]
 #![feature(on_unimplemented)]
 #![feature(simd)]
 #![feature(staged_api)]
@@ -74,6 +78,8 @@
 #![feature(concat_idents)]
 #![feature(reflect)]
 #![feature(custom_attribute)]
+#![feature(const_fn)]
+#![feature(allow_internal_unstable)]
 
 #[macro_use]
 mod macros;
index 64eb75ea530f10f7f5d349a5660c764c4ef9e4b4..14bb82dff7d6eacfaae85a68032266ea37fb6ab0 100644 (file)
@@ -10,6 +10,7 @@
 
 /// Entry point of thread panic, for details, see std::macros
 #[macro_export]
+#[allow_internal_unstable]
 macro_rules! panic {
     () => (
         panic!("explicit panic")
@@ -173,12 +174,11 @@ macro_rules! try {
 /// # Examples
 ///
 /// ```
-/// # #![allow(unused_must_use)]
 /// use std::io::Write;
 ///
 /// let mut w = Vec::new();
-/// write!(&mut w, "test");
-/// write!(&mut w, "formatted {}", "arguments");
+/// write!(&mut w, "test").unwrap();
+/// write!(&mut w, "formatted {}", "arguments").unwrap();
 /// ```
 #[macro_export]
 macro_rules! write {
index 5909c5cc30e510dce250e58a7a01f0fa2d965ab4..dd60164a114db0f547ff61718a22f2d5222ad738 100644 (file)
@@ -54,8 +54,7 @@ pub trait Sized {
 }
 
 /// Types that can be "unsized" to a dynamically sized type.
-#[unstable(feature = "core")]
-#[cfg(not(stage0))]
+#[unstable(feature = "unsize")]
 #[lang="unsize"]
 pub trait Unsize<T> {
     // Empty.
@@ -120,11 +119,10 @@ pub trait Unsize<T> {
 /// ```
 ///
 /// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
-/// attempt to derive a `Copy` implementation, we'll get an error.
+/// attempt to derive a `Copy` implementation, we'll get an error:
 ///
 /// ```text
-/// error: the trait `Copy` may not be implemented for this type; field `points` does not implement
-/// `Copy`
+/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
 /// ```
 ///
 /// ## How can I implement `Copy`?
@@ -225,7 +223,10 @@ impl<T> !Sync for *mut T { }
 /// ensure that they are never copied, even if they lack a destructor.
 #[unstable(feature = "core",
            reason = "likely to change with new variance strategy")]
+#[deprecated(since = "1.2.0",
+             reason = "structs are by default not copyable")]
 #[lang = "no_copy_bound"]
+#[allow(deprecated)]
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
 pub struct NoCopy;
 
@@ -359,7 +360,7 @@ macro_rules! impls{
 /// struct is dropped, it may in turn drop one or more instances of
 /// the type `T`, though that may not be apparent from the other
 /// structure of the type itself. This is commonly necessary if the
-/// structure is using an unsafe pointer like `*mut T` whose referent
+/// structure is using a raw pointer like `*mut T` whose referent
 /// may be dropped when the type is dropped, as a `*mut T` is
 /// otherwise not treated as owned.
 ///
@@ -387,7 +388,7 @@ mod impls {
 /// that function. Here is an example:
 ///
 /// ```
-/// #![feature(core)]
+/// #![feature(reflect_marker)]
 /// use std::marker::Reflect;
 /// use std::any::Any;
 /// fn foo<T:Reflect+'static>(x: &T) {
@@ -412,7 +413,8 @@ mod impls {
 ///
 /// [1]: http://en.wikipedia.org/wiki/Parametricity
 #[rustc_reflect_like]
-#[unstable(feature = "core", reason = "requires RFC and more experience")]
+#[unstable(feature = "reflect_marker",
+           reason = "requires RFC and more experience")]
 #[allow(deprecated)]
 #[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
                             ensure all type parameters are bounded by `Any`"]
index 173b73fdb0924366c269f8d2b31df974f44d9b5c..b53b61e517397819608ca80beab3e58494c0a8dd 100644 (file)
@@ -52,20 +52,61 @@ pub use intrinsics::transmute;
 /// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
 /// * Panicking destructors are likely to leak local resources
 ///
+/// # When To Use
+///
+/// There's only a few reasons to use this function. They mainly come
+/// up in unsafe code or FFI code.
+///
+/// * You have an uninitialized value, perhaps for performance reasons, and
+///   need to prevent the destructor from running on it.
+/// * You have two copies of a value (like `std::mem::swap`), but need the
+///   destructor to only run once to prevent a double free.
+/// * Transferring resources across FFI boundries.
+///
 /// # Example
 ///
-/// ```rust,no_run
+/// Leak some heap memory by never deallocating it.
+///
+/// ```rust
 /// use std::mem;
-/// use std::fs::File;
 ///
-/// // Leak some heap memory by never deallocating it
 /// let heap_memory = Box::new(3);
 /// mem::forget(heap_memory);
+/// ```
+///
+/// Leak an I/O object, never closing the file.
+///
+/// ```rust,no_run
+/// use std::mem;
+/// use std::fs::File;
 ///
-/// // Leak an I/O object, never closing the file
 /// let file = File::open("foo.txt").unwrap();
 /// mem::forget(file);
 /// ```
+///
+/// The swap function uses forget to good effect.
+///
+/// ```rust
+/// use std::mem;
+/// use std::ptr;
+///
+/// fn swap<T>(x: &mut T, y: &mut T) {
+///     unsafe {
+///         // Give ourselves some scratch space to work with
+///         let mut t: T = mem::uninitialized();
+///
+///         // Perform the swap, `&mut` pointers never alias
+///         ptr::copy_nonoverlapping(&*x, &mut t, 1);
+///         ptr::copy_nonoverlapping(&*y, x, 1);
+///         ptr::copy_nonoverlapping(&t, y, 1);
+///
+///         // y and t now point to the same thing, but we need to completely
+///         // forget `t` because we do not want to run the destructor for `T`
+///         // on its value, which is still owned somewhere outside this function.
+///         mem::forget(t);
+///     }
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn forget<T>(t: T) {
     unsafe { intrinsics::forget(t) }
@@ -95,29 +136,12 @@ pub fn size_of<T>() -> usize {
 ///
 /// assert_eq!(4, mem::size_of_val(&5i32));
 /// ```
-#[cfg(not(stage0))]
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
     unsafe { intrinsics::size_of_val(val) }
 }
 
-/// Returns the size of the type that `_val` points to in bytes.
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// assert_eq!(4, mem::size_of_val(&5i32));
-/// ```
-#[cfg(stage0)]
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn size_of_val<T>(_val: &T) -> usize {
-    size_of::<T>()
-}
-
 /// Returns the ABI-required minimum alignment of a type
 ///
 /// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
@@ -131,6 +155,7 @@ pub fn size_of_val<T>(_val: &T) -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(reason = "use `align_of` instead", since = "1.2.0")]
 pub fn min_align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -144,33 +169,16 @@ pub fn min_align_of<T>() -> usize {
 ///
 /// assert_eq!(4, mem::min_align_of_val(&5i32));
 /// ```
-#[cfg(not(stage0))]
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
 pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
     unsafe { intrinsics::min_align_of_val(val) }
 }
 
-/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// assert_eq!(4, mem::min_align_of_val(&5i32));
-/// ```
-#[cfg(stage0)]
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn min_align_of_val<T>(_val: &T) -> usize {
-    min_align_of::<T>()
-}
-
 /// Returns the alignment in memory for a type.
 ///
-/// This function will return the alignment, in bytes, of a type in memory. If the alignment
-/// returned is adhered to, then the type is guaranteed to function properly.
+/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
 ///
 /// # Examples
 ///
@@ -182,17 +190,10 @@ pub fn min_align_of_val<T>(_val: &T) -> usize {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn align_of<T>() -> usize {
-    // We use the preferred alignment as the default alignment for a type. This
-    // appears to be what clang migrated towards as well:
-    //
-    // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
-    unsafe { intrinsics::pref_align_of::<T>() }
+    unsafe { intrinsics::min_align_of::<T>() }
 }
 
-/// Returns the alignment of the type of the value that `_val` points to.
-///
-/// This is similar to `align_of`, but function will properly handle types such as trait objects
-/// (in the future), returning the alignment for an arbitrary value at runtime.
+/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
 ///
 /// # Examples
 ///
@@ -203,8 +204,8 @@ pub fn align_of<T>() -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn align_of_val<T>(_val: &T) -> usize {
-    align_of::<T>()
+pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Creates a value initialized to zero.
@@ -301,8 +302,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
         ptr::copy_nonoverlapping(&*y, x, 1);
         ptr::copy_nonoverlapping(&t, y, 1);
 
-        // y and t now point to the same thing, but we need to completely forget `t`
-        // because it's no longer relevant.
+        // y and t now point to the same thing, but we need to completely
+        // forget `t` because we do not want to run the destructor for `T`
+        // on its value, which is still owned somewhere outside this function.
         forget(t);
     }
 }
@@ -451,9 +453,13 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
 
 /// Transforms lifetime of the second pointer to match the first.
 #[inline]
-#[unstable(feature = "core",
+#[unstable(feature = "copy_lifetime",
            reason = "this function may be removed in the future due to its \
                      questionable utility")]
+#[deprecated(since = "1.2.0",
+             reason = "unclear that this function buys more safety and \
+                       lifetimes are generally not handled as such in unsafe \
+                       code today")]
 pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                         ptr: &T) -> &'a T {
     transmute(ptr)
@@ -461,9 +467,13 @@ pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
 
 /// Transforms lifetime of the second mutable pointer to match the first.
 #[inline]
-#[unstable(feature = "core",
+#[unstable(feature = "copy_lifetime",
            reason = "this function may be removed in the future due to its \
                      questionable utility")]
+#[deprecated(since = "1.2.0",
+             reason = "unclear that this function buys more safety and \
+                       lifetimes are generally not handled as such in unsafe \
+                       code today")]
 pub unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                                ptr: &mut T)
                                                               -> &'a mut T
index 59819fd500d1d25235ae95a1306c9a8504f60132..1b5fa4e0e950b9ba113e16c143f6103452812d0d 100644 (file)
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 //! Exposes the NonZero lang item which provides optimization hints.
+#![unstable(feature = "nonzero",
+            reason = "needs an RFC to flesh out the design")]
 
 use marker::Sized;
-use ops::Deref;
-#[cfg(not(stage0))]
-use ops::CoerceUnsized;
+use ops::{CoerceUnsized, Deref};
 
 /// Unsafe trait to indicate what types are usable with the NonZero struct
 pub unsafe trait Zeroable {}
@@ -35,7 +35,6 @@ unsafe impl Zeroable for u64 {}
 /// NULL or 0 that might allow certain optimizations.
 #[lang = "non_zero"]
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
-#[unstable(feature = "core")]
 pub struct NonZero<T: Zeroable>(T);
 
 impl<T: Zeroable> NonZero<T> {
@@ -57,5 +56,4 @@ impl<T: Zeroable> Deref for NonZero<T> {
     }
 }
 
-#[cfg(not(stage0))]
 impl<T: Zeroable+CoerceUnsized<U>, U: Zeroable> CoerceUnsized<NonZero<U>> for NonZero<T> {}
index 50dd3f1661adf6c0fa632841668af366e683c104..aade9061657b7f4ecc9e250abdb8e42f20e1e84d 100644 (file)
@@ -71,7 +71,9 @@ pub mod consts {
     pub const PI: f32 = 3.14159265358979323846264338327950288_f32;
 
     /// pi * 2.0
-    #[unstable(feature = "core", reason = "unclear naming convention/usefulness")]
+    #[unstable(feature = "float_consts",
+               reason = "unclear naming convention/usefulness")]
+    #[deprecated(since = "1.2.0", reason = "unclear on usefulness")]
     pub const PI_2: f32 = 6.28318530717958647692528676655900576_f32;
 
     /// pi/2.0
@@ -135,7 +137,6 @@ pub mod consts {
     pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
 }
 
-#[unstable(feature = "core", reason = "trait is unstable")]
 impl Float for f32 {
     #[inline]
     fn nan() -> f32 { NAN }
index 62b566e7eb40cb65f8b45d704e0f8c2fa83d22f7..7c9e846af9b10219c1d2ae02bf255b95fb6c244c 100644 (file)
@@ -71,7 +71,9 @@ pub mod consts {
     pub const PI: f64 = 3.14159265358979323846264338327950288_f64;
 
     /// pi * 2.0
-    #[unstable(feature = "core", reason = "unclear naming convention/usefulness")]
+    #[unstable(feature = "float_consts",
+               reason = "unclear naming convention/usefulness")]
+    #[deprecated(since = "1.2.0", reason = "unclear on usefulness")]
     pub const PI_2: f64 = 6.28318530717958647692528676655900576_f64;
 
     /// pi/2.0
@@ -135,7 +137,6 @@ pub mod consts {
     pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
 }
 
-#[unstable(feature = "core", reason = "trait is unstable")]
 impl Float for f64 {
     #[inline]
     fn nan() -> f64 { NAN }
index d6a5e44a1fb00372681874471c27fe5abc034d15..4f373c16f7c0888974a8d79ee646d6115f2e58a7 100644 (file)
@@ -146,7 +146,7 @@ macro_rules! define_bignum {
 
                 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].iter()) {
+                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;
@@ -166,7 +166,7 @@ macro_rules! define_bignum {
 
                 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].iter()) {
+                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;
@@ -183,7 +183,7 @@ macro_rules! define_bignum {
 
                 let mut sz = self.size;
                 let mut carry = 0;
-                for a in self.base[..sz].iter_mut() {
+                for a in &mut self.base[..sz] {
                     let (c, v) = (*a).full_mul(other, carry);
                     *a = v;
                     carry = c;
index f51dcf54a19590a812637ca1bc21531f841be32f..f3a7e8f09a9eb77c3dec1d9938f352ff43c75600 100644 (file)
@@ -126,6 +126,8 @@ functions.
 // while this is extensively documented, this is in principle private which is
 // only made public for testing. do not expose us.
 #![doc(hidden)]
+#![unstable(feature = "flt2dec",
+            reason = "internal routines only exposed for testing")]
 
 use prelude::*;
 use i16;
index a819932525bd14259559a5c8fb407fbfa9d1bb42..a11377893713d02a0610645beee045bbd4d0c1a3 100644 (file)
@@ -24,7 +24,6 @@ use num::flt2dec::estimator::estimate_scaling_factor;
 use num::flt2dec::bignum::Digit32 as Digit;
 use num::flt2dec::bignum::Big32x36 as Big;
 
-// FIXME(#22540) const ref to static array seems to ICE
 static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000,
                              1000000, 10000000, 100000000, 1000000000];
 static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000,
@@ -328,4 +327,3 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi
 
     (len, k)
 }
-
index 220811e9985c33c8843e3ed78e41c450538ef04f..54d3c92eca4666cd6334f4fffcc3a148266e80bf 100644 (file)
@@ -87,7 +87,7 @@ for i in xrange(-308, 333, 8):
     f = ((f << 64 >> (l-1)) + 1) >> 1; e += l - 64
     print '    (%#018x, %5d, %4d),' % (f, e, i)
 */
-// FIXME(#22540) const ref to static array seems to ICE
+
 #[doc(hidden)]
 pub static CACHED_POW10: [(u64, i16, i16); 81] = [ // (f, e, k)
     (0xe61acf033d1a45df, -1087, -308),
@@ -746,4 +746,3 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi
         None => fallback(d, buf, limit),
     }
 }
-
index 3113521e0afff825ed7352ba894b73928686f8a3..efc91238809784650f60a6657e1d4c38b38fb871 100644 (file)
@@ -14,11 +14,13 @@ macro_rules! int_module { ($T:ty, $bits:expr) => (
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
-#[unstable(feature = "core")]
+#[unstable(feature = "num_bits_bytes",
+           reason = "may want to be an associated function")]
 pub const BITS : usize = $bits;
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
-#[unstable(feature = "core")]
+#[unstable(feature = "num_bits_bytes",
+           reason = "may want to be an associated function")]
 pub const BYTES : usize = ($bits / 8);
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
index 0fd0d90b12501ea87b257bb523b56a1c6d0f1b47..2cdfe03eafe7f10ebb2760f13a42937ea47b84c0 100644 (file)
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 //! Operations and constants for pointer-sized signed integers (`isize` type)
-//!
-//! This type was recently added to replace `int`. The rollout of the
-//! new type will gradually take place over the alpha cycle along with
-//! the development of clearer conventions around integer types.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
index bd7286dfa3fa5cd09dd168a974c5b71eeae71f38..97b4f776755332863f6b0502cb3f897bd71e6a9a 100644 (file)
@@ -41,10 +41,7 @@ use str::{FromStr, StrExt};
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
 pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
-#[unstable(feature = "core", reason = "may be removed or relocated")]
 pub mod wrapping;
-
-#[unstable(feature = "core", reason = "internal routines only exposed for testing")]
 pub mod flt2dec;
 
 /// Types that have a "zero" value.
@@ -73,11 +70,11 @@ macro_rules! zero_one_impl {
     ($($t:ty)*) => ($(
         impl Zero for $t {
             #[inline]
-            fn zero() -> $t { 0 }
+            fn zero() -> Self { 0 }
         }
         impl One for $t {
             #[inline]
-            fn one() -> $t { 1 }
+            fn one() -> Self { 1 }
         }
     )*)
 }
@@ -87,20 +84,20 @@ macro_rules! zero_one_impl_float {
     ($($t:ty)*) => ($(
         impl Zero for $t {
             #[inline]
-            fn zero() -> $t { 0.0 }
+            fn zero() -> Self { 0.0 }
         }
         impl One for $t {
             #[inline]
-            fn one() -> $t { 1.0 }
+            fn one() -> Self { 1.0 }
         }
     )*)
 }
 zero_one_impl_float! { f32 f64 }
 
 macro_rules! checked_op {
-    ($T:ty, $U:ty, $op:path, $x:expr, $y:expr) => {{
+    ($U:ty, $op:path, $x:expr, $y:expr) => {{
         let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
-        if overflowed { None } else { Some(result as $T) }
+        if overflowed { None } else { Some(result as Self) }
     }}
 }
 
@@ -110,40 +107,36 @@ unsafe fn bswap8(x: u8) -> u8 { x }
 
 // `Int` + `SignedInt` implemented for signed integers
 macro_rules! int_impl {
-    ($T:ident = $ActualT:ty, $UnsignedT:ty, $BITS:expr,
+    ($ActualT:ty, $UnsignedT:ty, $BITS:expr,
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
         /// Returns the smallest value that can be represented by this integer type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn min_value() -> $T {
-            (-1 as $T) << ($BITS - 1)
+        pub fn min_value() -> Self {
+            (-1 as Self) << ($BITS - 1)
         }
 
         /// Returns the largest value that can be represented by this integer type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn max_value() -> $T {
-            let min = $T::min_value(); !min
+        pub fn max_value() -> Self {
+            let min = Self::min_value(); !min
         }
 
         /// Converts a string slice in a given base to an integer.
         ///
         /// Leading and trailing whitespace represent an error.
         ///
-        /// # Arguments
-        ///
-        /// * src - A string slice
-        /// * radix - The base to use. Must lie in the range [2 .. 36]
-        ///
-        /// # Return value
+        /// # Examples
         ///
-        /// `Err(ParseIntError)` if the string did not represent a valid number.
-        /// Otherwise, `Ok(n)` where `n` is the integer represented by `src`.
+        /// ```
+        /// assert_eq!(u32::from_str_radix("A", 16), Ok(10));
+        /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[allow(deprecated)]
-        pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> {
+        pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
             from_str_radix(src, radix)
         }
 
@@ -220,8 +213,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn rotate_left(self, n: u32) -> $T {
-            (self as $UnsignedT).rotate_left(n) as $T
+        pub fn rotate_left(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_left(n) as Self
         }
 
         /// Shifts the bits to the right by a specified amount, `n`,
@@ -238,8 +231,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn rotate_right(self, n: u32) -> $T {
-            (self as $UnsignedT).rotate_right(n) as $T
+        pub fn rotate_right(self, n: u32) -> Self {
+            (self as $UnsignedT).rotate_right(n) as Self
         }
 
         /// Reverses the byte order of the integer.
@@ -254,8 +247,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn swap_bytes(self) -> $T {
-            (self as $UnsignedT).swap_bytes() as $T
+        pub fn swap_bytes(self) -> Self {
+            (self as $UnsignedT).swap_bytes() as Self
         }
 
         /// Converts an integer from big endian to the target's endianness.
@@ -276,7 +269,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn from_be(x: $T) -> $T {
+        pub fn from_be(x: Self) -> Self {
             if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
         }
 
@@ -298,7 +291,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn from_le(x: $T) -> $T {
+        pub fn from_le(x: Self) -> Self {
             if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
         }
 
@@ -320,7 +313,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn to_be(self) -> $T { // or not to be?
+        pub fn to_be(self) -> Self { // or not to be?
             if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
         }
 
@@ -342,7 +335,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn to_le(self) -> $T {
+        pub fn to_le(self) -> Self {
             if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
         }
 
@@ -357,8 +350,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_add(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $add_with_overflow, self, other)
+        pub fn checked_add(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $add_with_overflow, self, other)
         }
 
         /// Checked integer subtraction. Computes `self - other`, returning
@@ -372,8 +365,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_sub(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $sub_with_overflow, self, other)
+        pub fn checked_sub(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $sub_with_overflow, self, other)
         }
 
         /// Checked integer multiplication. Computes `self * other`, returning
@@ -387,8 +380,8 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_mul(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $mul_with_overflow, self, other)
+        pub fn checked_mul(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $mul_with_overflow, self, other)
         }
 
         /// Checked integer division. Computes `self / other`, returning `None`
@@ -403,10 +396,10 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_div(self, v: $T) -> Option<$T> {
+        pub fn checked_div(self, v: Self) -> Option<Self> {
             match v {
                 0   => None,
-               -1 if self == <$T>::min_value()
+               -1 if self == Self::min_value()
                     => None,
                 v   => Some(self / v),
             }
@@ -416,11 +409,11 @@ macro_rules! int_impl {
         /// the numeric bounds instead of overflowing.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn saturating_add(self, other: $T) -> $T {
+        pub fn saturating_add(self, other: Self) -> Self {
             match self.checked_add(other) {
                 Some(x)                       => x,
-                None if other >= <$T as Zero>::zero() => <$T>::max_value(),
-                None => <$T>::min_value(),
+                None if other >= Self::zero() => Self::max_value(),
+                None => Self::min_value(),
             }
         }
 
@@ -428,11 +421,11 @@ macro_rules! int_impl {
         /// at the numeric bounds instead of overflowing.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn saturating_sub(self, other: $T) -> $T {
+        pub fn saturating_sub(self, other: Self) -> Self {
             match self.checked_sub(other) {
                 Some(x)                      => x,
-                None if other >= <$T as Zero>::zero() => <$T>::min_value(),
-                None => <$T>::max_value(),
+                None if other >= Self::zero() => Self::min_value(),
+                None => Self::max_value(),
             }
         }
 
@@ -440,7 +433,7 @@ macro_rules! int_impl {
         /// wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_add(self, rhs: $T) -> $T {
+        pub fn wrapping_add(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_add(self, rhs)
             }
@@ -450,7 +443,7 @@ macro_rules! int_impl {
         /// wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_sub(self, rhs: $T) -> $T {
+        pub fn wrapping_sub(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_sub(self, rhs)
             }
@@ -460,7 +453,7 @@ macro_rules! int_impl {
         /// other`, wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_mul(self, rhs: $T) -> $T {
+        pub fn wrapping_mul(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_mul(self, rhs)
             }
@@ -475,9 +468,9 @@ macro_rules! int_impl {
         /// to `-MIN`, a positive value that is too large to represent
         /// in the type. In such a case, this function returns `MIN`
         /// itself..
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_div(self, rhs: $T) -> $T {
+        pub fn wrapping_div(self, rhs: Self) -> Self {
             self.overflowing_div(rhs).0
         }
 
@@ -488,9 +481,9 @@ macro_rules! int_impl {
         /// implementation artifacts make `x % y` illegal for `MIN /
         /// -1` on a signed type illegal (where `MIN` is the negative
         /// minimal value). In such a case, this function returns `0`.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_rem(self, rhs: $T) -> $T {
+        pub fn wrapping_rem(self, rhs: Self) -> Self {
             self.overflowing_rem(rhs).0
         }
 
@@ -502,27 +495,27 @@ macro_rules! int_impl {
         /// negative minimal value for the type); this is a positive
         /// value that is too large to represent in the type. In such
         /// a case, this function returns `MIN` itself.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_neg(self) -> $T {
+        pub fn wrapping_neg(self) -> Self {
             self.overflowing_neg().0
         }
 
         /// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
         /// where `mask` removes any high-order bits of `rhs` that
         /// would cause the shift to exceed the bitwidth of the type.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_shl(self, rhs: u32) -> $T {
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
 
         /// Panic-free bitwise shift-left; yields `self >> mask(rhs)`,
         /// where `mask` removes any high-order bits of `rhs` that
         /// would cause the shift to exceed the bitwidth of the type.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_shr(self, rhs: u32) -> $T {
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
 
@@ -537,9 +530,9 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn pow(self, mut exp: u32) -> $T {
+        pub fn pow(self, mut exp: u32) -> Self {
             let mut base = self;
-            let mut acc = <$T as One>::one();
+            let mut acc = Self::one();
 
             let mut prev_base = self;
             let mut base_oflo = false;
@@ -573,7 +566,7 @@ macro_rules! int_impl {
         /// optimized code will return `i32::min_value()` without a panic.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn abs(self) -> $T {
+        pub fn abs(self) -> Self {
             if self.is_negative() {
                 // Note that the #[inline] above means that the overflow
                 // semantics of this negation depend on the crate we're being
@@ -591,7 +584,7 @@ macro_rules! int_impl {
         /// - `-1` if the number is negative
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn signum(self) -> $T {
+        pub fn signum(self) -> Self {
             match self {
                 n if n > 0 =>  1,
                 0          =>  0,
@@ -615,7 +608,7 @@ macro_rules! int_impl {
 
 #[lang = "i8"]
 impl i8 {
-    int_impl! { i8 = i8, u8, 8,
+    int_impl! { i8, u8, 8,
         intrinsics::i8_add_with_overflow,
         intrinsics::i8_sub_with_overflow,
         intrinsics::i8_mul_with_overflow }
@@ -623,7 +616,7 @@ impl i8 {
 
 #[lang = "i16"]
 impl i16 {
-    int_impl! { i16 = i16, u16, 16,
+    int_impl! { i16, u16, 16,
         intrinsics::i16_add_with_overflow,
         intrinsics::i16_sub_with_overflow,
         intrinsics::i16_mul_with_overflow }
@@ -631,7 +624,7 @@ impl i16 {
 
 #[lang = "i32"]
 impl i32 {
-    int_impl! { i32 = i32, u32, 32,
+    int_impl! { i32, u32, 32,
         intrinsics::i32_add_with_overflow,
         intrinsics::i32_sub_with_overflow,
         intrinsics::i32_mul_with_overflow }
@@ -639,7 +632,7 @@ impl i32 {
 
 #[lang = "i64"]
 impl i64 {
-    int_impl! { i64 = i64, u64, 64,
+    int_impl! { i64, u64, 64,
         intrinsics::i64_add_with_overflow,
         intrinsics::i64_sub_with_overflow,
         intrinsics::i64_mul_with_overflow }
@@ -648,7 +641,7 @@ impl i64 {
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { isize = i32, u32, 32,
+    int_impl! { i32, u32, 32,
         intrinsics::i32_add_with_overflow,
         intrinsics::i32_sub_with_overflow,
         intrinsics::i32_mul_with_overflow }
@@ -657,7 +650,7 @@ impl isize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { isize = i64, u64, 64,
+    int_impl! { i64, u64, 64,
         intrinsics::i64_add_with_overflow,
         intrinsics::i64_sub_with_overflow,
         intrinsics::i64_mul_with_overflow }
@@ -665,7 +658,7 @@ impl isize {
 
 // `Int` + `UnsignedInt` implemented for signed integers
 macro_rules! uint_impl {
-    ($T:ty = $ActualT:ty, $BITS:expr,
+    ($ActualT:ty, $BITS:expr,
      $ctpop:path,
      $ctlz:path,
      $cttz:path,
@@ -675,11 +668,11 @@ macro_rules! uint_impl {
      $mul_with_overflow:path) => {
         /// Returns the smallest value that can be represented by this integer type.
         #[stable(feature = "rust1", since = "1.0.0")]
-        pub fn min_value() -> $T { 0 }
+        pub fn min_value() -> Self { 0 }
 
         /// Returns the largest value that can be represented by this integer type.
         #[stable(feature = "rust1", since = "1.0.0")]
-        pub fn max_value() -> $T { !0 }
+        pub fn max_value() -> Self { !0 }
 
         /// Converts a string slice in a given base to an integer.
         ///
@@ -696,7 +689,7 @@ macro_rules! uint_impl {
         /// Otherwise, `Ok(n)` where `n` is the integer represented by `src`.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[allow(deprecated)]
-        pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> {
+        pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
             from_str_radix(src, radix)
         }
 
@@ -788,7 +781,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn rotate_left(self, n: u32) -> $T {
+        pub fn rotate_left(self, n: u32) -> Self {
             // Protect against undefined behaviour for over-long bit shifts
             let n = n % $BITS;
             (self << n) | (self >> (($BITS - n) % $BITS))
@@ -808,7 +801,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn rotate_right(self, n: u32) -> $T {
+        pub fn rotate_right(self, n: u32) -> Self {
             // Protect against undefined behaviour for over-long bit shifts
             let n = n % $BITS;
             (self >> n) | (self << (($BITS - n) % $BITS))
@@ -826,8 +819,8 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn swap_bytes(self) -> $T {
-            unsafe { $bswap(self as $ActualT) as $T }
+        pub fn swap_bytes(self) -> Self {
+            unsafe { $bswap(self as $ActualT) as Self }
         }
 
         /// Converts an integer from big endian to the target's endianness.
@@ -848,7 +841,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn from_be(x: $T) -> $T {
+        pub fn from_be(x: Self) -> Self {
             if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
         }
 
@@ -870,7 +863,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn from_le(x: $T) -> $T {
+        pub fn from_le(x: Self) -> Self {
             if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
         }
 
@@ -892,7 +885,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn to_be(self) -> $T { // or not to be?
+        pub fn to_be(self) -> Self { // or not to be?
             if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
         }
 
@@ -914,7 +907,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn to_le(self) -> $T {
+        pub fn to_le(self) -> Self {
             if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
         }
 
@@ -929,8 +922,8 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_add(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $add_with_overflow, self, other)
+        pub fn checked_add(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $add_with_overflow, self, other)
         }
 
         /// Checked integer subtraction. Computes `self - other`, returning
@@ -944,8 +937,8 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_sub(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $sub_with_overflow, self, other)
+        pub fn checked_sub(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $sub_with_overflow, self, other)
         }
 
         /// Checked integer multiplication. Computes `self * other`, returning
@@ -959,8 +952,8 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_mul(self, other: $T) -> Option<$T> {
-            checked_op!($T, $ActualT, $mul_with_overflow, self, other)
+        pub fn checked_mul(self, other: Self) -> Option<Self> {
+            checked_op!($ActualT, $mul_with_overflow, self, other)
         }
 
         /// Checked integer division. Computes `self / other`, returning `None`
@@ -975,7 +968,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_div(self, v: $T) -> Option<$T> {
+        pub fn checked_div(self, v: Self) -> Option<Self> {
             match v {
                 0 => None,
                 v => Some(self / v),
@@ -986,11 +979,11 @@ macro_rules! uint_impl {
         /// the numeric bounds instead of overflowing.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn saturating_add(self, other: $T) -> $T {
+        pub fn saturating_add(self, other: Self) -> Self {
             match self.checked_add(other) {
                 Some(x)                       => x,
-                None if other >= <$T as Zero>::zero() => <$T>::max_value(),
-                None => <$T>::min_value(),
+                None if other >= Self::zero() => Self::max_value(),
+                None => Self::min_value(),
             }
         }
 
@@ -998,11 +991,11 @@ macro_rules! uint_impl {
         /// at the numeric bounds instead of overflowing.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn saturating_sub(self, other: $T) -> $T {
+        pub fn saturating_sub(self, other: Self) -> Self {
             match self.checked_sub(other) {
                 Some(x)                       => x,
-                None if other >= <$T as Zero>::zero() => <$T>::min_value(),
-                None => <$T>::max_value(),
+                None if other >= Self::zero() => Self::min_value(),
+                None => Self::max_value(),
             }
         }
 
@@ -1010,7 +1003,7 @@ macro_rules! uint_impl {
         /// wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_add(self, rhs: $T) -> $T {
+        pub fn wrapping_add(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_add(self, rhs)
             }
@@ -1020,7 +1013,7 @@ macro_rules! uint_impl {
         /// wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_sub(self, rhs: $T) -> $T {
+        pub fn wrapping_sub(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_sub(self, rhs)
             }
@@ -1030,7 +1023,7 @@ macro_rules! uint_impl {
         /// other`, wrapping around at the boundary of the type.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn wrapping_mul(self, rhs: $T) -> $T {
+        pub fn wrapping_mul(self, rhs: Self) -> Self {
             unsafe {
                 intrinsics::overflowing_mul(self, rhs)
             }
@@ -1045,9 +1038,9 @@ macro_rules! uint_impl {
         /// to `-MIN`, a positive value that is too large to represent
         /// in the type. In such a case, this function returns `MIN`
         /// itself..
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_div(self, rhs: $T) -> $T {
+        pub fn wrapping_div(self, rhs: Self) -> Self {
             self.overflowing_div(rhs).0
         }
 
@@ -1058,9 +1051,9 @@ macro_rules! uint_impl {
         /// implementation artifacts make `x % y` illegal for `MIN /
         /// -1` on a signed type illegal (where `MIN` is the negative
         /// minimal value). In such a case, this function returns `0`.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_rem(self, rhs: $T) -> $T {
+        pub fn wrapping_rem(self, rhs: Self) -> Self {
             self.overflowing_rem(rhs).0
         }
 
@@ -1072,27 +1065,27 @@ macro_rules! uint_impl {
         /// negative minimal value for the type); this is a positive
         /// value that is too large to represent in the type. In such
         /// a case, this function returns `MIN` itself.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_neg(self) -> $T {
+        pub fn wrapping_neg(self) -> Self {
             self.overflowing_neg().0
         }
 
         /// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
         /// where `mask` removes any high-order bits of `rhs` that
         /// would cause the shift to exceed the bitwidth of the type.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_shl(self, rhs: u32) -> $T {
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
 
         /// Panic-free bitwise shift-left; yields `self >> mask(rhs)`,
         /// where `mask` removes any high-order bits of `rhs` that
         /// would cause the shift to exceed the bitwidth of the type.
-        #[unstable(feature = "core", since = "1.0.0")]
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
-        pub fn wrapping_shr(self, rhs: u32) -> $T {
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
 
@@ -1105,9 +1098,9 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn pow(self, mut exp: u32) -> $T {
+        pub fn pow(self, mut exp: u32) -> Self {
             let mut base = self;
-            let mut acc = <$T as One>::one();
+            let mut acc = Self::one();
 
             let mut prev_base = self;
             let mut base_oflo = false;
@@ -1135,17 +1128,17 @@ macro_rules! uint_impl {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn is_power_of_two(self) -> bool {
-            (self.wrapping_sub(<$T as One>::one())) & self == <$T as Zero>::zero() &&
-                !(self == <$T as Zero>::zero())
+            (self.wrapping_sub(Self::one())) & self == Self::zero() &&
+                !(self == Self::zero())
         }
 
         /// Returns the smallest power of two greater than or equal to `self`.
         /// Unspecified behavior on overflow.
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn next_power_of_two(self) -> $T {
-            let bits = size_of::<$T>() * 8;
-            let one: $T = <$T as One>::one();
+        pub fn next_power_of_two(self) -> Self {
+            let bits = size_of::<Self>() * 8;
+            let one: Self = Self::one();
             one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits)
         }
 
@@ -1153,7 +1146,7 @@ macro_rules! uint_impl {
         /// the next power of two is greater than the type's maximum value,
         /// `None` is returned, otherwise the power of two is wrapped in `Some`.
         #[stable(feature = "rust1", since = "1.0.0")]
-        pub fn checked_next_power_of_two(self) -> Option<$T> {
+        pub fn checked_next_power_of_two(self) -> Option<Self> {
             let npot = self.next_power_of_two();
             if npot >= self {
                 Some(npot)
@@ -1166,7 +1159,7 @@ macro_rules! uint_impl {
 
 #[lang = "u8"]
 impl u8 {
-    uint_impl! { u8 = u8, 8,
+    uint_impl! { u8, 8,
         intrinsics::ctpop8,
         intrinsics::ctlz8,
         intrinsics::cttz8,
@@ -1178,7 +1171,7 @@ impl u8 {
 
 #[lang = "u16"]
 impl u16 {
-    uint_impl! { u16 = u16, 16,
+    uint_impl! { u16, 16,
         intrinsics::ctpop16,
         intrinsics::ctlz16,
         intrinsics::cttz16,
@@ -1190,7 +1183,7 @@ impl u16 {
 
 #[lang = "u32"]
 impl u32 {
-    uint_impl! { u32 = u32, 32,
+    uint_impl! { u32, 32,
         intrinsics::ctpop32,
         intrinsics::ctlz32,
         intrinsics::cttz32,
@@ -1203,7 +1196,7 @@ impl u32 {
 
 #[lang = "u64"]
 impl u64 {
-    uint_impl! { u64 = u64, 64,
+    uint_impl! { u64, 64,
         intrinsics::ctpop64,
         intrinsics::ctlz64,
         intrinsics::cttz64,
@@ -1216,7 +1209,7 @@ impl u64 {
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { usize = u32, 32,
+    uint_impl! { u32, 32,
         intrinsics::ctpop32,
         intrinsics::ctlz32,
         intrinsics::cttz32,
@@ -1229,7 +1222,7 @@ impl usize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { usize = u64, 64,
+    uint_impl! { u64, 64,
         intrinsics::ctpop64,
         intrinsics::ctlz64,
         intrinsics::cttz64,
@@ -1266,6 +1259,8 @@ pub enum FpCategory {
 
 /// A built-in floating point number.
 #[doc(hidden)]
+#[unstable(feature = "core_float",
+           reason = "stable interface is via `impl f{32,64}` in later crates")]
 pub trait Float {
     /// Returns the NaN value.
     fn nan() -> Self;
@@ -1366,9 +1361,9 @@ pub trait Float {
 }
 
 macro_rules! from_str_float_impl {
-    ($T:ident) => {
+    ($t:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl FromStr for $T {
+        impl FromStr for $t {
             type Err = ParseFloatError;
 
             /// Converts a string in base 10 to a float.
@@ -1377,14 +1372,13 @@ macro_rules! from_str_float_impl {
             /// This function accepts strings such as
             ///
             /// * '3.14'
-            /// * '+3.14', equivalent to '3.14'
             /// * '-3.14'
             /// * '2.5E10', or equivalently, '2.5e10'
             /// * '2.5E-10'
             /// * '.' (understood as 0)
             /// * '5.'
             /// * '.5', or, equivalently,  '0.5'
-            /// * '+inf', 'inf', '-inf', 'NaN'
+            /// * 'inf', '-inf', 'NaN'
             ///
             /// Leading and trailing whitespace represent an error.
             ///
@@ -1399,8 +1393,8 @@ macro_rules! from_str_float_impl {
             /// number represented by `src`.
             #[inline]
             #[allow(deprecated)]
-            fn from_str(src: &str) -> Result<$T, ParseFloatError> {
-                $T::from_str_radix(src, 10)
+            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
+                Self::from_str_radix(src, 10)
             }
         }
     }
@@ -1409,12 +1403,12 @@ from_str_float_impl!(f32);
 from_str_float_impl!(f64);
 
 macro_rules! from_str_radix_int_impl {
-    ($($T:ident)*) => {$(
+    ($($t:ty)*) => {$(
         #[stable(feature = "rust1", since = "1.0.0")]
         #[allow(deprecated)]
-        impl FromStr for $T {
+        impl FromStr for $t {
             type Err = ParseIntError;
-            fn from_str(src: &str) -> Result<$T, ParseIntError> {
+            fn from_str(src: &str) -> Result<Self, ParseIntError> {
                 from_str_radix(src, 10)
             }
         }
@@ -1432,17 +1426,17 @@ trait FromStrRadixHelper: PartialOrd + Copy {
 }
 
 macro_rules! doit {
-    ($($t:ident)*) => ($(impl FromStrRadixHelper for $t {
-        fn min_value() -> Self { <$t>::min_value() }
-        fn from_u32(u: u32) -> Self { u as $t }
+    ($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
+        fn min_value() -> Self { Self::min_value() }
+        fn from_u32(u: u32) -> Self { u as Self }
         fn checked_mul(&self, other: u32) -> Option<Self> {
-            <$t>::checked_mul(*self, other as $t)
+            Self::checked_mul(*self, other as Self)
         }
         fn checked_sub(&self, other: u32) -> Option<Self> {
-            <$t>::checked_sub(*self, other as $t)
+            Self::checked_sub(*self, other as Self)
         }
         fn checked_add(&self, other: u32) -> Option<Self> {
-            <$t>::checked_add(*self, other as $t)
+            Self::checked_add(*self, other as Self)
         }
     })*)
 }
@@ -1516,8 +1510,11 @@ enum IntErrorKind {
 }
 
 impl ParseIntError {
-    #[unstable(feature = "core", reason = "available through Error trait")]
-    pub fn description(&self) -> &str {
+    #[unstable(feature = "int_error_internals",
+               reason = "available through Error trait and this method should \
+                         not be exposed publicly")]
+    #[doc(hidden)]
+    pub fn __description(&self) -> &str {
         match self.kind {
             IntErrorKind::Empty => "cannot parse integer from empty string",
             IntErrorKind::InvalidDigit => "invalid digit found in string",
@@ -1530,7 +1527,7 @@ impl ParseIntError {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for ParseIntError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.description().fmt(f)
+        self.__description().fmt(f)
     }
 }
 
@@ -1539,10 +1536,15 @@ impl fmt::Display for ParseIntError {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseFloatError {
     #[doc(hidden)]
+    #[unstable(feature = "float_error_internals",
+               reason = "should not be exposed publicly")]
     pub __kind: FloatErrorKind
 }
 
 #[derive(Debug, Clone, PartialEq)]
+#[unstable(feature = "float_error_internals",
+           reason = "should not be exposed publicly")]
+#[doc(hidden)]
 pub enum FloatErrorKind {
     Empty,
     Invalid,
index 867829507455035e7eabbf74fd394efca5102cb4..0719d7c17cc4e44fbf2a6b99ca74ba8b1fa52410 100644 (file)
 
 macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
-#[unstable(feature = "core")]
+#[unstable(feature = "num_bits_bytes",
+           reason = "may want to be an associated function")]
 pub const BITS : usize = $bits;
-#[unstable(feature = "core")]
+#[unstable(feature = "num_bits_bytes",
+           reason = "may want to be an associated function")]
 pub const BYTES : usize = ($bits / 8);
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 602ef4fe45e734e0f1a931a2a50c98ce98e0511a..6fd23425e4d897476b53c73ec3a5ea7b3f360f04 100644 (file)
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 //! Operations and constants for pointer-sized unsigned integers (`usize` type)
-//!
-//! This type was recently added to replace `uint`. The rollout of the
-//! new type will gradually take place over the alpha cycle along with
-//! the development of clearer conventions around integer types.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
index 69c2222949032212c33ad9a506debed9a5161d76..748ed29e3a30682e0c39d0863f166d46acda2c91 100644 (file)
@@ -10,6 +10,7 @@
 
 #![allow(missing_docs)]
 #![allow(deprecated)]
+#![unstable(feature = "wrapping", reason = "may be removed or relocated")]
 
 use super::Wrapping;
 
@@ -30,7 +31,6 @@ use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
 
 use ::{i8,i16,i32,i64};
 
-#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
 pub trait OverflowingOps {
     fn overflowing_add(self, rhs: Self) -> (Self, bool);
     fn overflowing_sub(self, rhs: Self) -> (Self, bool);
index f16614cfd092d41df7269fc7f6a6cbcaf4a7ab26..48b1cbeef4fddd95d401d652b114caa233b54617 100644 (file)
@@ -29,8 +29,8 @@
 //!
 //! # Examples
 //!
-//! This example creates a `Point` struct that implements `Add` and `Sub`, and then
-//! demonstrates adding and subtracting two `Point`s.
+//! This example creates a `Point` struct that implements `Add` and `Sub`, and
+//! then demonstrates adding and subtracting two `Point`s.
 //!
 //! ```rust
 //! use std::ops::{Add, Sub};
 //! }
 //! ```
 //!
-//! See the documentation for each trait for a minimum implementation that prints
-//! something to the screen.
+//! See the documentation for each trait for a minimum implementation that
+//! prints something to the screen.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use marker::Sized;
+use marker::{Sized, Unsize};
 use fmt;
 
-#[cfg(not(stage0))]
-use marker::Unsize;
-
-/// The `Drop` trait is used to run some code when a value goes out of scope. This
-/// is sometimes called a 'destructor'.
+/// The `Drop` trait is used to run some code when a value goes out of scope.
+/// This is sometimes called a 'destructor'.
 ///
 /// # Examples
 ///
-/// A trivial implementation of `Drop`. The `drop` method is called when `_x` goes
-/// out of scope, and therefore `main` prints `Dropping!`.
+/// A trivial implementation of `Drop`. The `drop` method is called when `_x`
+/// goes out of scope, and therefore `main` prints `Dropping!`.
 ///
 /// ```
 /// struct HasDrop;
@@ -106,8 +103,7 @@ pub trait Drop {
 // based on "op T" where T is expected to be `Copy`able
 macro_rules! forward_ref_unop {
     (impl $imp:ident, $method:ident for $t:ty) => {
-        #[unstable(feature = "core",
-                   reason = "recently added, waiting for dust to settle")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> $imp for &'a $t {
             type Output = <$t as $imp>::Output;
 
@@ -123,8 +119,7 @@ macro_rules! forward_ref_unop {
 // based on "T op U" where T and U are expected to be `Copy`able
 macro_rules! forward_ref_binop {
     (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
-        #[unstable(feature = "core",
-                   reason = "recently added, waiting for dust to settle")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> $imp<$u> for &'a $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -134,8 +129,7 @@ macro_rules! forward_ref_binop {
             }
         }
 
-        #[unstable(feature = "core",
-                   reason = "recently added, waiting for dust to settle")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> $imp<&'a $u> for $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -145,8 +139,7 @@ macro_rules! forward_ref_binop {
             }
         }
 
-        #[unstable(feature = "core",
-                   reason = "recently added, waiting for dust to settle")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, 'b> $imp<&'a $u> for &'b $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -1213,40 +1206,30 @@ mod impls {
 
 /// Trait that indicates that this is a pointer or a wrapper for one,
 /// where unsizing can be performed on the pointee.
-#[unstable(feature = "core")]
-#[cfg(not(stage0))]
+#[unstable(feature = "coerce_unsized")]
 #[lang="coerce_unsized"]
 pub trait CoerceUnsized<T> {
     // Empty.
 }
 
 // &mut T -> &mut U
-#[cfg(not(stage0))]
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
 // &mut T -> &U
-#[cfg(not(stage0))]
 impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
 // &mut T -> *mut U
-#[cfg(not(stage0))]
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
 // &mut T -> *const U
-#[cfg(not(stage0))]
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
 
 // &T -> &U
-#[cfg(not(stage0))]
 impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
 // &T -> *const U
-#[cfg(not(stage0))]
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
 
 // *mut T -> *mut U
-#[cfg(not(stage0))]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
 // *mut T -> *const U
-#[cfg(not(stage0))]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
 
 // *const T -> *const U
-#[cfg(not(stage0))]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
index 8da28094be3aed3c007bd1469f45949cd80a05c7..c5203c5111b64ab5e3ab7fa306eca86b12062ccd 100644 (file)
 //! // but to start with we've just got `None`.
 //! let mut name_of_biggest_animal = None;
 //! let mut size_of_biggest_animal = 0;
-//! for big_thing in all_the_big_things.iter() {
+//! for big_thing in &all_the_big_things {
 //!     match *big_thing {
 //!         Kingdom::Animal(size, name) if size > size_of_biggest_animal => {
 //!             // Now we've found the name of some big animal
@@ -274,7 +274,7 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
+    /// # #![feature(as_slice)]
     /// let mut x = Some("Diamonds");
     /// {
     ///     let v = x.as_mut_slice();
@@ -285,7 +285,7 @@ impl<T> Option<T> {
     /// assert_eq!(x, Some("Dirt"));
     /// ```
     #[inline]
-    #[unstable(feature = "core",
+    #[unstable(feature = "as_slice",
                reason = "waiting for mut conventions")]
     pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
         match *self {
@@ -320,7 +320,7 @@ impl<T> Option<T> {
     ///
     /// ```{.should_panic}
     /// let x: Option<&str> = None;
-    /// x.expect("the world is ending"); // panics with `world is ending`
+    /// x.expect("the world is ending"); // panics with `the world is ending`
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -409,9 +409,11 @@ impl<T> Option<T> {
     /// Convert an `Option<String>` into an `Option<usize>`, consuming the original:
     ///
     /// ```
-    /// let num_as_str: Option<String> = Some("10".to_string());
-    /// // `Option::map` takes self *by value*, consuming `num_as_str`
-    /// let num_as_int: Option<usize> = num_as_str.map(|n| n.len());
+    /// let maybe_some_string = Some(String::from("Hello, World!"));
+    /// // `Option::map` takes self *by value*, consuming `maybe_some_string`
+    /// let maybe_some_len = maybe_some_string.map(|s| s.len());
+    ///
+    /// assert_eq!(maybe_some_len, Some(13));
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -422,7 +424,8 @@ impl<T> Option<T> {
         }
     }
 
-    /// Applies a function to the contained value or returns a default.
+    /// Applies a function to the contained value (if any),
+    /// or returns a `default` (if not).
     ///
     /// # Examples
     ///
@@ -435,14 +438,15 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
+    pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
         match self {
             Some(t) => f(t),
-            None => def
+            None => default,
         }
     }
 
-    /// Applies a function to the contained value or computes a default.
+    /// Applies a function to the contained value (if any),
+    /// or computes a `default` (if not).
     ///
     /// # Examples
     ///
@@ -457,10 +461,10 @@ impl<T> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -> U {
+    pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
         match self {
             Some(t) => f(t),
-            None => def()
+            None => default()
         }
     }
 
@@ -470,7 +474,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// let x = Some("foo");
     /// assert_eq!(x.ok_or(0), Ok("foo"));
     ///
@@ -492,7 +495,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// let x = Some("foo");
     /// assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
     ///
@@ -534,7 +536,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
     /// let mut x = Some(4);
     /// match x.iter_mut().next() {
     ///     Some(&mut ref mut v) => *v = 42,
@@ -864,6 +865,7 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
 impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
 
 /// An iterator over the item contained inside an Option.
+#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<A> { inner: Item<A> }
 
index 635150c088688f3c98b5a17aea9c1f6694787e92..8133db097dfcf9c8b8ded1d4011cb6c525fa82cd 100644 (file)
@@ -29,6 +29,9 @@
 //! library, but the location of this may change over time.
 
 #![allow(dead_code, missing_docs)]
+#![unstable(feature = "core_panic",
+            reason = "internal details of the implementation of the `panic!` \
+                      and related macros")]
 
 use fmt;
 
index a4d529ad47d09036fe32366fd9bd3150db89f4a6..ac153d64ab28ffbbeb0a37a843ab3a6d1d76b36f 100644 (file)
 //! use core::prelude::*;
 //! ```
 
+#![unstable(feature = "core_prelude",
+            reason = "the libcore prelude has not been scrutinized and \
+                      stabilized yet")]
+
 // Reexported core operators
 pub use marker::{Copy, Send, Sized, Sync};
 pub use ops::{Drop, Fn, FnMut, FnOnce};
@@ -32,7 +36,6 @@ pub use ops::{Drop, Fn, FnMut, FnOnce};
 pub use mem::drop;
 
 // Reexported types and traits
-
 pub use char::CharExt;
 pub use clone::Clone;
 pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
index 47c029f11b38fad65971f9822d532aae935a161b..f2792a525d66b311f3fcdde63fe71af580b2642e 100644 (file)
 
 // FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory
 
-//! Operations on unsafe pointers, `*const T`, and `*mut T`.
+//! Operations on raw pointers, `*const T`, and `*mut T`.
 //!
-//! Working with unsafe pointers in Rust is uncommon,
+//! Working with raw pointers in Rust is uncommon,
 //! typically limited to a few patterns.
 //!
 //! Use the `null` function to create null pointers, and the `is_null` method
 //! of the `*const T` type  to check for null. The `*const T` type also defines
 //! the `offset` method, for pointer math.
 //!
-//! # Common ways to create unsafe pointers
+//! # Common ways to create raw pointers
 //!
 //! ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
 //!
@@ -49,7 +49,7 @@
 //! the raw pointer. It doesn't destroy `T` or deallocate any memory.
 //!
 //! ```
-//! # #![feature(alloc)]
+//! # #![feature(box_raw)]
 //! use std::boxed;
 //!
 //! unsafe {
@@ -86,7 +86,7 @@
 //!
 //! Usually you wouldn't literally use `malloc` and `free` from Rust,
 //! but C APIs hand out a lot of pointers generally, so are a common source
-//! of unsafe pointers in Rust.
+//! of raw pointers in Rust.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "pointer")]
@@ -204,7 +204,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
 ///
 /// This is unsafe for the same reasons that `read` is unsafe.
 #[inline(always)]
-#[unstable(feature = "core",
+#[unstable(feature = "read_and_zero",
            reason = "may play a larger role in std::ptr future extensions")]
 pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     // Copy the data out from `dest`:
@@ -219,7 +219,7 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
 /// Variant of read_and_zero that writes the specific drop-flag byte
 /// (which may be more appropriate than zero).
 #[inline(always)]
-#[unstable(feature = "core",
+#[unstable(feature = "filling_drop",
            reason = "may play a larger role in std::ptr future extensions")]
 pub unsafe fn read_and_drop<T>(dest: *mut T) -> T {
     // Copy the data out from `dest`:
@@ -267,9 +267,10 @@ impl<T: ?Sized> *const T {
     /// null-safety, it is important to note that this is still an unsafe
     /// operation because the returned value could be pointing to invalid
     /// memory.
-    #[unstable(feature = "core",
-               reason = "Option is not clearly the right return type, and we may want \
-                         to tie the return lifetime to a borrow of the raw pointer")]
+    #[unstable(feature = "ptr_as_ref",
+               reason = "Option is not clearly the right return type, and we \
+                         may want to tie the return lifetime to a borrow of \
+                         the raw pointer")]
     #[inline]
     pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized {
         if self.is_null() {
@@ -314,9 +315,10 @@ impl<T: ?Sized> *mut T {
     /// null-safety, it is important to note that this is still an unsafe
     /// operation because the returned value could be pointing to invalid
     /// memory.
-    #[unstable(feature = "core",
-               reason = "Option is not clearly the right return type, and we may want \
-                         to tie the return lifetime to a borrow of the raw pointer")]
+    #[unstable(feature = "ptr_as_ref",
+               reason = "Option is not clearly the right return type, and we \
+                         may want to tie the return lifetime to a borrow of \
+                         the raw pointer")]
     #[inline]
     pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized {
         if self.is_null() {
@@ -347,7 +349,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// As with `as_ref`, this is unsafe because it cannot verify the validity
     /// of the returned pointer.
-    #[unstable(feature = "core",
+    #[unstable(feature = "ptr_as_ref",
                reason = "return value does not necessarily convey all possible \
                          information")]
     #[inline]
@@ -507,9 +509,14 @@ impl<T: ?Sized> PartialOrd for *mut T {
 /// modified without a unique path to the `Unique` reference. Useful
 /// for building abstractions like `Vec<T>` or `Box<T>`, which
 /// internally use raw pointers to manage the memory that they own.
-#[unstable(feature = "unique")]
+#[unstable(feature = "unique", reason = "needs an RFC to flesh out design")]
 pub struct Unique<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>,
 }
 
@@ -527,21 +534,19 @@ unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 #[unstable(feature = "unique")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
+#[unstable(feature = "unique")]
 impl<T: ?Sized> Unique<T> {
     /// Creates a new `Unique`.
-    #[unstable(feature = "unique")]
     pub unsafe fn new(ptr: *mut T) -> Unique<T> {
         Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
 
     /// Dereferences the content.
-    #[unstable(feature = "unique")]
     pub unsafe fn get(&self) -> &T {
         &**self.pointer
     }
 
     /// Mutably dereferences the content.
-    #[unstable(feature = "unique")]
     pub unsafe fn get_mut(&mut self) -> &mut T {
         &mut ***self
     }
index ec84ef7986a43b8b8c327954174c566ee6a90548..43535ddd1d5c5f7ff9b27d7bb8d91919e805e4b5 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![allow(missing_docs)]
-#![unstable(feature = "core")]
+#![unstable(feature = "raw")]
 
 //! Contains struct definitions for the layout of compiler built-in types.
 //!
@@ -49,7 +49,7 @@ use mem;
 /// # Examples
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(raw)]
 /// use std::raw::{self, Repr};
 ///
 /// let slice: &[u16] = &[1, 2, 3, 4];
@@ -98,7 +98,7 @@ impl<T> Clone for Slice<T> {
 /// # Examples
 ///
 /// ```
-/// # #![feature(core)]
+/// # #![feature(raw)]
 /// use std::mem;
 /// use std::raw;
 ///
index e909946ece40221ffa548666aed832ce44b2e9fd..d87c1020dcc2f99e58e9ec0d4de3649e2a7744bf 100644 (file)
 //! }
 //! ```
 //!
-//! `try!` is imported by the prelude, and is available everywhere.
+//! `try!` is imported by the prelude and is available everywhere, but it can only
+//! be used in functions that return `Result` because of the early return of
+//! `Err` that it provides.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -418,7 +420,7 @@ impl<T, E> Result<T, E> {
     /// Converts from `Result<T, E>` to `&mut [T]` (without copying)
     ///
     /// ```
-    /// # #![feature(core)]
+    /// # #![feature(as_slice)]
     /// let mut x: Result<&str, u32> = Ok("Gold");
     /// {
     ///     let v = x.as_mut_slice();
@@ -432,7 +434,7 @@ impl<T, E> Result<T, E> {
     /// assert!(x.as_mut_slice().is_empty());
     /// ```
     #[inline]
-    #[unstable(feature = "core",
+    #[unstable(feature = "as_slice",
                reason = "waiting for mut conventions")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         match *self {
@@ -729,6 +731,26 @@ impl<T, E: fmt::Debug> Result<T, E> {
                 panic!("called `Result::unwrap()` on an `Err` value: {:?}", e)
         }
     }
+
+    /// Unwraps a result, yielding the content of an `Ok`.
+    ///
+    /// Panics if the value is an `Err`, with a panic message including the
+    /// passed message, and the content of the `Err`.
+    ///
+    /// # Examples
+    /// ```{.should_panic}
+    /// #![feature(result_expect)]
+    /// let x: Result<u32, &str> = Err("emergency failure");
+    /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_expect", reason = "newly introduced")]
+    pub fn expect(self, msg: &str) -> T {
+        match self {
+            Ok(t) => t,
+            Err(e) => panic!("{}: {:?}", msg, e),
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -944,7 +966,11 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
 /// If an `Err` is encountered, it is immediately returned.
 /// Otherwise, the folded value is returned.
 #[inline]
-#[unstable(feature = "core")]
+#[unstable(feature = "result_fold",
+           reason = "unclear if this function should exist")]
+#[deprecated(since = "1.2.0",
+             reason = "has not seen enough usage to justify its position in \
+                       the standard library")]
 pub fn fold<T,
             V,
             E,
index 7b55ba49a07f779e83766b417cc4b35861dbdafb..7ecd08bea3574fc192b3d9d2811b39e2922d264a 100644 (file)
@@ -19,7 +19,7 @@
 //! provided beyond this module.
 //!
 //! ```rust
-//! # #![feature(core)]
+//! # #![feature(core_simd)]
 //! fn main() {
 //!     use std::simd::f32x4;
 //!     let a = f32x4(40.0, 41.0, 42.0, 43.0);
 //! These are all experimental. The interface may change entirely, without
 //! warning.
 
+#![unstable(feature = "core_simd",
+            reason = "needs an RFC to flesh out the design")]
+
 #![allow(non_camel_case_types)]
 #![allow(missing_docs)]
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
@@ -45,26 +47,22 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
                  pub i8, pub i8, pub i8, pub i8,
                  pub i8, pub i8, pub i8, pub i8);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
                  pub i16, pub i16, pub i16, pub i16);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i64x2(pub i64, pub i64);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
@@ -73,32 +71,27 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
                  pub u8, pub u8, pub u8, pub u8,
                  pub u8, pub u8, pub u8, pub u8);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
                  pub u16, pub u16, pub u16, pub u16);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u64x2(pub u64, pub u64);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
 
-#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
index 546e0bc806e12cab0f5376786782409b755152ff..a8c995f37cce44cb84bcb5bf86bfeff447d159cc 100644 (file)
@@ -64,6 +64,8 @@ use raw::Slice as RawSlice;
 /// Extension methods for slices.
 #[allow(missing_docs)] // docs in libcollections
 #[doc(hidden)]
+#[unstable(feature = "core_slice_ext",
+           reason = "stable interface provided by `impl [T]` in later crates")]
 pub trait SliceExt {
     type Item;
 
@@ -124,7 +126,30 @@ pub trait SliceExt {
     fn clone_from_slice(&mut self, &[Self::Item]) -> usize where Self::Item: Clone;
 }
 
-#[unstable(feature = "core")]
+// Use macros to be generic over const/mut
+macro_rules! slice_offset {
+    ($ptr:expr, $by:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            ::intrinsics::arith_offset(ptr as *mut i8, $by) as *mut _
+        } else {
+            ptr.offset($by)
+        }
+    }};
+}
+
+macro_rules! slice_ref {
+    ($ptr:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            // Use a non-null pointer value
+            &mut *(1 as *mut _)
+        } else {
+            transmute(ptr)
+        }
+    }};
+}
+
 impl<T> SliceExt for [T] {
     type Item = T;
 
@@ -136,16 +161,18 @@ impl<T> SliceExt for [T] {
     #[inline]
     fn iter<'a>(&'a self) -> Iter<'a, T> {
         unsafe {
-            let p = self.as_ptr();
-            assume(!p.is_null());
-            if mem::size_of::<T>() == 0 {
-                Iter {ptr: p,
-                      end: ((p as usize).wrapping_add(self.len())) as *const T,
-                      _marker: marker::PhantomData}
+            let p = if mem::size_of::<T>() == 0 {
+                1 as *const _
             } else {
-                Iter {ptr: p,
-                      end: p.offset(self.len() as isize),
-                      _marker: marker::PhantomData}
+                let p = self.as_ptr();
+                assume(!p.is_null());
+                p
+            };
+
+            Iter {
+                ptr: p,
+                end: slice_offset!(p, self.len() as isize),
+                _marker: marker::PhantomData
             }
         }
     }
@@ -230,7 +257,6 @@ impl<T> SliceExt for [T] {
         self.repr().data
     }
 
-    #[unstable(feature = "core")]
     fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize> where
         F: FnMut(&T) -> Ordering
     {
@@ -273,16 +299,18 @@ impl<T> SliceExt for [T] {
     #[inline]
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
         unsafe {
-            let p = self.as_mut_ptr();
-            assume(!p.is_null());
-            if mem::size_of::<T>() == 0 {
-                IterMut {ptr: p,
-                         end: ((p as usize).wrapping_add(self.len())) as *mut T,
-                         _marker: marker::PhantomData}
+            let p = if mem::size_of::<T>() == 0 {
+                1 as *mut _
             } else {
-                IterMut {ptr: p,
-                         end: p.offset(self.len() as isize),
-                         _marker: marker::PhantomData}
+                let p = self.as_mut_ptr();
+                assume(!p.is_null());
+                p
+            };
+
+            IterMut {
+                ptr: p,
+                end: slice_offset!(p, self.len() as isize),
+                _marker: marker::PhantomData
             }
         }
     }
@@ -409,12 +437,10 @@ impl<T> SliceExt for [T] {
         m >= n && needle == &self[m-n..]
     }
 
-    #[unstable(feature = "core")]
     fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord {
         self.binary_search_by(|p| p.cmp(x))
     }
 
-    #[unstable(feature = "core")]
     fn next_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
@@ -445,7 +471,6 @@ impl<T> SliceExt for [T] {
         true
     }
 
-    #[unstable(feature = "core")]
     fn prev_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
@@ -630,31 +655,6 @@ fn size_from_ptr<T>(_: *const T) -> usize {
     mem::size_of::<T>()
 }
 
-
-// Use macros to be generic over const/mut
-macro_rules! slice_offset {
-    ($ptr:expr, $by:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            transmute((ptr as isize).wrapping_add($by))
-        } else {
-            ptr.offset($by)
-        }
-    }};
-}
-
-macro_rules! slice_ref {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &mut *(1 as *mut _)
-        } else {
-            transmute(ptr)
-        }
-    }};
-}
-
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
@@ -771,7 +771,7 @@ impl<'a, T> Iter<'a, T> {
     ///
     /// This has the same lifetime as the original slice, and so the
     /// iterator can continue to be used while this exists.
-    #[unstable(feature = "core")]
+    #[unstable(feature = "iter_to_slice")]
     pub fn as_slice(&self) -> &'a [T] {
         make_slice!(self.ptr, self.end)
     }
@@ -781,7 +781,7 @@ impl<'a, T> Iter<'a, T> {
         match self.as_slice().get(n) {
             Some(elem_ref) => unsafe {
                 self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(slice_ref!(elem_ref))
+                Some(elem_ref)
             },
             None => {
                 self.ptr = self.end;
@@ -801,7 +801,8 @@ impl<'a, T> Clone for Iter<'a, T> {
     fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
 }
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, T> RandomAccessIterator for Iter<'a, T> {
     #[inline]
     fn indexable(&self) -> usize {
@@ -839,7 +840,7 @@ impl<'a, T> IterMut<'a, T> {
     /// to consume the iterator. Consider using the `Slice` and
     /// `SliceMut` implementations for obtaining slices with more
     /// restricted lifetimes that do not consume the iterator.
-    #[unstable(feature = "core")]
+    #[unstable(feature = "iter_to_slice")]
     pub fn into_slice(self) -> &'a mut [T] {
         make_mut_slice!(self.ptr, self.end)
     }
@@ -849,7 +850,7 @@ impl<'a, T> IterMut<'a, T> {
         match make_mut_slice!(self.ptr, self.end).get_mut(n) {
             Some(elem_ref) => unsafe {
                 self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(slice_ref!(elem_ref))
+                Some(elem_ref)
             },
             None => {
                 self.ptr = self.end;
@@ -1173,7 +1174,8 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, T> RandomAccessIterator for Windows<'a, T> {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1260,7 +1262,8 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
 
-#[unstable(feature = "core", reason = "trait is experimental")]
+#[unstable(feature = "iter_idx", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, T> RandomAccessIterator for Chunks<'a, T> {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1346,7 +1349,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
 //
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable(feature = "core")]
+#[unstable(feature = "ref_slice")]
 pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
     unsafe {
         from_raw_parts(s, 1)
@@ -1354,7 +1357,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
 }
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable(feature = "core")]
+#[unstable(feature = "ref_slice")]
 pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
     unsafe {
         from_raw_parts_mut(s, 1)
@@ -1412,7 +1415,7 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
 //
 
 /// Operations on `[u8]`.
-#[unstable(feature = "core", reason = "needs review")]
+#[unstable(feature = "slice_bytes", reason = "needs review")]
 pub mod bytes {
     use ptr;
     use slice::SliceExt;
@@ -1500,7 +1503,11 @@ impl<T: PartialOrd> PartialOrd for [T] {
 }
 
 /// Extension methods for slices containing integers.
-#[unstable(feature = "core")]
+#[unstable(feature = "int_slice")]
+#[deprecated(since = "1.2.0",
+             reason = "has not seen much usage and may want to live in the \
+                       standard library now that most slice methods are \
+                       on an inherent implementation block")]
 pub trait IntSliceExt<U, S> {
     /// Converts the slice to an immutable slice of unsigned integers with the same width.
     fn as_unsigned<'a>(&'a self) -> &'a [U];
@@ -1515,7 +1522,8 @@ pub trait IntSliceExt<U, S> {
 
 macro_rules! impl_int_slice {
     ($u:ty, $s:ty, $t:ty) => {
-        #[unstable(feature = "core")]
+        #[unstable(feature = "int_slice")]
+        #[allow(deprecated)]
         impl IntSliceExt<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } }
index 11ca6e332b5713da5c204c7cd65755269aaab7b0..5a621176c4a812b45976d9744964f2ea31eeab62 100644 (file)
@@ -13,6 +13,7 @@
 //! For more details, see std::str
 
 #![doc(primitive = "str")]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::OldSearcher::{TwoWay, TwoWayLong};
 use self::pattern::Pattern;
@@ -191,7 +192,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
 
 /// Reads the next code point out of a byte iterator (assuming a
 /// UTF-8-like encoding).
-#[unstable(feature = "core")]
+#[unstable(feature = "str_internals")]
 #[inline]
 pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     // Decode UTF-8
@@ -226,9 +227,8 @@ pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
 
 /// Reads the last code point out of a byte iterator (assuming a
 /// UTF-8-like encoding).
-#[unstable(feature = "core")]
 #[inline]
-pub fn next_code_point_reverse(bytes: &mut slice::Iter<u8>) -> Option<u32> {
+fn next_code_point_reverse(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     // Decode UTF-8
     let w = match bytes.next_back() {
         None => return None,
@@ -638,10 +638,10 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split()`.
+        #[doc="Created with the method `.split()`."]
         struct Split;
     reverse:
-        /// Created with the method `.rsplit()`.
+        #[doc="Created with the method `.rsplit()`."]
         struct RSplit;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -652,10 +652,10 @@ generate_pattern_iterators! {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split_terminator()`.
+        #[doc="Created with the method `.split_terminator()`."]
         struct SplitTerminator;
     reverse:
-        /// Created with the method `.rsplit_terminator()`.
+        #[doc="Created with the method `.rsplit_terminator()`."]
         struct RSplitTerminator;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -698,10 +698,10 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.splitn()`.
+        #[doc="Created with the method `.splitn()`."]
         struct SplitN;
     reverse:
-        /// Created with the method `.rsplitn()`.
+        #[doc="Created with the method `.rsplitn()`."]
         struct RSplitN;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -732,13 +732,13 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.match_indices()`.
+        #[doc="Created with the method `.match_indices()`."]
         struct MatchIndices;
     reverse:
-        /// Created with the method `.rmatch_indices()`.
+        #[doc="Created with the method `.rmatch_indices()`."]
         struct RMatchIndices;
     stability:
-        #[unstable(feature = "core",
+        #[unstable(feature = "str_match_indices",
                    reason = "type may be removed or have its iterator impl changed")]
     internal:
         MatchIndicesInternal yielding ((usize, usize));
@@ -773,13 +773,13 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.matches()`.
+        #[doc="Created with the method `.matches()`."]
         struct Matches;
     reverse:
-        /// Created with the method `.rmatches()`.
+        #[doc="Created with the method `.rmatches()`."]
         struct RMatches;
     stability:
-        #[unstable(feature = "core", reason = "type got recently added")]
+        #[stable(feature = "str_matches", since = "1.2.0")]
     internal:
         MatchesInternal yielding (&'a str);
     delegate double ended;
@@ -1470,6 +1470,8 @@ mod traits {
 /// Methods for string slices
 #[allow(missing_docs)]
 #[doc(hidden)]
+#[unstable(feature = "core_str_ext",
+           reason = "stable interface provided by `impl str` in later crates")]
 pub trait StrExt {
     // NB there are no docs here are they're all located on the StrExt trait in
     // libcollections, not here.
@@ -1517,6 +1519,7 @@ pub trait StrExt {
     fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
         where P::Searcher: ReverseSearcher<'a>;
     fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
+    fn split_at(&self, mid: usize) -> (&str, &str);
     fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
     fn subslice_offset(&self, inner: &str) -> usize;
     fn as_ptr(&self) -> *const u8;
@@ -1809,6 +1812,18 @@ impl StrExt for str {
         self.find(pat)
     }
 
+    fn split_at(&self, mid: usize) -> (&str, &str) {
+        // is_char_boundary checks that the index is in [0, .len()]
+        if self.is_char_boundary(mid) {
+            unsafe {
+                (self.slice_unchecked(0, mid),
+                 self.slice_unchecked(mid, self.len()))
+            }
+        } else {
+            slice_error_fail(self, 0, mid)
+        }
+    }
+
     #[inline]
     fn slice_shift_char(&self) -> Option<(char, &str)> {
         if self.is_empty() {
@@ -1857,8 +1872,7 @@ impl AsRef<[u8]> for str {
 /// Pluck a code point out of a UTF-8-like byte slice and return the
 /// index of the next code point.
 #[inline]
-#[unstable(feature = "core")]
-pub fn char_range_at_raw(bytes: &[u8], i: usize) -> (u32, usize) {
+fn char_range_at_raw(bytes: &[u8], i: usize) -> (u32, usize) {
     if bytes[i] < 128 {
         return (bytes[i] as u32, i + 1);
     }
index 9a96612195cf8f01c02e347203fc16ae611880ad..8bdbab55211d8cce2dc735d1d3fd670450098d15 100644 (file)
@@ -13,6 +13,9 @@
 //! For more details, see the traits `Pattern`, `Searcher`,
 //! `ReverseSearcher` and `DoubleEndedSearcher`.
 
+#![unstable(feature = "pattern",
+            reason = "API not fully fleshed out and ready to be stabilized")]
+
 use prelude::*;
 
 // Pattern
diff --git a/src/libcore/ty.rs b/src/libcore/ty.rs
deleted file mode 100644 (file)
index 35c1cb0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Types dealing with unsafe actions.
-
-use marker;
index 8e3c7f4595a48cafe2865ecbdafbf6b389b2c461..c50f18c235233ff57dfd2e5b897c657b7dbd7412 100644 (file)
@@ -70,13 +70,15 @@ fn int_xor() {
     assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
 }
 
-static S_BOOL : AtomicBool = ATOMIC_BOOL_INIT;
-static S_INT  : AtomicIsize  = ATOMIC_ISIZE_INIT;
-static S_UINT : AtomicUsize = ATOMIC_USIZE_INIT;
+static S_FALSE: AtomicBool = AtomicBool::new(false);
+static S_TRUE: AtomicBool = AtomicBool::new(true);
+static S_INT: AtomicIsize  = AtomicIsize::new(0);
+static S_UINT: AtomicUsize = AtomicUsize::new(0);
 
 #[test]
 fn static_init() {
-    assert!(!S_BOOL.load(SeqCst));
+    assert!(!S_FALSE.load(SeqCst));
+    assert!(S_TRUE.load(SeqCst));
     assert!(S_INT.load(SeqCst) == 0);
     assert!(S_UINT.load(SeqCst) == 0);
 }
index f02312b8641e118f7ec3d7b20cb228067732690c..20740a5e2cebc91dc3649cbf6a2c60536c4efe2e 100644 (file)
@@ -115,13 +115,13 @@ fn discard_doesnt_unborrow() {
 }
 
 #[test]
-fn clone_ref_updates_flag() {
+fn ref_clone_updates_flag() {
     let x = RefCell::new(0);
     {
         let b1 = x.borrow();
         assert_eq!(x.borrow_state(), BorrowState::Reading);
         {
-            let _b2 = clone_ref(&b1);
+            let _b2 = Ref::clone(&b1);
             assert_eq!(x.borrow_state(), BorrowState::Reading);
         }
         assert_eq!(x.borrow_state(), BorrowState::Reading);
@@ -129,6 +129,82 @@ fn clone_ref_updates_flag() {
     assert_eq!(x.borrow_state(), BorrowState::Unused);
 }
 
+#[test]
+fn ref_map_does_not_update_flag() {
+    let x = RefCell::new(Some(5));
+    {
+        let b1: Ref<Option<u32>> = x.borrow();
+        assert_eq!(x.borrow_state(), BorrowState::Reading);
+        {
+            let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
+            assert_eq!(*b2, 5);
+            assert_eq!(x.borrow_state(), BorrowState::Reading);
+        }
+        assert_eq!(x.borrow_state(), BorrowState::Unused);
+    }
+    assert_eq!(x.borrow_state(), BorrowState::Unused);
+}
+
+#[test]
+fn ref_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> Ref<u32> {
+            Ref::map(self.0.borrow(), |tuple| &tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    let d: Ref<u32> = x.accessor();
+    assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_filter_map_accessor() {
+    struct X(RefCell<Result<u32, ()>>);
+    impl X {
+        fn accessor(&self) -> Option<Ref<u32>> {
+            Ref::filter_map(self.0.borrow(), |r| r.as_ref().ok())
+        }
+    }
+    let x = X(RefCell::new(Ok(7)));
+    let d: Ref<u32> = x.accessor().unwrap();
+    assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_mut_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> RefMut<u32> {
+            RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    {
+        let mut d: RefMut<u32> = x.accessor();
+        assert_eq!(*d, 7);
+        *d += 1;
+    }
+    assert_eq!(*x.0.borrow(), (8, 'z'));
+}
+
+#[test]
+fn ref_mut_filter_map_accessor() {
+    struct X(RefCell<Result<u32, ()>>);
+    impl X {
+        fn accessor(&self) -> Option<RefMut<u32>> {
+            RefMut::filter_map(self.0.borrow_mut(), |r| r.as_mut().ok())
+        }
+    }
+    let x = X(RefCell::new(Ok(7)));
+    {
+        let mut d: RefMut<u32> = x.accessor().unwrap();
+        assert_eq!(*d, 7);
+        *d += 1;
+    }
+    assert_eq!(*x.0.borrow(), Ok(8));
+}
+
 #[test]
 fn as_unsafe_cell() {
     let c1: Cell<usize> = Cell::new(0);
index b73807aa317588a7500309bc87b2d8912990875a..1506982586a00a55f819084d2e9f6b5a33b8e849 100644 (file)
@@ -58,6 +58,8 @@ fn test_to_lowercase() {
     fn lower(c: char) -> char {
         let mut it = c.to_lowercase();
         let c = it.next().unwrap();
+        // As of Unicode version 7.0.0, `SpecialCasing.txt` has no lower-case mapping
+        // to multiple code points.
         assert!(it.next().is_none());
         c
     }
@@ -73,29 +75,54 @@ fn test_to_lowercase() {
     assert_eq!(lower('Μ'), 'μ');
     assert_eq!(lower('Α'), 'α');
     assert_eq!(lower('Σ'), 'σ');
+    assert_eq!(lower('Dž'), 'dž');
+    assert_eq!(lower('fi'), 'fi');
 }
 
 #[test]
 fn test_to_uppercase() {
-    fn upper(c: char) -> char {
-        let mut it = c.to_uppercase();
-        let c = it.next().unwrap();
-        assert!(it.next().is_none());
-        c
+    fn upper(c: char) -> Vec<char> {
+        c.to_uppercase().collect()
     }
-    assert_eq!(upper('a'), 'A');
-    assert_eq!(upper('ö'), 'Ö');
-    assert_eq!(upper('ß'), 'ß'); // not ẞ: Latin capital letter sharp s
-    assert_eq!(upper('ü'), 'Ü');
-    assert_eq!(upper('💩'), '💩');
-
-    assert_eq!(upper('σ'), 'Σ');
-    assert_eq!(upper('τ'), 'Τ');
-    assert_eq!(upper('ι'), 'Ι');
-    assert_eq!(upper('γ'), 'Γ');
-    assert_eq!(upper('μ'), 'Μ');
-    assert_eq!(upper('α'), 'Α');
-    assert_eq!(upper('ς'), 'Σ');
+    assert_eq!(upper('a'), ['A']);
+    assert_eq!(upper('ö'), ['Ö']);
+    assert_eq!(upper('ß'), ['S', 'S']); // not ẞ: Latin capital letter sharp s
+    assert_eq!(upper('ü'), ['Ü']);
+    assert_eq!(upper('💩'), ['💩']);
+
+    assert_eq!(upper('σ'), ['Σ']);
+    assert_eq!(upper('τ'), ['Τ']);
+    assert_eq!(upper('ι'), ['Ι']);
+    assert_eq!(upper('γ'), ['Γ']);
+    assert_eq!(upper('μ'), ['Μ']);
+    assert_eq!(upper('α'), ['Α']);
+    assert_eq!(upper('ς'), ['Σ']);
+    assert_eq!(upper('Dž'), ['DŽ']);
+    assert_eq!(upper('fi'), ['F', 'I']);
+    assert_eq!(upper('ᾀ'), ['Ἀ', 'Ι']);
+}
+
+#[test]
+fn test_to_titlecase() {
+    fn title(c: char) -> Vec<char> {
+        c.to_titlecase().collect()
+    }
+    assert_eq!(title('a'), ['A']);
+    assert_eq!(title('ö'), ['Ö']);
+    assert_eq!(title('ß'), ['S', 's']); // not ẞ: Latin capital letter sharp s
+    assert_eq!(title('ü'), ['Ü']);
+    assert_eq!(title('💩'), ['💩']);
+
+    assert_eq!(title('σ'), ['Σ']);
+    assert_eq!(title('τ'), ['Τ']);
+    assert_eq!(title('ι'), ['Ι']);
+    assert_eq!(title('γ'), ['Γ']);
+    assert_eq!(title('μ'), ['Μ']);
+    assert_eq!(title('α'), ['Α']);
+    assert_eq!(title('ς'), ['Σ']);
+    assert_eq!(title('DŽ'), ['Dž']);
+    assert_eq!(title('fi'), ['F', 'i']);
+    assert_eq!(title('ᾀ'), ['ᾈ']);
 }
 
 #[test]
index cdb9c38f027f729d83c99f7c8d44e1170859c34c..42872589bb01fa296dbe0d76ffb8e2575a6ef5e7 100644 (file)
@@ -16,4 +16,6 @@ fn test_format_flags() {
     // No residual flags left by pointer formatting
     let p = "".as_ptr();
     assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p));
+
+    assert_eq!(format!("{: >3}", 'a'), "  a");
 }
index 0415c75aa5204cb6eaa43dd6f37296f5dd0a63de..dca899a8e9f7a14ddf323f3f96637b1d1ad113a2 100644 (file)
@@ -82,7 +82,7 @@ fn test_iterator_chain() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
-    let it = xs.iter().chain(ys.iter());
+    let it = xs.iter().chain(&ys);
     let mut i = 0;
     for &x in it {
         assert_eq!(x, expected[i]);
@@ -107,11 +107,11 @@ fn test_iterator_chain_nth() {
     let zs = [];
     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
     for (i, x) in expected.iter().enumerate() {
-        assert_eq!(Some(x), xs.iter().chain(ys.iter()).nth(i));
+        assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
     }
-    assert_eq!(zs.iter().chain(xs.iter()).nth(0), Some(&0));
+    assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
 
-    let mut it = xs.iter().chain(zs.iter());
+    let mut it = xs.iter().chain(&zs);
     assert_eq!(it.nth(5), Some(&5));
     assert_eq!(it.next(), None);
 }
@@ -121,10 +121,10 @@ fn test_iterator_chain_last() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
     let zs = [];
-    assert_eq!(xs.iter().chain(ys.iter()).last(), Some(&60));
-    assert_eq!(zs.iter().chain(ys.iter()).last(), Some(&60));
-    assert_eq!(ys.iter().chain(zs.iter()).last(), Some(&60));
-    assert_eq!(zs.iter().chain(zs.iter()).last(), None);
+    assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&zs).last(), None);
 }
 
 #[test]
@@ -132,8 +132,8 @@ fn test_iterator_chain_count() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
     let zs = [];
-    assert_eq!(xs.iter().chain(ys.iter()).count(), 10);
-    assert_eq!(zs.iter().chain(ys.iter()).count(), 4);
+    assert_eq!(xs.iter().chain(&ys).count(), 10);
+    assert_eq!(zs.iter().chain(&ys).count(), 4);
 }
 
 #[test]
@@ -571,8 +571,8 @@ fn test_iterator_size_hint() {
     assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
     assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
     assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
-    assert_eq!(vi.clone().chain(v2.iter()).size_hint(), (13, Some(13)));
-    assert_eq!(vi.clone().zip(v2.iter()).size_hint(), (3, Some(3)));
+    assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
+    assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
     assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
     assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
     assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
@@ -742,7 +742,7 @@ fn test_double_ended_filter_map() {
 fn test_double_ended_chain() {
     let xs = [1, 2, 3, 4, 5];
     let ys = [7, 9, 11];
-    let mut it = xs.iter().chain(ys.iter()).rev();
+    let mut it = xs.iter().chain(&ys).rev();
     assert_eq!(it.next().unwrap(), &11);
     assert_eq!(it.next().unwrap(), &9);
     assert_eq!(it.next_back().unwrap(), &1);
@@ -807,7 +807,7 @@ fn check_randacc_iter<A, T>(a: T, len: usize) where
 fn test_double_ended_flat_map() {
     let u = [0,1];
     let v = [5,6,7,8];
-    let mut it = u.iter().flat_map(|x| v[*x..v.len()].iter());
+    let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
     assert_eq!(it.next_back().unwrap(), &8);
     assert_eq!(it.next().unwrap(),      &5);
     assert_eq!(it.next_back().unwrap(), &7);
@@ -824,7 +824,7 @@ fn test_double_ended_flat_map() {
 fn test_random_access_chain() {
     let xs = [1, 2, 3, 4, 5];
     let ys = [7, 9, 11];
-    let mut it = xs.iter().chain(ys.iter());
+    let mut it = xs.iter().chain(&ys);
     assert_eq!(it.idx(0).unwrap(), &1);
     assert_eq!(it.idx(5).unwrap(), &7);
     assert_eq!(it.idx(7).unwrap(), &11);
@@ -862,7 +862,7 @@ fn test_random_access_rev() {
 fn test_random_access_zip() {
     let xs = [1, 2, 3, 4, 5];
     let ys = [7, 9, 11];
-    check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len()));
+    check_randacc_iter(xs.iter().zip(&ys), cmp::min(xs.len(), ys.len()));
 }
 
 #[test]
@@ -1096,6 +1096,19 @@ fn test_fuse_count() {
     // Can't check len now because count consumes.
 }
 
+#[test]
+fn test_once() {
+    let mut it = once(42);
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_empty() {
+    let mut it = empty::<i32>();
+    assert_eq!(it.next(), None);
+}
+
 #[bench]
 fn bench_rposition(b: &mut Bencher) {
     let it: Vec<usize> = (0..300).collect();
index 90c1e8b132e42be16975d4d66eb6996bd1ec2598..08536e63204753e4e90372b0223afece3987d12b 100644 (file)
@@ -8,23 +8,45 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
-#![cfg_attr(stage0, feature(custom_attribute))]
-
+#![feature(as_unsafe_cell)]
+#![feature(borrow_state)]
 #![feature(box_syntax)]
-#![feature(unboxed_closures)]
+#![feature(cell_extras)]
+#![feature(cmp_partial)]
+#![feature(const_fn)]
 #![feature(core)]
-#![feature(test)]
+#![feature(core_float)]
+#![feature(float_extras)]
+#![feature(float_from_str_radix)]
+#![feature(flt2dec)]
+#![feature(fmt_radix)]
+#![feature(hash_default)]
+#![feature(hasher_write)]
+#![feature(iter_arith)]
+#![feature(iter_arith)]
+#![feature(iter_cmp)]
+#![feature(iter_empty)]
+#![feature(iter_idx)]
+#![feature(iter_iterate)]
+#![feature(iter_min_max)]
+#![feature(iter_once)]
+#![feature(iter_order)]
+#![feature(iter_unfold)]
+#![feature(libc)]
+#![feature(nonzero)]
+#![feature(num_bits_bytes)]
+#![feature(ptr_as_ref)]
 #![feature(rand)]
+#![feature(range_inclusive)]
+#![feature(raw)]
+#![feature(result_expect)]
+#![feature(slice_bytes)]
+#![feature(slice_patterns)]
+#![feature(step_by)]
+#![feature(test)]
+#![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(std_misc)]
-#![feature(libc)]
-#![feature(hash)]
-#![feature(debug_builders)]
 #![feature(unique)]
-#![feature(step_by)]
-#![feature(slice_patterns)]
-#![feature(float_from_str_radix)]
 
 extern crate core;
 extern crate test;
index 66945ad251f1ed3dc9a68912aa699a0e2e44dcbe..04271ed5dd1a174de5c2e3770c6e85b44e07f1bd 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::option::*;
-use core::marker;
 use core::mem;
 use core::clone::Clone;
 
@@ -72,7 +71,7 @@ fn test_option_dance() {
     let x = Some(());
     let mut y = Some(5);
     let mut y2 = 0;
-    for _x in x.iter() {
+    for _x in x {
         y2 = y.take().unwrap();
     }
     assert_eq!(y2, 5);
@@ -81,7 +80,8 @@ fn test_option_dance() {
 
 #[test] #[should_panic]
 fn test_option_too_much_dance() {
-    let mut y = Some(marker::NoCopy);
+    struct A;
+    let mut y = Some(A);
     let _y2 = y.take().unwrap();
     let _y3 = y.take().unwrap();
 }
index 3fdb102875332f7aa4b26db6993abfb9ab5c6151..02ea6b10e6e03ce05de3335e8191d996cbd508e0 100644 (file)
@@ -137,3 +137,16 @@ pub fn test_unwrap_or_else_panic() {
     let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
     let _ : isize = bad_err.unwrap_or_else(handler);
 }
+
+
+#[test]
+pub fn test_expect_ok() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    assert_eq!(ok.expect("Unexpected error"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected error: \"All good\"")]
+pub fn test_expect_err() {
+    let err: Result<isize, &'static str> = Err("All good");
+    err.expect("Got expected error");
+}
index 1e0e2018050baff53e4ba74c07adc4ac47548cad..58cdf1133ec6a83b5ff11b1faf82274e39e4115b 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(libc)]
 #![feature(staged_api)]
 #![feature(unique)]
-#![cfg_attr(test, feature(rustc_private, rand, collections))]
+#![cfg_attr(test, feature(rustc_private, rand, vec_push_all))]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
index fa2ae79688d72a89d429601e241a221fe960e22b..c2b28bd134d478f7c64be02c634f05067f89f069 100644 (file)
@@ -22,7 +22,7 @@
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
index 5782c57834eedc6f14ab226aff6ca7f35b1a8b33..0d15f584d648aed652a39452175e7a10cc0cd95e 100644 (file)
@@ -85,7 +85,7 @@
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
@@ -953,7 +953,7 @@ fn test_split_within() {
     fn t(s: &str, i: usize, u: &[String]) {
         let mut v = Vec::new();
         each_split_within(s, i, |s| { v.push(s.to_string()); true });
-        assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b));
+        assert!(v.iter().zip(u).all(|(a,b)| a == b));
     }
     t("", 0, &[]);
     t("", 15, &[]);
index 95b78e1cbfd039a1b4d1e5665a0e4d4b0dd12830..f8d80035d97fb62f645924142a72f9a7b7b76933 100644 (file)
@@ -74,7 +74,7 @@
 //!         // (assumes that |N| \approxeq |E|)
 //!         let &Edges(ref v) = self;
 //!         let mut nodes = Vec::with_capacity(v.len());
-//!         for &(s,t) in v.iter() {
+//!         for &(s,t) in v {
 //!             nodes.push(s); nodes.push(t);
 //!         }
 //!         nodes.sort();
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![feature(collections)]
+
 #![feature(into_cow)]
+#![feature(str_escape)]
 
 use self::LabelText::*;
 
@@ -558,7 +559,7 @@ pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N
     }
 
     try!(writeln(w, &["digraph ", g.graph_id().as_slice(), " {"]));
-    for n in &*g.nodes() {
+    for n in g.nodes().iter() {
         try!(indent(w));
         let id = g.node_id(n);
         if options.contains(&RenderOption::NoNodeLabels) {
@@ -570,7 +571,7 @@ pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N
         }
     }
 
-    for e in &*g.edges() {
+    for e in g.edges().iter() {
         let escaped_label = g.edge_label(e).escape();
         try!(indent(w));
         let source = g.source(e);
index 78a030cde6bab70b5da39aab12a0b163c3390ac0..893bceed582314895129a798943ec7eddf629cd9 100644 (file)
@@ -18,7 +18,7 @@
 #![cfg_attr(not(feature = "cargo-build"), staged_api)]
 #![cfg_attr(not(feature = "cargo-build"), no_std)]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![cfg_attr(test, feature(test))]
@@ -146,10 +146,19 @@ pub use funcs::bsd43::*;
 #[link(name = "m")]
 extern {}
 
-#[cfg(all(target_env = "musl", not(test)))]
+// 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 {}
 
+#[cfg(all(windows, target_env = "msvc"))]
+#[link(name = "kernel32")]
+#[link(name = "shell32")]
+#[link(name = "msvcrt")]
+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.
@@ -5484,17 +5493,17 @@ pub mod funcs {
                 pub fn dup2(src: c_int, dst: c_int) -> c_int;
                 #[link_name = "_execv"]
                 pub fn execv(prog: *const c_char,
-                             argv: *mut *const c_char) -> intptr_t;
+                             argv: *const *const c_char) -> intptr_t;
                 #[link_name = "_execve"]
-                pub fn execve(prog: *const c_char, argv: *mut *const c_char,
-                              envp: *mut *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: *mut *const c_char) -> c_int;
+                              argv: *const *const c_char) -> c_int;
                 #[link_name = "_execvpe"]
-                pub fn execvpe(c: *const c_char, argv: *mut *const c_char,
-                               envp: *mut *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"]
@@ -5678,12 +5687,12 @@ pub mod funcs {
                 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: *mut *const c_char) -> c_int;
-                pub fn execve(prog: *const c_char, argv: *mut *const c_char,
-                              envp: *mut *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: *mut *const c_char) -> c_int;
+                              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;
@@ -5693,7 +5702,9 @@ pub mod funcs {
                 pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
                                  -> c_int;
                 pub fn getlogin() -> *mut c_char;
-                pub fn getopt(argc: c_int, argv: *mut *const 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 getpgrp() -> pid_t;
                 pub fn getpid() -> pid_t;
@@ -5743,19 +5754,19 @@ pub mod funcs {
                 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: *mut *const c_char) -> c_int;
-                pub fn execve(prog: *const c_char, argv: *mut *const c_char,
-                              envp: *mut *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: *mut *const c_char) -> c_int;
+                              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: *mut *const c_char,
+                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;
@@ -6302,8 +6313,8 @@ pub mod funcs {
                                 lpOverlapped: LPOVERLAPPED) -> BOOL;
                 pub fn WriteFile(hFile: HANDLE,
                                  lpBuffer: LPVOID,
-                                 nNumberOfBytesToRead: DWORD,
-                                 lpNumberOfBytesRead: LPDWORD,
+                                 nNumberOfBytesToWrite: DWORD,
+                                 lpNumberOfBytesWritten: LPDWORD,
                                  lpOverlapped: LPOVERLAPPED) -> BOOL;
                 pub fn SetFilePointerEx(hFile: HANDLE,
                                         liDistanceToMove: LARGE_INTEGER,
index 9ea680c7efe7643c8bab6a4717333931bb3d49bd..5d38a381e6b7e878dbc464ae3acd8e265599c86c 100644 (file)
@@ -17,7 +17,7 @@ pub struct LogDirective {
     pub level: u32,
 }
 
-pub static LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO",
+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
index 4280a88f724a29eb8d91ace42dd889def74750c3..7bafd9382f059e8f715507212ec11085855f18d8 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![deny(missing_docs)]
 
-#![feature(alloc)]
-#![feature(staged_api)]
+#![feature(box_raw)]
 #![feature(box_syntax)]
-#![feature(core)]
-#![feature(std_misc)]
+#![feature(const_fn)]
+#![feature(iter_cmp)]
+#![feature(rt)]
+#![feature(staged_api)]
+#![feature(static_mutex)]
 
-use std::boxed;
 use std::cell::RefCell;
 use std::fmt;
 use std::io::{self, Stderr};
@@ -184,7 +185,7 @@ use std::mem;
 use std::env;
 use std::rt;
 use std::slice;
-use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
+use std::sync::{Once, StaticMutex};
 
 use directive::LOG_LEVEL_NAMES;
 
@@ -200,7 +201,7 @@ pub const MAX_LOG_LEVEL: u32 = 255;
 /// The default logging level of a crate if no other is specified.
 const DEFAULT_LOG_LEVEL: u32 = 1;
 
-static LOCK: StaticMutex = MUTEX_INIT;
+static LOCK: StaticMutex = StaticMutex::new();
 
 /// An unsafe constant that is the maximum logging level of any module
 /// specified. This is the first line of defense to determining whether a
@@ -367,7 +368,7 @@ pub struct LogLocation {
 /// module's log statement should be emitted or not.
 #[doc(hidden)]
 pub fn mod_enabled(level: u32, module: &str) -> bool {
-    static INIT: Once = ONCE_INIT;
+    static INIT: Once = Once::new();
     INIT.call_once(init);
 
     // It's possible for many threads are in this function, only one of them
@@ -434,12 +435,12 @@ fn init() {
 
         assert!(FILTER.is_null());
         match filter {
-            Some(f) => FILTER = boxed::into_raw(box f),
+            Some(f) => FILTER = Box::into_raw(box f),
             None => {}
         }
 
         assert!(DIRECTIVES.is_null());
-        DIRECTIVES = boxed::into_raw(box directives);
+        DIRECTIVES = Box::into_raw(box directives);
 
         // Schedule the cleanup for the globals for when the runtime exits.
         let _ = rt::at_exit(move || {
index bcb827cb471cacac023c650ae81a78d147ec83d7..da360978369f20f6fc40e7cbcc08b667456e201f 100644 (file)
@@ -174,7 +174,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
         self.init(&[0; KEY_WORDS]);
         // set key in place
         let key = &mut self.state[4 .. 4+KEY_WORDS];
-        for (k, s) in key.iter_mut().zip(seed.iter()) {
+        for (k, s) in key.iter_mut().zip(seed) {
             *k = *s;
         }
     }
index a108fd70d1ca9d6410eb60bc1f048dbacf68b211..b6de4bf892cdfb658def734e365de8eaf9aa0bea 100644 (file)
@@ -12,7 +12,7 @@
 // algorithm. Autogenerated by `ziggurat_tables.py`.
 
 pub type ZigTable = &'static [f64; 257];
-pub static ZIG_NORM_R: f64 = 3.654152885361008796;
+pub const ZIG_NORM_R: f64 = 3.654152885361008796;
 pub static ZIG_NORM_X: [f64; 257] =
     [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
      3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
@@ -145,7 +145,7 @@ pub static ZIG_NORM_F: [f64; 257] =
      0.887984660763399880, 0.898095921906304051, 0.908726440060562912, 0.919991505048360247,
      0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
      1.000000000000000000];
-pub static ZIG_EXP_R: f64 = 7.697117470131050077;
+pub const ZIG_EXP_R: f64 = 7.697117470131050077;
 pub static ZIG_EXP_X: [f64; 257] =
     [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
      6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
index 22fe46a8bd83a20e9f78a1a81ec2f47fcfc28c37..ec9aa2d16d24ad0b5ea80b1871bf3ffb0e8bf68c 100644 (file)
@@ -140,7 +140,7 @@ impl IsaacRng {
         }
 
         let r = [(0, MIDPOINT), (MIDPOINT, 0)];
-        for &(mr_offset, m2_offset) in r.iter() {
+        for &(mr_offset, m2_offset) in &r {
 
             macro_rules! rngstepp {
                 ($j:expr, $shift:expr) => {{
@@ -379,7 +379,7 @@ impl Isaac64Rng {
             }
         }
 
-        for &(mr_offset, m2_offset) in MP_VEC.iter() {
+        for &(mr_offset, m2_offset) in &MP_VEC {
             for base in (0..MIDPOINT / 4).map(|i| i * 4) {
 
                 macro_rules! rngstepp {
index 1359894b4dd72fd6410190b86e4aad67abd0a7f8..ec510b4a5bdfb4367792dc6194e7b1884af558ef 100644 (file)
@@ -21,7 +21,7 @@
 #![crate_name = "rand"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![no_std]
 #![unstable(feature = "rand",
             reason = "use `rand` from crates.io")]
 #![feature(core)]
+#![feature(core_float)]
+#![feature(core_prelude)]
+#![feature(core_slice_ext)]
 #![feature(no_std)]
+#![feature(num_bits_bytes)]
 #![feature(staged_api)]
 #![feature(step_by)]
 
-#![cfg_attr(test, feature(test, rand, rustc_private))]
+#![cfg_attr(test, feature(test, rand, rustc_private, iter_order))]
 
 #![allow(deprecated)]
 
index b7938397038b490d6b02c4b0092ad4ad8b62966a..18b1d39ea82d80e59f068b35c215e2ccd228d897 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
-#![feature(core)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
+#![feature(slice_bytes)]
 
 #![cfg_attr(test, feature(test))]
 
@@ -397,39 +397,68 @@ pub mod reader {
         }
     }
 
-    pub fn docs<F>(d: Doc, mut it: F) -> bool where
-        F: FnMut(usize, Doc) -> bool,
-    {
-        let mut pos = d.start;
-        while pos < d.end {
-            let elt_tag = try_or!(tag_at(d.data, pos), false);
-            let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
-            pos = elt_size.next + elt_size.val;
-            let doc = Doc { data: d.data, start: elt_size.next, end: pos };
-            if !it(elt_tag.val, doc) {
-                return false;
+    pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
+        DocsIterator {
+            d: d
+        }
+    }
+
+    pub struct DocsIterator<'a> {
+        d: Doc<'a>,
+    }
+
+    impl<'a> Iterator for DocsIterator<'a> {
+        type Item = (usize, Doc<'a>);
+
+        fn next(&mut self) -> Option<(usize, Doc<'a>)> {
+            if self.d.start >= self.d.end {
+                return None;
             }
+
+            let elt_tag = try_or!(tag_at(self.d.data, self.d.start), {
+                self.d.start = self.d.end;
+                None
+            });
+            let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), {
+                self.d.start = self.d.end;
+                None
+            });
+
+            let end = elt_size.next + elt_size.val;
+            let doc = Doc {
+                data: self.d.data,
+                start: elt_size.next,
+                end: end,
+            };
+
+            self.d.start = end;
+            return Some((elt_tag.val, doc));
         }
-        return true;
     }
 
-    pub fn tagged_docs<F>(d: Doc, tg: usize, mut it: F) -> bool where
-        F: FnMut(Doc) -> bool,
-    {
-        let mut pos = d.start;
-        while pos < d.end {
-            let elt_tag = try_or!(tag_at(d.data, pos), false);
-            let elt_size = try_or!(tag_len_at(d.data, elt_tag), false);
-            pos = elt_size.next + elt_size.val;
-            if elt_tag.val == tg {
-                let doc = Doc { data: d.data, start: elt_size.next,
-                                end: pos };
-                if !it(doc) {
-                    return false;
+    pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> {
+        TaggedDocsIterator {
+            iter: docs(d),
+            tag: tag,
+        }
+    }
+
+    pub struct TaggedDocsIterator<'a> {
+        iter: DocsIterator<'a>,
+        tag: usize,
+    }
+
+    impl<'a> Iterator for TaggedDocsIterator<'a> {
+        type Item = Doc<'a>;
+
+        fn next(&mut self) -> Option<Doc<'a>> {
+            while let Some((tag, doc)) = self.iter.next() {
+                if tag == self.tag {
+                    return Some(doc);
                 }
             }
+            None
         }
-        return true;
     }
 
     pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
diff --git a/src/librustc/ast_map/blocks.rs b/src/librustc/ast_map/blocks.rs
new file mode 100644 (file)
index 0000000..6c9ed29
--- /dev/null
@@ -0,0 +1,254 @@
+// 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.
+
+//! This module provides a simplified abstraction for working with
+//! code blocks identified by their integer node-id.  In particular,
+//! it captures a common set of attributes that all "function-like
+//! things" (represented by `FnLike` instances) share.  For example,
+//! all `FnLike` instances have a type signature (be it explicit or
+//! inferred).  And all `FnLike` instances have a body, i.e. the code
+//! that is run when the function-like thing it represents is invoked.
+//!
+//! With the above abstraction in place, one can treat the program
+//! text as a collection of blocks of code (and most such blocks are
+//! nested within a uniquely determined `FnLike`), and users can ask
+//! for the `Code` associated with a particular NodeId.
+
+pub use self::Code::*;
+
+use ast_map::{self, Node};
+use syntax::abi;
+use syntax::ast::{Block, FnDecl, NodeId};
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::visit;
+
+/// An FnLikeNode is a Node that is like a fn, in that it has a decl
+/// and a body (as well as a NodeId, a span, etc).
+///
+/// More specifically, it is one of either:
+///   - A function item,
+///   - A closure expr (i.e. an ExprClosure), or
+///   - The default implementation for a trait method.
+///
+/// To construct one, use the `Code::from_node` function.
+#[derive(Copy, Clone)]
+pub struct FnLikeNode<'a> { node: ast_map::Node<'a> }
+
+/// MaybeFnLike wraps a method that indicates if an object
+/// corresponds to some FnLikeNode.
+pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
+
+/// Components shared by fn-like things (fn items, methods, closures).
+pub struct FnParts<'a> {
+    pub decl: &'a FnDecl,
+    pub body: &'a Block,
+    pub kind: visit::FnKind<'a>,
+    pub span: Span,
+    pub id:   NodeId,
+}
+
+impl MaybeFnLike for ast::Item {
+    fn is_fn_like(&self) -> bool {
+        match self.node { ast::ItemFn(..) => true, _ => false, }
+    }
+}
+
+impl MaybeFnLike for ast::TraitItem {
+    fn is_fn_like(&self) -> bool {
+        match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, }
+    }
+}
+
+impl MaybeFnLike for ast::Expr {
+    fn is_fn_like(&self) -> bool {
+        match self.node {
+            ast::ExprClosure(..) => true,
+            _ => false,
+        }
+    }
+}
+
+/// Carries either an FnLikeNode or a Block, as these are the two
+/// constructs that correspond to "code" (as in, something from which
+/// we can construct a control-flow graph).
+#[derive(Copy, Clone)]
+pub enum Code<'a> {
+    FnLikeCode(FnLikeNode<'a>),
+    BlockCode(&'a Block),
+}
+
+impl<'a> Code<'a> {
+    pub fn id(&self) -> ast::NodeId {
+        match *self {
+            FnLikeCode(node) => node.id(),
+            BlockCode(block) => block.id,
+        }
+    }
+
+    /// Attempts to construct a Code from presumed FnLike or Block node input.
+    pub fn from_node(node: Node) -> Option<Code> {
+        if let ast_map::NodeBlock(block) = node {
+            Some(BlockCode(block))
+        } else {
+            FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like))
+        }
+    }
+}
+
+/// These are all the components one can extract from a fn item for
+/// use when implementing FnLikeNode operations.
+struct ItemFnParts<'a> {
+    ident:    ast::Ident,
+    decl:     &'a ast::FnDecl,
+    unsafety: ast::Unsafety,
+    constness: ast::Constness,
+    abi:      abi::Abi,
+    vis:      ast::Visibility,
+    generics: &'a ast::Generics,
+    body:     &'a Block,
+    id:       ast::NodeId,
+    span:     Span
+}
+
+/// These are all the components one can extract from a closure expr
+/// for use when implementing FnLikeNode operations.
+struct ClosureParts<'a> {
+    decl: &'a FnDecl,
+    body: &'a Block,
+    id: NodeId,
+    span: Span
+}
+
+impl<'a> ClosureParts<'a> {
+    fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> {
+        ClosureParts { decl: d, body: b, id: id, span: s }
+    }
+}
+
+impl<'a> FnLikeNode<'a> {
+    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
+    pub fn from_node(node: Node) -> Option<FnLikeNode> {
+        let fn_like = match node {
+            ast_map::NodeItem(item) => item.is_fn_like(),
+            ast_map::NodeTraitItem(tm) => tm.is_fn_like(),
+            ast_map::NodeImplItem(_) => true,
+            ast_map::NodeExpr(e) => e.is_fn_like(),
+            _ => false
+        };
+        if fn_like {
+            Some(FnLikeNode {
+                node: node
+            })
+        } else {
+            None
+        }
+    }
+
+    pub fn to_fn_parts(self) -> FnParts<'a> {
+        FnParts {
+            decl: self.decl(),
+            body: self.body(),
+            kind: self.kind(),
+            span: self.span(),
+            id:   self.id(),
+        }
+    }
+
+    pub fn body(self) -> &'a Block {
+        self.handle(|i: ItemFnParts<'a>|  &*i.body,
+                    |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _|  body,
+                    |c: ClosureParts<'a>| c.body)
+    }
+
+    pub fn decl(self) -> &'a FnDecl {
+        self.handle(|i: ItemFnParts<'a>|  &*i.decl,
+                    |_, _, sig: &'a ast::MethodSig, _, _, _|  &sig.decl,
+                    |c: ClosureParts<'a>| c.decl)
+    }
+
+    pub fn span(self) -> Span {
+        self.handle(|i: ItemFnParts|     i.span,
+                    |_, _, _: &'a ast::MethodSig, _, _, span| span,
+                    |c: ClosureParts|    c.span)
+    }
+
+    pub fn id(self) -> NodeId {
+        self.handle(|i: ItemFnParts|     i.id,
+                    |id, _, _: &'a ast::MethodSig, _, _, _| id,
+                    |c: ClosureParts|    c.id)
+    }
+
+    pub fn kind(self) -> visit::FnKind<'a> {
+        let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> {
+            visit::FkItemFn(p.ident, p.generics, p.unsafety, p.constness, p.abi, p.vis)
+        };
+        let closure = |_: ClosureParts| {
+            visit::FkFnBlock
+        };
+        let method = |_, ident, sig: &'a ast::MethodSig, vis, _, _| {
+            visit::FkMethod(ident, sig, vis)
+        };
+        self.handle(item, method, closure)
+    }
+
+    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
+        I: FnOnce(ItemFnParts<'a>) -> A,
+        M: FnOnce(NodeId,
+                  ast::Ident,
+                  &'a ast::MethodSig,
+                  Option<ast::Visibility>,
+                  &'a ast::Block,
+                  Span)
+                  -> A,
+        C: FnOnce(ClosureParts<'a>) -> A,
+    {
+        match self.node {
+            ast_map::NodeItem(i) => match i.node {
+                ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) =>
+                    item_fn(ItemFnParts {
+                        id: i.id,
+                        ident: i.ident,
+                        decl: &**decl,
+                        unsafety: unsafety,
+                        body: &**block,
+                        generics: generics,
+                        abi: abi,
+                        vis: i.vis,
+                        constness: constness,
+                        span: i.span
+                    }),
+                _ => panic!("item FnLikeNode that is not fn-like"),
+            },
+            ast_map::NodeTraitItem(ti) => match ti.node {
+                ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                    method(ti.id, ti.ident, sig, None, body, ti.span)
+                }
+                _ => panic!("trait method FnLikeNode that is not fn-like"),
+            },
+            ast_map::NodeImplItem(ii) => {
+                match ii.node {
+                    ast::MethodImplItem(ref sig, ref body) => {
+                        method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
+                    }
+                    _ => {
+                        panic!("impl method FnLikeNode that is not fn-like")
+                    }
+                }
+            }
+            ast_map::NodeExpr(e) => match e.node {
+                ast::ExprClosure(_, ref decl, ref block) =>
+                    closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
+                _ => panic!("expr FnLikeNode that is not fn-like"),
+            },
+            _ => panic!("other FnLikeNode that is not fn-like"),
+        }
+    }
+}
diff --git a/src/librustc/ast_map/mod.rs b/src/librustc/ast_map/mod.rs
new file mode 100644 (file)
index 0000000..06d87f5
--- /dev/null
@@ -0,0 +1,1023 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use self::Node::*;
+pub use self::PathElem::*;
+use self::MapEntry::*;
+
+use syntax::abi;
+use syntax::ast::*;
+use syntax::ast_util;
+use syntax::codemap::{DUMMY_SP, Span, Spanned};
+use syntax::fold::Folder;
+use syntax::parse::token;
+use syntax::print::pprust;
+use syntax::visit::{self, Visitor};
+
+use arena::TypedArena;
+use std::cell::RefCell;
+use std::fmt;
+use std::io;
+use std::iter::{self, repeat};
+use std::mem;
+use std::slice;
+
+pub mod blocks;
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub enum PathElem {
+    PathMod(Name),
+    PathName(Name)
+}
+
+impl PathElem {
+    pub fn name(&self) -> Name {
+        match *self {
+            PathMod(name) | PathName(name) => name
+        }
+    }
+}
+
+impl fmt::Display for PathElem {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let slot = token::get_name(self.name());
+        write!(f, "{}", slot)
+    }
+}
+
+#[derive(Clone)]
+pub struct LinkedPathNode<'a> {
+    node: PathElem,
+    next: LinkedPath<'a>,
+}
+
+#[derive(Copy, Clone)]
+pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>);
+
+impl<'a> LinkedPath<'a> {
+    pub fn empty() -> LinkedPath<'a> {
+        LinkedPath(None)
+    }
+
+    pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> {
+        LinkedPath(Some(node))
+    }
+}
+
+impl<'a> Iterator for LinkedPath<'a> {
+    type Item = PathElem;
+
+    fn next(&mut self) -> Option<PathElem> {
+        match self.0 {
+            Some(node) => {
+                *self = node.next;
+                Some(node.node)
+            }
+            None => None
+        }
+    }
+}
+
+/// The type of the iterator used by with_path.
+pub type PathElems<'a, 'b> = iter::Chain<iter::Cloned<slice::Iter<'a, PathElem>>, LinkedPath<'b>>;
+
+pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
+    let itr = token::get_ident_interner();
+
+    path.fold(String::new(), |mut s, e| {
+        let e = itr.get(e.name());
+        if !s.is_empty() {
+            s.push_str("::");
+        }
+        s.push_str(&e[..]);
+        s
+    })
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum Node<'ast> {
+    NodeItem(&'ast Item),
+    NodeForeignItem(&'ast ForeignItem),
+    NodeTraitItem(&'ast TraitItem),
+    NodeImplItem(&'ast ImplItem),
+    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),
+
+    NodeLifetime(&'ast Lifetime),
+}
+
+/// Represents an entry and its parent Node ID
+/// The odd layout is to bring down the total size.
+#[derive(Copy, Debug)]
+enum MapEntry<'ast> {
+    /// Placeholder for holes in the map.
+    NotPresent,
+
+    /// All the node types, with a parent ID.
+    EntryItem(NodeId, &'ast Item),
+    EntryForeignItem(NodeId, &'ast ForeignItem),
+    EntryTraitItem(NodeId, &'ast TraitItem),
+    EntryImplItem(NodeId, &'ast ImplItem),
+    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),
+    EntryLifetime(NodeId, &'ast Lifetime),
+
+    /// Roots for node trees.
+    RootCrate,
+    RootInlinedParent(&'ast InlinedParent)
+}
+
+impl<'ast> Clone for MapEntry<'ast> {
+    fn clone(&self) -> MapEntry<'ast> {
+        *self
+    }
+}
+
+#[derive(Debug)]
+struct InlinedParent {
+    path: Vec<PathElem>,
+    ii: InlinedItem
+}
+
+impl<'ast> MapEntry<'ast> {
+    fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
+        match node {
+            NodeItem(n) => EntryItem(p, n),
+            NodeForeignItem(n) => EntryForeignItem(p, n),
+            NodeTraitItem(n) => EntryTraitItem(p, n),
+            NodeImplItem(n) => EntryImplItem(p, n),
+            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),
+            NodeStructCtor(n) => EntryStructCtor(p, n),
+            NodeLifetime(n) => EntryLifetime(p, n)
+        }
+    }
+
+    fn parent(self) -> Option<NodeId> {
+        Some(match self {
+            EntryItem(id, _) => id,
+            EntryForeignItem(id, _) => id,
+            EntryTraitItem(id, _) => id,
+            EntryImplItem(id, _) => id,
+            EntryVariant(id, _) => id,
+            EntryExpr(id, _) => id,
+            EntryStmt(id, _) => id,
+            EntryArg(id, _) => id,
+            EntryLocal(id, _) => id,
+            EntryPat(id, _) => id,
+            EntryBlock(id, _) => id,
+            EntryStructCtor(id, _) => id,
+            EntryLifetime(id, _) => id,
+            _ => return None
+        })
+    }
+
+    fn to_node(self) -> Option<Node<'ast>> {
+        Some(match self {
+            EntryItem(_, n) => NodeItem(n),
+            EntryForeignItem(_, n) => NodeForeignItem(n),
+            EntryTraitItem(_, n) => NodeTraitItem(n),
+            EntryImplItem(_, n) => NodeImplItem(n),
+            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),
+            EntryStructCtor(_, n) => NodeStructCtor(n),
+            EntryLifetime(_, n) => NodeLifetime(n),
+            _ => return None
+        })
+    }
+}
+
+/// Stores a crate and any number of inlined items from other crates.
+pub struct Forest {
+    krate: Crate,
+    inlined_items: TypedArena<InlinedParent>
+}
+
+impl Forest {
+    pub fn new(krate: Crate) -> Forest {
+        Forest {
+            krate: krate,
+            inlined_items: TypedArena::new()
+        }
+    }
+
+    pub fn krate<'ast>(&'ast self) -> &'ast Crate {
+        &self.krate
+    }
+}
+
+/// Represents a mapping from Node IDs to AST elements and their parent
+/// Node IDs
+pub struct Map<'ast> {
+    /// The backing storage for all the AST nodes.
+    forest: &'ast Forest,
+
+    /// NodeIds are sequential integers from 0, so we can be
+    /// super-compact by storing them in a vector. Not everything with
+    /// a NodeId is in the map, but empirically the occupancy is about
+    /// 75-80%, so there's not too much overhead (certainly less than
+    /// a hashmap, since they (at the time of writing) have a maximum
+    /// of 75% occupancy).
+    ///
+    /// Also, indexing is pretty quick when you've got a vector and
+    /// plain old integers.
+    map: RefCell<Vec<MapEntry<'ast>>>
+}
+
+impl<'ast> Map<'ast> {
+    fn entry_count(&self) -> usize {
+        self.map.borrow().len()
+    }
+
+    fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
+        self.map.borrow().get(id as usize).cloned()
+    }
+
+    pub fn krate(&self) -> &'ast Crate {
+        &self.forest.krate
+    }
+
+    /// Retrieve the Node corresponding to `id`, panicking if it cannot
+    /// be found.
+    pub fn get(&self, id: NodeId) -> Node<'ast> {
+        match self.find(id) {
+            Some(node) => node,
+            None => panic!("couldn't find node id {} in the AST map", id)
+        }
+    }
+
+    /// Retrieve the Node corresponding to `id`, returning None if
+    /// cannot be found.
+    pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
+        self.find_entry(id).and_then(|x| x.to_node())
+    }
+
+    /// Retrieve the parent NodeId for `id`, or `id` itself if no
+    /// parent is registered in this map.
+    pub fn get_parent(&self, id: NodeId) -> NodeId {
+        self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
+    }
+
+    pub fn get_parent_did(&self, id: NodeId) -> DefId {
+        let parent = self.get_parent(id);
+        match self.find_entry(parent) {
+            Some(RootInlinedParent(&InlinedParent {ii: IITraitItem(did, _), ..})) => did,
+            Some(RootInlinedParent(&InlinedParent {ii: IIImplItem(did, _), ..})) => did,
+            _ => ast_util::local_def(parent)
+        }
+    }
+
+    pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi {
+        let parent = self.get_parent(id);
+        let abi = match self.find_entry(parent) {
+            Some(EntryItem(_, i)) => {
+                match i.node {
+                    ItemForeignMod(ref nm) => Some(nm.abi),
+                    _ => None
+                }
+            }
+            /// Wrong but OK, because the only inlined foreign items are intrinsics.
+            Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic),
+            _ => None
+        };
+        match abi {
+            Some(abi) => abi,
+            None => panic!("expected foreign mod or inlined parent, found {}",
+                          self.node_to_string(parent))
+        }
+    }
+
+    pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
+        let vis = self.expect_foreign_item(id).vis;
+        match self.find(self.get_parent(id)) {
+            Some(NodeItem(i)) => vis.inherit_from(i.vis),
+            _ => vis
+        }
+    }
+
+    pub fn expect_item(&self, id: NodeId) -> &'ast Item {
+        match self.find(id) {
+            Some(NodeItem(item)) => item,
+            _ => panic!("expected item, found {}", self.node_to_string(id))
+        }
+    }
+
+    pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
+        match self.find(id) {
+            Some(NodeItem(i)) => {
+                match i.node {
+                    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"),
+                }
+            }
+            _ => panic!(format!("expected struct, found {}", self.node_to_string(id))),
+        }
+    }
+
+    pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
+        match self.find(id) {
+            Some(NodeVariant(variant)) => variant,
+            _ => panic!(format!("expected variant, found {}", self.node_to_string(id))),
+        }
+    }
+
+    pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem {
+        match self.find(id) {
+            Some(NodeForeignItem(item)) => item,
+            _ => panic!("expected foreign item, found {}", self.node_to_string(id))
+        }
+    }
+
+    pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
+        match self.find(id) {
+            Some(NodeExpr(expr)) => expr,
+            _ => panic!("expected expr, found {}", self.node_to_string(id))
+        }
+    }
+
+    /// returns the name associated with the given NodeId's AST
+    pub fn get_path_elem(&self, id: NodeId) -> PathElem {
+        let node = self.get(id);
+        match node {
+            NodeItem(item) => {
+                match item.node {
+                    ItemMod(_) | ItemForeignMod(_) => {
+                        PathMod(item.ident.name)
+                    }
+                    _ => PathName(item.ident.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),
+            _ => panic!("no path elem for {:?}", node)
+        }
+    }
+
+    pub fn with_path<T, F>(&self, id: NodeId, f: F) -> T where
+        F: FnOnce(PathElems) -> T,
+    {
+        self.with_path_next(id, LinkedPath::empty(), f)
+    }
+
+    pub fn path_to_string(&self, id: NodeId) -> String {
+        self.with_path(id, |path| path_to_string(path))
+    }
+
+    fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String {
+        self.with_path(id, |path| {
+            path_to_string(path.chain(Some(PathName(i.name))))
+        })
+    }
+
+    fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
+        F: FnOnce(PathElems) -> T,
+    {
+        let parent = self.get_parent(id);
+        let parent = match self.find_entry(id) {
+            Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => {
+                // Anonymous extern items, enum variants and struct ctors
+                // go in the parent scope.
+                self.get_parent(parent)
+            }
+            // But tuple struct ctors don't have names, so use the path of its
+            // parent, the struct item. Similarly with closure expressions.
+            Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
+                return self.with_path_next(parent, next, f);
+            }
+            _ => parent
+        };
+        if parent == id {
+            match self.find_entry(id) {
+                Some(RootInlinedParent(data)) => {
+                    f(data.path.iter().cloned().chain(next))
+                }
+                _ => f([].iter().cloned().chain(next))
+            }
+        } else {
+            self.with_path_next(parent, LinkedPath::from(&LinkedPathNode {
+                node: self.get_path_elem(id),
+                next: next
+            }), f)
+        }
+    }
+
+    /// Given a node ID, get a list of of attributes associated with the AST
+    /// corresponding to the Node ID
+    pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] {
+        let attrs = match self.find(id) {
+            Some(NodeItem(i)) => Some(&i.attrs[..]),
+            Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
+            Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
+            Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
+            Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
+            // unit/tuple structs take the attributes straight from
+            // the struct definition.
+            Some(NodeStructCtor(_)) => {
+                return self.attrs(self.get_parent(id));
+            }
+            _ => None
+        };
+        attrs.unwrap_or(&[])
+    }
+
+    /// Returns an iterator that yields the node id's with paths that
+    /// match `parts`.  (Requires `parts` is non-empty.)
+    ///
+    /// For example, if given `parts` equal to `["bar", "quux"]`, then
+    /// the iterator will produce node id's for items with paths
+    /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
+    /// any other such items it can find in the map.
+    pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
+                                 -> NodesMatchingSuffix<'a, 'ast> {
+        NodesMatchingSuffix {
+            map: self,
+            item_name: parts.last().unwrap(),
+            in_which: &parts[..parts.len() - 1],
+            idx: 0,
+        }
+    }
+
+    pub fn opt_span(&self, id: NodeId) -> Option<Span> {
+        let sp = match self.find(id) {
+            Some(NodeItem(item)) => item.span,
+            Some(NodeForeignItem(foreign_item)) => foreign_item.span,
+            Some(NodeTraitItem(trait_method)) => trait_method.span,
+            Some(NodeImplItem(ref impl_item)) => impl_item.span,
+            Some(NodeVariant(variant)) => variant.span,
+            Some(NodeExpr(expr)) => expr.span,
+            Some(NodeStmt(stmt)) => stmt.span,
+            Some(NodeArg(pat)) | 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,
+            _ => return None,
+        };
+        Some(sp)
+    }
+
+    pub fn span(&self, id: NodeId) -> Span {
+        self.opt_span(id)
+            .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
+    }
+
+    pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
+        if def_id.krate == LOCAL_CRATE {
+            self.opt_span(def_id.node).unwrap_or(fallback)
+        } else {
+            fallback
+        }
+    }
+
+    pub fn node_to_string(&self, id: NodeId) -> String {
+        node_id_to_string(self, id, true)
+    }
+
+    pub fn node_to_user_string(&self, id: NodeId) -> String {
+        node_id_to_string(self, id, false)
+    }
+}
+
+pub struct NodesMatchingSuffix<'a, 'ast:'a> {
+    map: &'a Map<'ast>,
+    item_name: &'a String,
+    in_which: &'a [String],
+    idx: NodeId,
+}
+
+impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> {
+    /// Returns true only if some suffix of the module path for parent
+    /// matches `self.in_which`.
+    ///
+    /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
+    /// returns true if parent's path ends with the suffix
+    /// `x_0::x_1::...::x_k`.
+    fn suffix_matches(&self, parent: NodeId) -> bool {
+        let mut cursor = parent;
+        for part in self.in_which.iter().rev() {
+            let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
+                None => return false,
+                Some((node_id, name)) => (node_id, name),
+            };
+            if &part[..] != mod_name.as_str() {
+                return false;
+            }
+            cursor = self.map.get_parent(mod_id);
+        }
+        return true;
+
+        // Finds the first mod in parent chain for `id`, along with
+        // that mod's name.
+        //
+        // If `id` itself is a mod named `m` with parent `p`, then
+        // returns `Some(id, m, p)`.  If `id` has no mod in its parent
+        // chain, then returns `None`.
+        fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> {
+            loop {
+                match map.find(id) {
+                    None => return None,
+                    Some(NodeItem(item)) if item_is_mod(&*item) =>
+                        return Some((id, item.ident.name)),
+                    _ => {}
+                }
+                let parent = map.get_parent(id);
+                if parent == id { return None }
+                id = parent;
+            }
+
+            fn item_is_mod(item: &Item) -> bool {
+                match item.node {
+                    ItemMod(_) => true,
+                    _ => false,
+                }
+            }
+        }
+    }
+
+    // We are looking at some node `n` with a given name and parent
+    // id; do their names match what I am seeking?
+    fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool {
+        name.as_str() == &self.item_name[..] &&
+            self.suffix_matches(parent_of_n)
+    }
+}
+
+impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
+    type Item = NodeId;
+
+    fn next(&mut self) -> Option<NodeId> {
+        loop {
+            let idx = self.idx;
+            if idx as usize >= self.map.entry_count() {
+                return None;
+            }
+            self.idx += 1;
+            let (p, name) = match self.map.find_entry(idx) {
+                Some(EntryItem(p, n))       => (p, n.name()),
+                Some(EntryForeignItem(p, n))=> (p, n.name()),
+                Some(EntryTraitItem(p, n))  => (p, n.name()),
+                Some(EntryImplItem(p, n))   => (p, n.name()),
+                Some(EntryVariant(p, n))    => (p, n.name()),
+                _ => continue,
+            };
+            if self.matches_names(p, name) {
+                return Some(idx)
+            }
+        }
+    }
+}
+
+trait Named {
+    fn name(&self) -> Name;
+}
+
+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 } }
+
+pub trait FoldOps {
+    fn new_id(&self, id: NodeId) -> NodeId {
+        id
+    }
+    fn new_def_id(&self, def_id: DefId) -> DefId {
+        def_id
+    }
+    fn new_span(&self, span: Span) -> Span {
+        span
+    }
+}
+
+/// A Folder that updates IDs and Span's according to fold_ops.
+struct IdAndSpanUpdater<F> {
+    fold_ops: F
+}
+
+impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
+    fn new_id(&mut self, id: NodeId) -> NodeId {
+        self.fold_ops.new_id(id)
+    }
+
+    fn new_span(&mut self, span: Span) -> Span {
+        self.fold_ops.new_span(span)
+    }
+}
+
+/// A Visitor that walks over an AST and collects Node's into an AST Map.
+struct NodeCollector<'ast> {
+    map: Vec<MapEntry<'ast>>,
+    /// The node in which we are currently mapping (an item or a method).
+    parent: 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);
+        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 = self.parent;
+        self.parent = 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 = parent;
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        let parent = self.parent;
+        self.parent = ti.id;
+        visit::walk_trait_item(self, ti);
+        self.parent = parent;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        let parent = self.parent;
+        self.parent = ii.id;
+        visit::walk_impl_item(self, ii);
+        self.parent = parent;
+    }
+
+    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)
+        });
+        visit::walk_pat(self, pat);
+    }
+
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        self.insert(expr.id, NodeExpr(expr));
+        visit::walk_expr(self, expr);
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
+        visit::walk_stmt(self, stmt);
+    }
+
+    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
+                b: &'ast Block, s: Span, _: NodeId) {
+        self.visit_fn_decl(fd);
+        visit::walk_fn(self, fk, fd, b, s);
+    }
+
+    fn visit_ty(&mut self, ty: &'ast Ty) {
+        match ty.node {
+            TyBareFn(ref fd) => {
+                self.visit_fn_decl(&*fd.decl);
+            }
+            _ => {}
+        }
+        visit::walk_ty(self, ty);
+    }
+
+    fn visit_block(&mut self, block: &'ast Block) {
+        self.insert(block.id, NodeBlock(block));
+        visit::walk_block(self, block);
+    }
+
+    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, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map<'ast> {
+    // Replace the crate with an empty one to take it out.
+    let krate = mem::replace(&mut forest.krate, Crate {
+        module: Mod {
+            inner: DUMMY_SP,
+            items: vec![],
+        },
+        attrs: vec![],
+        config: vec![],
+        exported_macros: vec![],
+        span: DUMMY_SP
+    });
+    forest.krate = IdAndSpanUpdater { fold_ops: fold_ops }.fold_crate(krate);
+
+    let mut collector = NodeCollector {
+        map: vec![],
+        parent: CRATE_NODE_ID
+    };
+    collector.insert_entry(CRATE_NODE_ID, RootCrate);
+    visit::walk_crate(&mut collector, &forest.krate);
+    let map = collector.map;
+
+    if log_enabled!(::log::DEBUG) {
+        // This only makes sense for ordered stores; note the
+        // enumerate to count the number of entries.
+        let (entries_less_1, _) = map.iter().filter(|&x| {
+            match *x {
+                NotPresent => false,
+                _ => true
+            }
+        }).enumerate().last().expect("AST map was empty after folding?");
+
+        let entries = entries_less_1 + 1;
+        let vector_length = map.len();
+        debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
+              entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
+    }
+
+    Map {
+        forest: forest,
+        map: RefCell::new(map)
+    }
+}
+
+/// Used for items loaded from external crate that are being inlined into this
+/// crate.  The `path` should be the path to the item but should not include
+/// the item itself.
+pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
+                                          path: Vec<PathElem>,
+                                          ii: InlinedItem,
+                                          fold_ops: F)
+                                          -> &'ast InlinedItem {
+    let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
+    let ii = match ii {
+        IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")),
+        IITraitItem(d, ti) => {
+            IITraitItem(fld.fold_ops.new_def_id(d),
+                        fld.fold_trait_item(ti).expect_one("expected one trait item"))
+        }
+        IIImplItem(d, ii) => {
+            IIImplItem(fld.fold_ops.new_def_id(d),
+                       fld.fold_impl_item(ii).expect_one("expected one impl item"))
+        }
+        IIForeign(i) => IIForeign(fld.fold_foreign_item(i))
+    };
+
+    let ii_parent = map.forest.inlined_items.alloc(InlinedParent {
+        path: path,
+        ii: ii
+    });
+
+    let mut collector = NodeCollector {
+        map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
+        parent: fld.new_id(DUMMY_NODE_ID)
+    };
+    let ii_parent_id = collector.parent;
+    collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
+    visit::walk_inlined_item(&mut collector, &ii_parent.ii);
+
+    // 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 {
+        IIItem(_) => {}
+        IITraitItem(_, ref ti) => {
+            collector.insert(ti.id, NodeTraitItem(ti));
+        }
+        IIImplItem(_, ref ii) => {
+            collector.insert(ii.id, NodeImplItem(ii));
+        }
+        IIForeign(ref i) => {
+            collector.insert(i.id, NodeForeignItem(i));
+        }
+    }
+    *map.map.borrow_mut() = collector.map;
+    &ii_parent.ii
+}
+
+pub trait NodePrinter {
+    fn print_node(&mut self, node: &Node) -> io::Result<()>;
+}
+
+impl<'a> NodePrinter for pprust::State<'a> {
+    fn print_node(&mut self, node: &Node) -> io::Result<()> {
+        match *node {
+            NodeItem(a)        => self.print_item(&*a),
+            NodeForeignItem(a) => self.print_foreign_item(&*a),
+            NodeTraitItem(a)   => self.print_trait_item(a),
+            NodeImplItem(a)    => self.print_impl_item(a),
+            NodeVariant(a)     => self.print_variant(&*a),
+            NodeExpr(a)        => self.print_expr(&*a),
+            NodeStmt(a)        => self.print_stmt(&*a),
+            NodePat(a)         => self.print_pat(&*a),
+            NodeBlock(a)       => self.print_block(&*a),
+            NodeLifetime(a)    => self.print_lifetime(&*a),
+
+            // these cases do not carry enough information in the
+            // 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"),
+        }
+    }
+}
+
+fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
+    let id_str = format!(" (id={})", id);
+    let id_str = if include_id { &id_str[..] } else { "" };
+
+    match map.find(id) {
+        Some(NodeItem(item)) => {
+            let path_str = map.path_to_str_with_ident(id, item.ident);
+            let item_str = match item.node {
+                ItemExternCrate(..) => "extern crate",
+                ItemUse(..) => "use",
+                ItemStatic(..) => "static",
+                ItemConst(..) => "const",
+                ItemFn(..) => "fn",
+                ItemMod(..) => "mod",
+                ItemForeignMod(..) => "foreign mod",
+                ItemTy(..) => "ty",
+                ItemEnum(..) => "enum",
+                ItemStruct(..) => "struct",
+                ItemTrait(..) => "trait",
+                ItemImpl(..) => "impl",
+                ItemDefaultImpl(..) => "default impl",
+                ItemMac(..) => "macro"
+            };
+            format!("{} {}{}", item_str, path_str, id_str)
+        }
+        Some(NodeForeignItem(item)) => {
+            let path_str = map.path_to_str_with_ident(id, item.ident);
+            format!("foreign item {}{}", path_str, id_str)
+        }
+        Some(NodeImplItem(ii)) => {
+            match ii.node {
+                ConstImplItem(..) => {
+                    format!("assoc const {} in {}{}",
+                            token::get_ident(ii.ident),
+                            map.path_to_string(id),
+                            id_str)
+                }
+                MethodImplItem(..) => {
+                    format!("method {} in {}{}",
+                            token::get_ident(ii.ident),
+                            map.path_to_string(id), id_str)
+                }
+                TypeImplItem(_) => {
+                    format!("assoc type {} in {}{}",
+                            token::get_ident(ii.ident),
+                            map.path_to_string(id),
+                            id_str)
+                }
+                MacImplItem(ref mac) => {
+                    format!("method macro {}{}",
+                            pprust::mac_to_string(mac), id_str)
+                }
+            }
+        }
+        Some(NodeTraitItem(ti)) => {
+            let kind = match ti.node {
+                ConstTraitItem(..) => "assoc constant",
+                MethodTraitItem(..) => "trait method",
+                TypeTraitItem(..) => "assoc type",
+            };
+
+            format!("{} {} in {}{}",
+                    kind,
+                    token::get_ident(ti.ident),
+                    map.path_to_string(id),
+                    id_str)
+        }
+        Some(NodeVariant(ref variant)) => {
+            format!("variant {} in {}{}",
+                    token::get_ident(variant.node.name),
+                    map.path_to_string(id), id_str)
+        }
+        Some(NodeExpr(ref expr)) => {
+            format!("expr {}{}", pprust::expr_to_string(&**expr), id_str)
+        }
+        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)
+        }
+        Some(NodePat(ref pat)) => {
+            format!("pat {}{}", pprust::pat_to_string(&**pat), id_str)
+        }
+        Some(NodeBlock(ref block)) => {
+            format!("block {}{}", pprust::block_to_string(&**block), id_str)
+        }
+        Some(NodeStructCtor(_)) => {
+            format!("struct_ctor {}{}", map.path_to_string(id), id_str)
+        }
+        Some(NodeLifetime(ref l)) => {
+            format!("lifetime {}{}",
+                    pprust::lifetime_to_string(&**l), id_str)
+        }
+        None => {
+            format!("unknown node{}", id_str)
+        }
+    }
+}
index e9f4860f4514e12049c0ee554de37ae08794fa63..87144bf1e4e63b048958321bd98a9faa87d01c7d 100644 (file)
@@ -176,6 +176,38 @@ for the entire lifetime of a program. Creating a boxed value allocates memory on
 the heap at runtime, and therefore cannot be done at compile time.
 "##,
 
+E0011: r##"
+Initializers for constants and statics are evaluated at compile time.
+User-defined operators rely on user-defined functions, which cannot be evaluated
+at compile time.
+
+Bad example:
+
+```
+use std::ops::Index;
+
+struct Foo { a: u8 }
+
+impl Index<u8> for Foo {
+    type Output = u8;
+
+    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
+}
+
+const a: Foo = Foo { a: 0u8 };
+const b: u8 = a[0]; // Index trait is defined by the user, bad!
+```
+
+Only operators on builtin types are allowed.
+
+Example:
+
+```
+const a: &'static [i32] = &[1, 2, 3];
+const b: i32 = a[0]; // Good!
+```
+"##,
+
 E0013: r##"
 Static and const variables can refer to other const variables. But a const
 variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
@@ -195,10 +227,48 @@ const Y: i32 = A;
 ```
 "##,
 
+E0014: r##"
+Constants can only be initialized by a constant value or, in a future
+version of Rust, a call to a const function. This error indicates the use
+of a path (like a::b, or x) denoting something other than one of these
+allowed items. Example:
+
+```
+const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
+```
+
+To avoid it, you have to replace the non-constant value:
+
+```
+const FOO: i32 = { const X : i32 = 0; X };
+// or even:
+const FOO: i32 = { 0 }; // but brackets are useless here
+```
+"##,
+
 E0015: r##"
-The only function calls allowed in static or constant expressions are enum
-variant constructors or struct constructors (for unit or tuple structs). This
-is because Rust currently does not support compile-time function execution.
+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.
+
+See [RFC 911] for more details on the design of `const fn`s.
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
+E0016: r##"
+Blocks in constants may only contain items (such as constant, function
+definition, etc...) and a tail expression. Example:
+
+```
+const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
+```
+
+To avoid it, you have to replace the non-item object:
+
+```
+const FOO: i32 = { const X : i32 = 0; X };
+```
 "##,
 
 E0018: r##"
@@ -218,9 +288,45 @@ Therefore, casting one of these non-constant pointers to an integer results
 in a non-constant integer which lead to this error. Example:
 
 ```
-const X: u32 = 50;
-const Y: *const u32 = &X;
-println!("{:?}", Y);
+const X: u32 = 1;
+const Y: usize = &X as *const u32 as usize;
+println!("{}", Y);
+```
+"##,
+
+E0019: r##"
+A function call isn't allowed in the const's initialization expression
+because the expression's value must be known at compile-time. Example of
+erroneous code:
+
+```
+enum Test {
+    V1
+}
+
+impl Test {
+    fn test(&self) -> i32 {
+        12
+    }
+}
+
+fn main() {
+    const FOO: Test = Test::V1;
+
+    const A: i32 = FOO.test(); // You can't call Test::func() here !
+}
+```
+
+Remember: you can't use a function call inside a const's initialization
+expression! However, you can totally use it elsewhere you want:
+
+```
+fn main() {
+    const FOO: Test = Test::V1;
+
+    FOO.func(); // here is good
+    let x = FOO.func(); // or even here!
+}
 ```
 "##,
 
@@ -257,8 +363,8 @@ http://doc.rust-lang.org/reference.html#ffi-attributes
 E0133: r##"
 Using unsafe functionality, such as dereferencing raw pointers and calling
 functions via FFI or marked as unsafe, is potentially dangerous and disallowed
-by safety checks. As such, those safety checks can be temporarily relaxed by
-wrapping the unsafe instructions inside an `unsafe` block. For instance:
+by safety checks. These safety checks can be relaxed for a section of the code
+by wrapping the unsafe instructions with an `unsafe` block. For instance:
 
 ```
 unsafe fn f() { return; }
@@ -396,6 +502,54 @@ enum Method { GET, POST }
 ```
 "##,
 
+E0261: r##"
+When using a lifetime like `'a` in a type, it must be declared before being
+used.
+
+These two examples illustrate the problem:
+
+```
+// error, use of undeclared lifetime name `'a`
+fn foo(x: &'a str) { }
+
+struct Foo {
+    // error, use of undeclared lifetime name `'a`
+    x: &'a str,
+}
+```
+
+These can be fixed by declaring lifetime parameters:
+
+```
+fn foo<'a>(x: &'a str) { }
+
+struct Foo<'a> {
+    x: &'a str,
+}
+```
+"##,
+
+E0262: r##"
+Declaring certain lifetime names in parameters is disallowed. For example,
+because the `'static` lifetime is a special built-in lifetime name denoting
+the lifetime of the entire program, this is an error:
+
+```
+// error, illegal lifetime parameter name `'static`
+fn foo<'static>(x: &'static str) { }
+```
+"##,
+
+E0263: r##"
+A lifetime name cannot be declared more than once in the same scope. For
+example:
+
+```
+// error, lifetime name `'a` declared twice in the same scope
+fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
+```
+"##,
+
 E0265: r##"
 This error indicates that a static or constant references itself.
 All statics and constants need to resolve to a value in an acyclic manner.
@@ -475,7 +629,7 @@ impl Trait for i8 { type AssociatedType = &'static str; }
 
 foo(3_i8);
 // Here, we invoke `foo` with an `i8`, which does not satisfy
-// the constraint `<i8 as Trait>::AssociatedType=32`, and
+// the constraint `<i8 as Trait>::AssociatedType=u32`, and
 // therefore the type-checker complains with this error code.
 ```
 
@@ -794,18 +948,96 @@ struct Foo<T: 'static> {
     foo: &'static T
 }
 ```
+"##,
+
+E0378: r##"
+Method calls that aren't calls to inherent `const` methods are disallowed
+in statics, constants, and constant functions.
+
+For example:
+
+```
+const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
+
+struct Foo(i32);
+
+impl Foo {
+    const fn foo(&self) -> i32 {
+        self.bar() // error, `bar` isn't `const`
+    }
+
+    fn bar(&self) -> i32 { self.0 }
+}
+```
+
+For more information about `const fn`'s, see [RFC 911].
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
+E0394: r##"
+From [RFC 246]:
+
+ > It is illegal for a static to reference another static by value. It is
+ > required that all references be borrowed.
+
+[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
+"##,
+
+E0397: r##"
+It is not allowed for a mutable static to allocate or have destructors. For
+example:
+
+```
+// error: mutable statics are not allowed to have boxes
+static mut FOO: Option<Box<usize>> = None;
+
+// error: mutable statics are not allowed to have destructors
+static mut BAR: Option<Vec<i32>> = None;
+```
+"##,
+
+E0398: r##"
+In Rust 1.3, the default object lifetime bounds are expected to
+change, as described in RFC #1156 [1]. You are getting a warning
+because the compiler thinks it is possible that this change will cause
+a compilation error in your code. It is possible, though unlikely,
+that this is a false alarm.
+
+The heart of the change is that where `&'a Box<SomeTrait>` used to
+default to `&'a Box<SomeTrait+'a>`, it now defaults to `&'a
+Box<SomeTrait+'static>` (here, `SomeTrait` is the name of some trait
+type). Note that the only types which are affected are references to
+boxes, like `&Box<SomeTrait>` or `&[Box<SomeTrait>]`.  More common
+types like `&SomeTrait` or `Box<SomeTrait>` are unaffected.
+
+To silence this warning, edit your code to use an explicit bound.
+Most of the time, this means that you will want to change the
+signature of a function that you are calling. For example, if
+the error is reported on a call like `foo(x)`, and `foo` is
+defined as follows:
+
+```
+fn foo(arg: &Box<SomeTrait>) { ... }
+```
+
+you might change it to:
+
+```
+fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
+```
+
+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
 "##
 
 }
 
 
 register_diagnostics! {
-    E0011,
-    E0012,
-    E0014,
-    E0016,
     E0017,
-    E0019,
     E0022,
     E0038,
     E0109,
@@ -815,9 +1047,6 @@ register_diagnostics! {
     E0136,
     E0138,
     E0139,
-    E0261, // use of undeclared lifetime name
-    E0262, // illegal lifetime parameter name
-    E0263, // lifetime name declared twice in same scope
     E0264, // unknown external lang item
     E0266, // expected item
     E0269, // not all control paths return a value
@@ -846,5 +1075,7 @@ register_diagnostics! {
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
     E0316, // nested quantification of lifetimes
-    E0370  // discriminant overflow
+    E0370, // discriminant overflow
+    E0395, // pointer comparison in const-expr
+    E0396  // pointer dereference in const-expr
 }
index 12d6fcd0303ec0d1f1b31ffa555bdc29710e7053..c19ba19f5b76bed5d8a48e471ae95c488303eadf 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![feature(append)]
 #![feature(associated_consts)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(clone_from_slice)]
 #![feature(collections)]
-#![feature(core)]
+#![feature(const_fn)]
 #![feature(duration)]
 #![feature(duration_span)]
+#![feature(dynamic_lib)]
+#![feature(enumset)]
 #![feature(fs_canonicalize)]
-#![feature(hash)]
+#![feature(hash_default)]
+#![feature(hashmap_hasher)]
 #![feature(into_cow)]
+#![feature(iter_cmp)]
+#![feature(iter_arith)]
 #![feature(libc)]
+#![feature(map_in_place)]
+#![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_bytes)]
+#![feature(slice_extras)]
 #![feature(slice_patterns)]
+#![feature(slice_position_elem)]
 #![feature(staged_api)]
-#![feature(std_misc)]
 #![feature(str_char)]
+#![feature(str_match_indices)]
+#![feature(vec_push_all)]
+#![feature(wrapping)]
 #![cfg_attr(test, feature(test))]
 
 #![allow(trivial_casts)]
@@ -91,9 +108,12 @@ pub mod back {
     pub use rustc_back::x86_64;
 }
 
+pub mod ast_map;
+
 pub mod middle {
     pub mod astconv_util;
     pub mod astencode;
+    pub mod cast;
     pub mod cfg;
     pub mod check_const;
     pub mod check_static_recursion;
@@ -166,7 +186,4 @@ mod rustc {
 }
 
 // Build the diagnostics array at the end so that the metadata includes error use sites.
-#[cfg(stage0)]
-__build_diagnostic_array! { DIAGNOSTICS }
-#[cfg(not(stage0))]
 __build_diagnostic_array! { librustc, DIAGNOSTICS }
index 9688447dc046a50f3f3996333d98c82354d20442..567be56b17f29687f34c7a47b090475d0cbaa877 100644 (file)
@@ -28,9 +28,8 @@ use self::TargetLint::*;
 use middle::privacy::ExportedItems;
 use middle::ty::{self, Ty};
 use session::{early_error, Session};
-use session::config::UnstableFeatures;
 use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject};
-use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid, ReleaseChannel};
+use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
 use util::nodemap::FnvHashMap;
 
@@ -208,23 +207,6 @@ impl LintStore {
             }
         }
     }
-
-    fn maybe_stage_features(&mut self, sess: &Session) {
-        let lvl = match sess.opts.unstable_features {
-            UnstableFeatures::Default => return,
-            UnstableFeatures::Disallow => Forbid,
-            UnstableFeatures::Cheat => Allow
-        };
-        match self.by_name.get("unstable_features") {
-            Some(&Id(lint_id)) => if self.get_level_source(lint_id).0 != Forbid {
-                self.set_level(lint_id, (lvl, ReleaseChannel))
-            },
-            Some(&Renamed(_, lint_id)) => if self.get_level_source(lint_id).0 != Forbid {
-                self.set_level(lint_id, (lvl, ReleaseChannel))
-            },
-            None => unreachable!()
-        }
-    }
 }
 
 /// Context for lint checking.
@@ -308,7 +290,6 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
 
     let name = lint.name_lower();
     let mut def = None;
-    let mut note = None;
     let msg = match source {
         Default => {
             format!("{}, #[{}({})] on by default", msg,
@@ -325,12 +306,6 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
             def = Some(src);
             msg.to_string()
         }
-        ReleaseChannel => {
-            let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
-            note = Some(format!("this feature may not be used in the {} release channel",
-                                release_channel));
-            msg.to_string()
-        }
     };
 
     // For purposes of printing, we can treat forbid as deny.
@@ -344,10 +319,6 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
         _ => sess.bug("impossible level in raw_emit_lint"),
     }
 
-    if let Some(note) = note {
-        sess.note(&note[..]);
-    }
-
     if let Some(span) = def {
         sess.span_note(span, "lint level defined here");
     }
@@ -689,9 +660,6 @@ impl LintPass for GatherNodeLevels {
 pub fn check_crate(tcx: &ty::ctxt,
                    exported_items: &ExportedItems) {
 
-    // If this is a feature-staged build of rustc then flip several lints to 'forbid'
-    tcx.sess.lint_store.borrow_mut().maybe_stage_features(&tcx.sess);
-
     let krate = tcx.map.krate();
     let mut cx = Context::new(tcx, krate, exported_items);
 
@@ -712,7 +680,7 @@ pub fn check_crate(tcx: &ty::ctxt,
 
     // If we missed any lints added to the session, then there's a bug somewhere
     // in the iteration code.
-    for (id, v) in &*tcx.sess.lints.borrow() {
+    for (id, v) in tcx.sess.lints.borrow().iter() {
         for &(lint, span, ref msg) in v {
             tcx.sess.span_bug(span,
                               &format!("unprocessed lint {} at {}: {}",
index 498b2ce518c16dc6055166053e19ed7ac5cb8b20..fe893f6270203ddaf9708448c1885b7f1c3b94c8 100644 (file)
@@ -101,9 +101,8 @@ macro_rules! declare_lint {
 #[macro_export]
 macro_rules! lint_array { ($( $lint:expr ),*) => (
     {
-        #[allow(non_upper_case_globals)]
-        static array: LintArray = &[ $( &$lint ),* ];
-        array
+        static ARRAY: LintArray = &[ $( &$lint ),* ];
+        ARRAY
     }
 ) }
 
@@ -248,9 +247,6 @@ pub enum LintSource {
 
     /// Lint level was set by a command-line flag.
     CommandLine,
-
-    /// Lint level was set by the release channel.
-    ReleaseChannel
 }
 
 pub type LevelSource = (Level, LintSource);
index f410626714f4805752e5579368e504a90ece5d4b..5f785fefa1241f93c50eb644a5d05daf467c348b 100644 (file)
@@ -146,8 +146,9 @@ enum_from_u32! {
         tag_table_closure_kinds = 0x65,
         tag_table_upvar_capture_map = 0x66,
         tag_table_capture_modes = 0x67,
-        tag_table_object_cast_map = 0x68,
+        // GAP 0x68
         tag_table_const_qualif = 0x69,
+        tag_table_cast_kinds = 0x6a,
     }
 }
 
@@ -261,3 +262,5 @@ pub const tag_item_super_predicates: usize = 0xa3;
 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;
index 12112fd45ebe9b2d0911992f79cc1e7bd4c0b38e..8562d8c01cc67d9cc8fceb76608a0da129c4e9c0 100644 (file)
@@ -21,6 +21,7 @@ use metadata::decoder;
 use metadata::loader;
 use metadata::loader::CratePaths;
 
+use std::cell::RefCell;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::fs;
@@ -376,14 +377,13 @@ impl<'a> CrateReader<'a> {
         let loader::Library { dylib, rlib, metadata } = lib;
 
         let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span);
-        let codemap_import_info = import_codemap(self.sess.codemap(), &metadata);
 
         let cmeta = Rc::new( cstore::crate_metadata {
             name: name.to_string(),
             data: metadata,
             cnum_map: cnum_map,
             cnum: cnum,
-            codemap_import_info: codemap_import_info,
+            codemap_import_info: RefCell::new(vec![]),
             span: span,
         });
 
@@ -616,9 +616,9 @@ impl<'a> CrateReader<'a> {
 /// file they represent, just information about length, line breaks, and
 /// multibyte characters. This information is enough to generate valid debuginfo
 /// for items inlined from other crates.
-fn import_codemap(local_codemap: &codemap::CodeMap,
-                  metadata: &MetadataBlob)
-                  -> Vec<cstore::ImportedFileMap> {
+pub fn import_codemap(local_codemap: &codemap::CodeMap,
+                      metadata: &MetadataBlob)
+                      -> Vec<cstore::ImportedFileMap> {
     let external_codemap = decoder::get_imported_filemaps(metadata.as_slice());
 
     let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| {
index 8a35c0120049024a49f105571b21c78d8026948d..4e0cf7b0e4cd4e4cdadf5a8cfb495feff188cd74 100644 (file)
 
 // Searching for information from the cstore
 
+use ast_map;
 use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
-use middle::def;
 use middle::lang_items;
 use middle::ty;
 
@@ -21,7 +21,6 @@ use rbml;
 use rbml::reader;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::expect;
@@ -114,12 +113,6 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
     decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
 }
 
-pub fn get_enum_variant_defs(cstore: &cstore::CStore, enum_id: ast::DefId)
-                             -> Vec<(def::Def, ast::Name, ast::Visibility)> {
-    let cdata = cstore.get_crate_data(enum_id.krate);
-    decoder::get_enum_variant_defs(&*cstore.intr, &*cdata, enum_id.node)
-}
-
 pub fn get_enum_variants<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
                                -> Vec<Rc<ty::VariantInfo<'tcx>>> {
     let cstore = &tcx.sess.cstore;
@@ -297,15 +290,6 @@ pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
     decoder::get_impl_trait(&*cdata, def.node, tcx)
 }
 
-// Given a def_id for an impl, return information about its vtables
-pub fn get_impl_vtables<'tcx>(tcx: &ty::ctxt<'tcx>,
-                              def: ast::DefId)
-                              -> ty::vtable_res<'tcx> {
-    let cstore = &tcx.sess.cstore;
-    let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_vtables(&*cdata, def.node, tcx)
-}
-
 pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
                             -> Vec<(cstore::NativeLibraryKind, String)> {
     let cdata = cstore.get_crate_data(crate_num);
@@ -384,6 +368,16 @@ pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
     decoder::is_typedef(&*cdata, did.node)
 }
 
+pub fn is_const_fn(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(did.krate);
+    decoder::is_const_fn(&*cdata, did.node)
+}
+
+pub fn is_impl(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(did.krate);
+    decoder::is_impl(&*cdata, did.node)
+}
+
 pub fn get_stability(cstore: &cstore::CStore,
                      def: ast::DefId)
                      -> Option<attr::Stability> {
@@ -391,8 +385,8 @@ pub fn get_stability(cstore: &cstore::CStore,
     decoder::get_stability(&*cdata, def.node)
 }
 
-pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool {
-    let cdata = cstore.get_crate_data(def.krate);
+pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
+    let cdata = cstore.get_crate_data(krate);
     let attrs = decoder::get_crate_attributes(cdata.data());
     for attr in &attrs {
         if &attr.name()[..] == "staged_api" {
@@ -409,11 +403,6 @@ pub fn get_repr_attrs(cstore: &cstore::CStore, def: ast::DefId)
     decoder::get_repr_attrs(&*cdata, def.node)
 }
 
-pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
-    let cdata = cstore.get_crate_data(def.krate);
-    decoder::is_associated_type(&*cdata, def.node)
-}
-
 pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> bool {
     let cdata = cstore.get_crate_data(trait_def_id.krate);
     decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
index 1f18b13fc46fe26fff04ab9c29d40db0d2f499fd..3112e8f4b4cfd21cac9212b13ff0c19450426c29 100644 (file)
@@ -18,12 +18,11 @@ pub use self::LinkagePreference::*;
 pub use self::NativeLibraryKind::*;
 
 use back::svh::Svh;
-use metadata::decoder;
-use metadata::loader;
+use metadata::{creader, decoder, loader};
 use session::search_paths::PathKind;
 use util::nodemap::{FnvHashMap, NodeMap};
 
-use std::cell::RefCell;
+use std::cell::{RefCell, Ref};
 use std::rc::Rc;
 use std::path::PathBuf;
 use flate::Bytes;
@@ -58,7 +57,7 @@ pub struct crate_metadata {
     pub data: MetadataBlob,
     pub cnum_map: cnum_map,
     pub cnum: ast::CrateNum,
-    pub codemap_import_info: Vec<ImportedFileMap>,
+    pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
     pub span: codemap::Span,
 }
 
@@ -128,7 +127,7 @@ impl CStore {
     pub fn iter_crate_data<I>(&self, mut i: I) where
         I: FnMut(ast::CrateNum, &crate_metadata),
     {
-        for (&k, v) in &*self.metas.borrow() {
+        for (&k, v) in self.metas.borrow().iter() {
             i(k, &**v);
         }
     }
@@ -137,7 +136,7 @@ impl CStore {
     pub fn iter_crate_data_origins<I>(&self, mut i: I) where
         I: FnMut(ast::CrateNum, &crate_metadata, Option<CrateSource>),
     {
-        for (&k, v) in &*self.metas.borrow() {
+        for (&k, v) in self.metas.borrow().iter() {
             let origin = self.get_used_crate_source(k);
             origin.as_ref().map(|cs| { assert!(k == cs.cnum); });
             i(k, &**v, origin);
@@ -186,7 +185,7 @@ impl CStore {
             }
             ordering.push(cnum);
         };
-        for (&num, _) in &*self.metas.borrow() {
+        for (&num, _) in self.metas.borrow().iter() {
             visit(self, num, &mut ordering);
         }
         ordering.reverse();
@@ -240,6 +239,20 @@ impl crate_metadata {
     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
     pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
     pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
+    pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
+                                 -> Ref<'a, Vec<ImportedFileMap>> {
+        let filemaps = self.codemap_import_info.borrow();
+        if filemaps.is_empty() {
+            drop(filemaps);
+            let filemaps = creader::import_codemap(codemap, &self.data);
+
+            // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
+            *self.codemap_import_info.borrow_mut() = filemaps;
+            self.codemap_import_info.borrow()
+        } else {
+            filemaps
+        }
+    }
 }
 
 impl MetadataBlob {
index 2f2a5d31c9f77aaf25087c681d255061bbd3acbf..5a79ef203b4b39162e63d05b7d2bd5f9ea68464e 100644 (file)
@@ -15,6 +15,7 @@
 pub use self::DefLike::*;
 use self::Family::*;
 
+use ast_map;
 use back::svh::Svh;
 use metadata::cstore::crate_metadata;
 use metadata::common::*;
@@ -30,7 +31,6 @@ use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
 use middle::ty::{self, Ty};
-use middle::astencode::vtable_decoder_helpers;
 use util::nodemap::FnvHashMap;
 
 use std::cell::{Cell, RefCell};
@@ -45,7 +45,6 @@ use std::str;
 use rbml::reader;
 use rbml;
 use serialize::Decodable;
-use syntax::ast_map;
 use syntax::attr;
 use syntax::parse::token::{IdentInterner, special_idents};
 use syntax::parse::token;
@@ -77,19 +76,12 @@ fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option<rbml:
     let pos = u32_from_be_bytes(&d.data[hash_pos..]) as usize;
     let tagged_doc = reader::doc_at(d.data, pos).unwrap();
 
-    let belt = tag_index_buckets_bucket_elt;
-
-    let mut ret = None;
-    reader::tagged_docs(tagged_doc.doc, belt, |elt| {
+    reader::tagged_docs(tagged_doc.doc, tag_index_buckets_bucket_elt).find(|elt| {
+        eq_fn(&elt.data[elt.start + 4 .. elt.end])
+    }).map(|elt| {
         let pos = u32_from_be_bytes(&elt.data[elt.start..]) as usize;
-        if eq_fn(&elt.data[elt.start + 4 .. elt.end]) {
-            ret = Some(reader::doc_at(d.data, pos).unwrap().doc);
-            false
-        } else {
-            true
-        }
-    });
-    ret
+        reader::doc_at(d.data, pos).unwrap().doc
+    })
 }
 
 pub fn maybe_find_item<'a>(item_id: ast::NodeId,
@@ -178,13 +170,23 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
     }
 }
 
+fn fn_constness(item: rbml::Doc) -> ast::Constness {
+    match reader::maybe_get_doc(item, tag_items_data_item_constness) {
+        None => ast::Constness::NotConst,
+        Some(constness_doc) => {
+            match reader::doc_as_u8(constness_doc) as char {
+                'c' => ast::Constness::Const,
+                'n' => ast::Constness::NotConst,
+                _ => panic!("unknown constness character")
+            }
+        }
+    }
+}
+
 fn item_sort(item: rbml::Doc) -> Option<char> {
-    let mut ret = None;
-    reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
-        ret = Some(doc.as_str_slice().as_bytes()[0] as char);
-        false
-    });
-    ret
+    reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| {
+        doc.as_str_slice().as_bytes()[0] as char
+    })
 }
 
 fn item_symbol(item: rbml::Doc) -> String {
@@ -198,12 +200,9 @@ fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
 }
 
 fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<ast::DefId> {
-    let mut ret = None;
-    reader::tagged_docs(d, tag_items_data_parent_item, |did| {
-        ret = Some(translated_def_id(cdata, did));
-        false
-    });
-    ret
+    reader::tagged_docs(d, tag_items_data_parent_item).nth(0).map(|did| {
+        translated_def_id(cdata, did)
+    })
 }
 
 fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
@@ -220,10 +219,8 @@ fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option<ast::DefId> {
     })
 }
 
-fn each_reexport<F>(d: rbml::Doc, f: F) -> bool where
-    F: FnMut(rbml::Doc) -> bool,
-{
-    reader::tagged_docs(d, tag_items_data_item_reexport, f)
+fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
+    reader::tagged_docs(d, tag_items_data_item_reexport)
 }
 
 fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
@@ -240,6 +237,13 @@ fn doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx>
                   |_, did| translate_def_id(cdata, did))
 }
 
+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| {
+        parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
+                      |_, did| translate_def_id(cdata, did))
+    })
+}
+
 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);
@@ -264,36 +268,20 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
     doc_trait_ref(tp, tcx, cdata)
 }
 
-fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec<ast::DefId> {
-    let mut ids = vec![];
-    reader::tagged_docs(item, tag_items_data_item_variant, |p| {
-        ids.push(translated_def_id(cdata, p));
-        true
-    });
-    ids
-}
-
 fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
     let path_doc = reader::get_doc(item_doc, tag_path);
-
-    let len_doc = reader::get_doc(path_doc, tag_path_len);
-    let len = reader::doc_as_u32(len_doc) as usize;
-
-    let mut result = Vec::with_capacity(len);
-    reader::docs(path_doc, |tag, elt_doc| {
+    reader::docs(path_doc).filter_map(|(tag, elt_doc)| {
         if tag == tag_path_elem_mod {
             let s = elt_doc.as_str_slice();
-            result.push(ast_map::PathMod(token::intern(s)));
+            Some(ast_map::PathMod(token::intern(s)))
         } else if tag == tag_path_elem_name {
             let s = elt_doc.as_str_slice();
-            result.push(ast_map::PathName(token::intern(s)));
+            Some(ast_map::PathName(token::intern(s)))
         } else {
             // ignore tag_path_len element
+            None
         }
-        true
-    });
-
-    result
+    }).collect()
 }
 
 fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
@@ -394,13 +382,9 @@ fn parse_polarity(item_doc: rbml::Doc) -> ast::ImplPolarity {
 
 fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
     let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
-    let mut names = Vec::new();
-    reader::tagged_docs(names_doc, tag_associated_type_name, |name_doc| {
-        let name = token::intern(name_doc.as_str_slice());
-        names.push(name);
-        true
-    });
-    names
+    reader::tagged_docs(names_doc, tag_associated_type_name)
+        .map(|name_doc| token::intern(name_doc.as_str_slice()))
+        .collect()
 }
 
 pub fn get_trait_def<'tcx>(cdata: Cmd,
@@ -516,18 +500,6 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
     }
 }
 
-pub fn get_impl_vtables<'tcx>(cdata: Cmd,
-                              id: ast::NodeId,
-                              tcx: &ty::ctxt<'tcx>)
-                              -> ty::vtable_res<'tcx>
-{
-    let item_doc = lookup_item(id, cdata.data());
-    let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
-    let mut decoder = reader::Decoder::new(vtables_doc);
-    decoder.read_vtable_res(tcx, cdata)
-}
-
-
 pub fn get_symbol(data: &[u8], id: ast::NodeId) -> String {
     return item_symbol(lookup_item(id, data));
 }
@@ -546,7 +518,7 @@ pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
 {
     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|item_doc| {
+    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,
@@ -566,7 +538,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
     G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     // Iterate over all children.
-    let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| {
+    for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) {
         let child_def_id = translated_def_id(cdata, child_info_doc);
 
         // This item may be in yet another crate if it was the child of a
@@ -592,26 +564,20 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
                 let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
                 let visibility = item_visibility(child_item_doc);
                 callback(def_like, child_name, visibility);
-
             }
         }
-
-        true
-    });
+    }
 
     // As a special case, iterate over all static methods of
     // associated implementations too. This is a bit of a botch.
     // --pcwalton
-    let _ = reader::tagged_docs(item_doc,
-                                tag_items_data_item_inherent_impl,
-                                |inherent_impl_def_id_doc| {
-        let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc,
-                                               cdata);
+    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);
         let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
         if let Some(inherent_impl_doc) = maybe_find_item(inherent_impl_def_id.node, items) {
-            let _ = reader::tagged_docs(inherent_impl_doc,
-                                        tag_item_impl_item,
-                                        |impl_item_def_id_doc| {
+            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) = maybe_find_item(impl_item_def_id.node, items) {
@@ -625,14 +591,11 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
                                  item_visibility(impl_method_doc));
                     }
                 }
-                true
-            });
+            }
         }
-        true
-    });
+    }
 
-    // Iterate over all reexports.
-    let _ = each_reexport(item_doc, |reexport_doc| {
+    for reexport_doc in reexports(item_doc) {
         let def_id_doc = reader::get_doc(reexport_doc,
                                          tag_items_data_item_reexport_def_id);
         let child_def_id = translated_def_id(cdata, def_id_doc);
@@ -662,9 +625,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
             // a public re-export.
             callback(def_like, token::intern(name), ast::Public);
         }
-
-        true
-    });
+    }
 }
 
 /// Iterates over each child of the given item.
@@ -745,37 +706,20 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
     }
 }
 
-pub fn get_enum_variant_defs(intr: &IdentInterner,
-                             cdata: Cmd,
-                             id: ast::NodeId)
-                             -> Vec<(def::Def, ast::Name, ast::Visibility)> {
-    let data = cdata.data();
-    let items = reader::get_doc(rbml::Doc::new(data), tag_items);
-    let item = find_item(id, items);
-    enum_variant_ids(item, cdata).iter().map(|did| {
-        let item = find_item(did.node, items);
-        let name = item_name(intr, item);
-        let visibility = item_visibility(item);
-        match item_to_def_like(cdata, item, *did) {
-            DlDef(def @ def::DefVariant(..)) => (def, name, visibility),
-            _ => unreachable!()
-        }
-    }).collect()
-}
-
 pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
                                tcx: &ty::ctxt<'tcx>) -> Vec<Rc<ty::VariantInfo<'tcx>>> {
     let data = cdata.data();
     let items = reader::get_doc(rbml::Doc::new(data), tag_items);
     let item = find_item(id, items);
     let mut disr_val = 0;
-    enum_variant_ids(item, cdata).iter().map(|did| {
+    reader::tagged_docs(item, tag_items_data_item_variant).map(|p| {
+        let did = translated_def_id(cdata, p);
         let item = find_item(did.node, items);
         let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
                                 item, tcx, cdata);
         let name = item_name(&*intr, item);
         let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
-            ty::ty_bare_fn(_, ref f) =>
+            ty::TyBareFn(_, ref f) =>
                 (Some(ctor_ty), f.sig.0.inputs.clone(), None),
             _ => { // Nullary or struct enum variant.
                 let mut arg_names = Vec::new();
@@ -804,7 +748,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
             name: name,
             // I'm not even sure if we encode visibility
             // for variants -- TEST -- tjc
-            id: *did,
+            id: did,
             disr_val: old_disr_val,
             vis: ast::Inherited
         })
@@ -841,22 +785,15 @@ 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)
                       -> Vec<ty::ImplOrTraitItemId> {
-    let mut impl_items = Vec::new();
-    reader::tagged_docs(lookup_item(impl_id, cdata.data()),
-                        tag_item_impl_item, |doc| {
+    reader::tagged_docs(lookup_item(impl_id, cdata.data()), tag_item_impl_item).map(|doc| {
         let def_id = item_def_id(doc, cdata);
         match item_sort(doc) {
-            Some('C') => impl_items.push(ty::ConstTraitItemId(def_id)),
-            Some('r') | Some('p') => {
-                impl_items.push(ty::MethodTraitItemId(def_id))
-            }
-            Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)),
+            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"),
         }
-        true
-    });
-
-    impl_items
+    }).collect()
 }
 
 pub fn get_trait_name(intr: Rc<IdentInterner>,
@@ -882,24 +819,24 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                     id: ast::NodeId,
                                     tcx: &ty::ctxt<'tcx>)
                                     -> ty::ImplOrTraitItem<'tcx> {
-    let method_doc = lookup_item(id, cdata.data());
+    let item_doc = lookup_item(id, cdata.data());
 
-    let def_id = item_def_id(method_doc, cdata);
+    let def_id = item_def_id(item_doc, cdata);
 
-    let container_id = item_require_parent_item(cdata, method_doc);
+    let container_id = item_require_parent_item(cdata, item_doc);
     let container_doc = lookup_item(container_id.node, cdata.data());
     let container = match item_family(container_doc) {
         Trait => TraitContainer(container_id),
         _ => ImplContainer(container_id),
     };
 
-    let name = item_name(&*intr, method_doc);
-    let vis = item_visibility(method_doc);
+    let name = item_name(&*intr, item_doc);
+    let vis = item_visibility(item_doc);
 
-    match item_sort(method_doc) {
+    match item_sort(item_doc) {
         Some('C') => {
-            let ty = doc_type(method_doc, tcx, cdata);
-            let default = get_provided_source(method_doc, cdata);
+            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,
@@ -910,11 +847,11 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
             }))
         }
         Some('r') | Some('p') => {
-            let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
-            let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
-            let fty = doc_method_fty(method_doc, tcx, cdata);
-            let explicit_self = get_explicit_self(method_doc);
-            let provided_source = get_provided_source(method_doc, cdata);
+            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 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,
@@ -927,8 +864,10 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                                         provided_source)))
         }
         Some('t') => {
+            let ty = maybe_doc_type(item_doc, tcx, cdata);
             ty::TypeTraitItem(Rc::new(ty::AssociatedType {
                 name: name,
+                ty: ty,
                 vis: vis,
                 def_id: def_id,
                 container: container,
@@ -942,20 +881,15 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
                               -> Vec<ty::ImplOrTraitItemId> {
     let data = cdata.data();
     let item = lookup_item(id, data);
-    let mut result = Vec::new();
-    reader::tagged_docs(item, tag_item_trait_item, |mth| {
+    reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
         let def_id = item_def_id(mth, cdata);
         match item_sort(mth) {
-            Some('C') => result.push(ty::ConstTraitItemId(def_id)),
-            Some('r') | Some('p') => {
-                result.push(ty::MethodTraitItemId(def_id));
-            }
-            Some('t') => result.push(ty::TypeTraitItemId(def_id)),
+            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"),
         }
-        true
-    });
-    result
+    }).collect()
 }
 
 pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
@@ -973,9 +907,8 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                         -> Vec<Rc<ty::Method<'tcx>>> {
     let data = cdata.data();
     let item = lookup_item(id, data);
-    let mut result = Vec::new();
 
-    reader::tagged_docs(item, tag_item_trait_item|mth_id| {
+    reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| {
         let did = item_def_id(mth_id, cdata);
         let mth = lookup_item(did.node, data);
 
@@ -985,13 +918,14 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                                     did.node,
                                                     tcx);
             if let ty::MethodTraitItem(ref method) = trait_item {
-                result.push((*method).clone())
+                Some((*method).clone())
+            } else {
+                None
             }
+        } else {
+            None
         }
-        true
-    });
-
-    return result;
+    }).collect()
 }
 
 pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
@@ -1001,10 +935,9 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
                                    -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let data = cdata.data();
     let item = lookup_item(id, data);
-    let mut result = Vec::new();
 
-    for &tag in &[tag_item_trait_item, tag_item_impl_item] {
-        reader::tagged_docs(item, tag|ac_id| {
+    [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 = lookup_item(did.node, data);
 
@@ -1014,14 +947,15 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
                                                         did.node,
                                                         tcx);
                 if let ty::ConstTraitItem(ref ac) = trait_item {
-                    result.push((*ac).clone())
+                    Some((*ac).clone())
+                } else {
+                    None
                 }
+            } else {
+                None
             }
-            true
-        });
-    }
-
-    return result;
+        })
+    }).collect()
 }
 
 pub fn get_type_name_if_impl(cdata: Cmd,
@@ -1031,13 +965,9 @@ pub fn get_type_name_if_impl(cdata: Cmd,
         return None;
     }
 
-    let mut ret = None;
-    reader::tagged_docs(item, tag_item_impl_type_basename, |doc| {
-        ret = Some(token::intern(doc.as_str_slice()));
-        false
-    });
-
-    ret
+    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>,
@@ -1050,20 +980,15 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
     }
 
     // If this impl implements a trait, don't consider it.
-    let ret = reader::tagged_docs(item, tag_item_trait_ref, |_doc| {
-        false
-    });
-
-    if !ret { return None }
+    if reader::tagged_docs(item, tag_item_trait_ref).next().is_some() {
+        return None;
+    }
 
-    let mut impl_method_ids = Vec::new();
-    reader::tagged_docs(item, tag_item_impl_item, |impl_method_doc| {
-        impl_method_ids.push(item_def_id(impl_method_doc, cdata));
-        true
-    });
+    let impl_method_ids = reader::tagged_docs(item, tag_item_impl_item)
+        .map(|impl_method_doc| item_def_id(impl_method_doc, cdata));
 
     let mut impl_methods = Vec::new();
-    for impl_method_id in &impl_method_ids {
+    for impl_method_id in impl_method_ids {
         let impl_method_doc = lookup_item(impl_method_id.node, cdata.data());
         let family = item_family(impl_method_doc);
         match family {
@@ -1088,12 +1013,9 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
     -> Option<ast::DefId>
 {
     let item = lookup_item(node_id, cdata.data());
-    let mut ret = None;
-    reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| {
-        ret = Some(item_require_parent_item(cdata, item));
-        false
-    });
-    ret
+    reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| {
+        item_require_parent_item(cdata, item)
+    })
 }
 
 pub fn get_item_attrs(cdata: Cmd,
@@ -1111,14 +1033,11 @@ pub fn get_item_attrs(cdata: Cmd,
 pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
     let data = rbml::Doc::new(cdata.data());
     let fields = reader::get_doc(data, tag_struct_fields);
-    let mut map = HashMap::new();
-    reader::tagged_docs(fields, tag_struct_field, |field| {
+    reader::tagged_docs(fields, tag_struct_field).map(|field| {
         let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
         let attrs = get_attributes(field);
-        map.insert(id, attrs);
-        true
-    });
-    map
+        (id, attrs)
+    }).collect()
 }
 
 fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
@@ -1133,81 +1052,69 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
     -> Vec<ty::field_ty> {
     let data = cdata.data();
     let item = lookup_item(id, data);
-    let mut result = Vec::new();
-    reader::tagged_docs(item, tag_item_field, |an_item| {
+    reader::tagged_docs(item, tag_item_field).filter_map(|an_item| {
         let f = item_family(an_item);
         if f == PublicField || f == InheritedField {
             let name = item_name(&*intr, an_item);
             let did = item_def_id(an_item, cdata);
             let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
             let origin_id =  translated_def_id(cdata, tagdoc);
-            result.push(ty::field_ty {
+            Some(ty::field_ty {
                 name: name,
                 id: did,
                 vis: struct_field_family_to_visibility(f),
                 origin: origin_id,
-            });
+            })
+        } else {
+            None
         }
-        true
-    });
-    reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
+    }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|an_item| {
         let did = item_def_id(an_item, cdata);
         let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
         let f = item_family(an_item);
         let origin_id =  translated_def_id(cdata, tagdoc);
-        result.push(ty::field_ty {
+        ty::field_ty {
             name: special_idents::unnamed_field.name,
             id: did,
             vis: struct_field_family_to_visibility(f),
             origin: origin_id,
-        });
-        true
-    });
-    result
+        }
+    })).collect()
 }
 
 fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
-    let mut items: Vec<P<ast::MetaItem>> = Vec::new();
-    reader::tagged_docs(md, tag_meta_item_word, |meta_item_doc| {
+    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());
-        items.push(attr::mk_word_item(n));
-        true
-    });
-    reader::tagged_docs(md, tag_meta_item_name_value, |meta_item_doc| {
+        attr::mk_word_item(n)
+    }).chain(reader::tagged_docs(md, tag_meta_item_name_value).map(|meta_item_doc| {
         let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
         let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
         let n = token::intern_and_get_ident(nd.as_str_slice());
         let v = token::intern_and_get_ident(vd.as_str_slice());
         // FIXME (#623): Should be able to decode MetaNameValue variants,
         // but currently the encoder just drops them
-        items.push(attr::mk_name_value_item_str(n, v));
-        true
-    });
-    reader::tagged_docs(md, tag_meta_item_list, |meta_item_doc| {
+        attr::mk_name_value_item_str(n, v)
+    })).chain(reader::tagged_docs(md, tag_meta_item_list).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());
         let subitems = get_meta_items(meta_item_doc);
-        items.push(attr::mk_list_item(n, subitems.into_iter().collect()));
-        true
-    });
-    return items;
+        attr::mk_list_item(n, subitems)
+    })).collect()
 }
 
 fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
-    let mut attrs: Vec<ast::Attribute> = Vec::new();
     match reader::maybe_get_doc(md, tag_attributes) {
-      Some(attrs_d) => {
-        reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| {
-            let is_sugared_doc = reader::doc_as_u8(
-                reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
-            ) == 1;
-            let meta_items = get_meta_items(attr_doc);
-            // Currently it's only possible to have a single meta item on
-            // an attribute
-            assert_eq!(meta_items.len(), 1);
-            let meta_item = meta_items.into_iter().nth(0).unwrap();
-            attrs.push(
+        Some(attrs_d) => {
+            reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| {
+                let is_sugared_doc = reader::doc_as_u8(
+                    reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
+                ) == 1;
+                let meta_items = get_meta_items(attr_doc);
+                // Currently it's only possible to have a single meta item on
+                // an attribute
+                assert_eq!(meta_items.len(), 1);
+                let meta_item = meta_items.into_iter().nth(0).unwrap();
                 codemap::Spanned {
                     node: ast::Attribute_ {
                         id: attr::mk_attr_id(),
@@ -1216,13 +1123,11 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
                         is_sugared_doc: is_sugared_doc,
                     },
                     span: codemap::DUMMY_SP
-                });
-            true
-        });
-      }
-      None => ()
+                }
+            }).collect()
+        },
+        None => vec![],
     }
-    return attrs;
 }
 
 fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
@@ -1249,26 +1154,23 @@ pub struct CrateDep {
 }
 
 pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> {
-    let mut deps: Vec<CrateDep> = Vec::new();
     let cratedoc = rbml::Doc::new(data);
     let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
-    let mut crate_num = 1;
+
     fn docstr(doc: rbml::Doc, tag_: usize) -> String {
         let d = reader::get_doc(doc, tag_);
         d.as_str_slice().to_string()
     }
-    reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| {
+
+    reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| {
         let name = docstr(depdoc, tag_crate_dep_crate_name);
         let hash = Svh::new(&docstr(depdoc, tag_crate_dep_hash));
-        deps.push(CrateDep {
-            cnum: crate_num,
+        CrateDep {
+            cnum: crate_num as u32 + 1,
             name: name,
             hash: hash,
-        });
-        crate_num += 1;
-        true
-    });
-    return deps;
+        }
+    }).collect()
 }
 
 fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> {
@@ -1360,14 +1262,11 @@ pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
     where F: FnMut(ast::DefId),
 {
     let item_doc = lookup_item(id, cdata.data());
-    reader::tagged_docs(item_doc,
-                        tag_items_data_item_inherent_impl,
-                        |impl_doc| {
+    for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) {
         if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
             callback(item_def_id(impl_doc, cdata));
         }
-        true
-    });
+    }
 }
 
 pub fn each_implementation_for_trait<F>(cdata: Cmd,
@@ -1377,12 +1276,9 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
 {
     if cdata.cnum == def_id.krate {
         let item_doc = lookup_item(def_id.node, cdata.data());
-        let _ = reader::tagged_docs(item_doc,
-                                    tag_items_data_item_extension_impl,
-                                    |impl_doc| {
+        for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_extension_impl) {
             callback(item_def_id(impl_doc, cdata));
-            true
-        });
+        }
         return;
     }
 
@@ -1392,13 +1288,12 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
         let def_id_u64 = def_to_u64(crate_local_did);
 
         let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
-        let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
+        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));
             }
-            true
-        });
+        }
     }
 }
 
@@ -1425,17 +1320,14 @@ pub fn get_native_libraries(cdata: Cmd)
                             -> Vec<(cstore::NativeLibraryKind, String)> {
     let libraries = reader::get_doc(rbml::Doc::new(cdata.data()),
                                     tag_native_libraries);
-    let mut result = Vec::new();
-    reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| {
+    reader::tagged_docs(libraries, tag_native_libraries_lib).map(|lib_doc| {
         let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
         let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
         let kind: cstore::NativeLibraryKind =
             cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
         let name = name_doc.as_str().to_string();
-        result.push((kind, name));
-        true
-    });
-    return result;
+        (kind, name)
+    }).collect()
 }
 
 pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
@@ -1447,12 +1339,14 @@ pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
     F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
 {
     let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
-    reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
+    for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
         let name = item_name(intr, macro_doc);
         let attrs = get_attributes(macro_doc);
         let body = reader::get_doc(macro_doc, tag_macro_def_body);
-        f(name, attrs, body.as_str().to_string())
-    });
+        if !f(name, attrs, body.as_str().to_string()) {
+            break;
+        }
+    }
 }
 
 pub fn get_dylib_dependency_formats(cdata: Cmd)
@@ -1485,43 +1379,32 @@ pub fn get_missing_lang_items(cdata: Cmd)
     -> Vec<lang_items::LangItem>
 {
     let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_lang_items);
-    let mut result = Vec::new();
-    reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| {
-        let item: lang_items::LangItem =
-            lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
-        result.push(item);
-        true
-    });
-    return result;
+    reader::tagged_docs(items, tag_lang_items_missing).map(|missing_docs| {
+        lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap()
+    }).collect()
 }
 
 pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
-    let mut ret = Vec::new();
     let method_doc = lookup_item(id, cdata.data());
     match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
         Some(args_doc) => {
-            reader::tagged_docs(args_doc, tag_method_argument_name, |name_doc| {
-                ret.push(name_doc.as_str_slice().to_string());
-                true
-            });
-        }
-        None => {}
+            reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| {
+                name_doc.as_str_slice().to_string()
+            }).collect()
+        },
+        None => vec![],
     }
-    return ret;
 }
 
 pub fn get_reachable_extern_fns(cdata: Cmd) -> Vec<ast::DefId> {
-    let mut ret = Vec::new();
     let items = reader::get_doc(rbml::Doc::new(cdata.data()),
                                 tag_reachable_extern_fns);
-    reader::tagged_docs(items, tag_reachable_extern_fn_id|doc| {
-        ret.push(ast::DefId {
+    reader::tagged_docs(items, tag_reachable_extern_fn_id).map(|doc| {
+        ast::DefId {
             krate: cdata.cnum,
             node: reader::doc_as_u32(doc),
-        });
-        true
-    });
-    return ret;
+        }
+    }).collect()
 }
 
 pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
@@ -1532,6 +1415,22 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
+pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
+    let item_doc = lookup_item(id, cdata.data());
+    match fn_constness(item_doc) {
+        ast::Constness::Const => true,
+        ast::Constness::NotConst => false,
+    }
+}
+
+pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
+    let item_doc = lookup_item(id, cdata.data());
+    match item_family(item_doc) {
+        Impl => true,
+        _ => false,
+    }
+}
+
 fn doc_generics<'tcx>(base_doc: rbml::Doc,
                       tcx: &ty::ctxt<'tcx>,
                       cdata: Cmd,
@@ -1541,16 +1440,15 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
     let doc = reader::get_doc(base_doc, tag);
 
     let mut types = subst::VecPerParamSpace::empty();
-    reader::tagged_docs(doc, tag_type_param_def, |p| {
+    for p in reader::tagged_docs(doc, tag_type_param_def) {
         let bd = parse_type_param_def_data(
             p.data, p.start, cdata.cnum, tcx,
             |_, did| translate_def_id(cdata, did));
         types.push(bd.space, bd);
-        true
-    });
+    }
 
     let mut regions = subst::VecPerParamSpace::empty();
-    reader::tagged_docs(doc, tag_region_param_def, |rp_doc| {
+    for rp_doc in reader::tagged_docs(doc, tag_region_param_def) {
         let ident_str_doc = reader::get_doc(rp_doc,
                                             tag_region_param_def_ident);
         let name = item_name(&*token::get_ident_interner(), ident_str_doc);
@@ -1564,23 +1462,17 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
         let doc = reader::get_doc(rp_doc, tag_region_param_def_index);
         let index = reader::doc_as_u64(doc) as u32;
 
-        let mut bounds = Vec::new();
-        reader::tagged_docs(rp_doc, tag_items_data_region, |p| {
-            bounds.push(
-                parse_region_data(
-                    p.data, cdata.cnum, p.start, tcx,
-                    |_, did| translate_def_id(cdata, did)));
-            true
-        });
+        let bounds = reader::tagged_docs(rp_doc, tag_items_data_region).map(|p| {
+            parse_region_data(p.data, cdata.cnum, p.start, tcx,
+                              |_, did| translate_def_id(cdata, did))
+        }).collect();
 
         regions.push(space, ty::RegionParameterDef { name: name,
                                                      def_id: def_id,
                                                      space: space,
                                                      index: index,
                                                      bounds: bounds });
-
-        true
-    });
+    }
 
     ty::Generics { types: types, regions: regions }
 }
@@ -1594,7 +1486,7 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
     let doc = reader::get_doc(base_doc, tag);
 
     let mut predicates = subst::VecPerParamSpace::empty();
-    reader::tagged_docs(doc, tag_predicate, |predicate_doc| {
+    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);
 
@@ -1603,20 +1495,11 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
                                         |_, did| translate_def_id(cdata, did));
 
         predicates.push(space, data);
-        true
-    });
+    }
 
     ty::GenericPredicates { predicates: predicates }
 }
 
-pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
-    let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
-    match maybe_find_item(id, items) {
-        None => false,
-        Some(item) => item_sort(item) == Some('t'),
-    }
-}
-
 pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
     let trait_doc = lookup_item(trait_id, cdata.data());
     assert!(item_family(trait_doc) == Family::Trait);
@@ -1633,14 +1516,8 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
     let crate_doc = rbml::Doc::new(metadata);
     let cm_doc = reader::get_doc(crate_doc, tag_codemap);
 
-    let mut filemaps = vec![];
-
-    reader::tagged_docs(cm_doc, tag_codemap_filemap, |filemap_doc| {
+    reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| {
         let mut decoder = reader::Decoder::new(filemap_doc);
-        let filemap: codemap::FileMap = Decodable::decode(&mut decoder).unwrap();
-        filemaps.push(filemap);
-        true
-    });
-
-    return filemaps;
+        Decodable::decode(&mut decoder).unwrap()
+    }).collect()
 }
index 86f33257e09036101239e8f0920348268612043c..b217eabec6e6a36af9b39ec0fe41f5dfead314a2 100644 (file)
@@ -15,6 +15,7 @@
 
 pub use self::InlinedItemRef::*;
 
+use ast_map::{self, LinkedPath, PathElem, PathElems};
 use back::svh::Svh;
 use session::config;
 use metadata::common::*;
@@ -34,7 +35,6 @@ use std::io::prelude::*;
 use std::io::{Cursor, SeekFrom};
 use syntax::abi;
 use syntax::ast::{self, DefId, NodeId};
-use syntax::ast_map::{self, LinkedPath, PathElem, PathElems};
 use syntax::ast_util::*;
 use syntax::ast_util;
 use syntax::attr;
@@ -377,7 +377,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
     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 {
+            for base_impl_did in implementations.iter() {
                 for &method_did in impl_items.get(base_impl_did).unwrap() {
                     let impl_item = ty::impl_or_trait_item(
                         ecx.tcx,
@@ -403,7 +403,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
                                           -> bool {
     match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
         Some(trait_items) => {
-            for trait_item in &**trait_items {
+            for trait_item in trait_items.iter() {
                 if let ty::MethodTraitItem(ref m) = *trait_item {
                     encode_reexported_static_method(rbml_w,
                                                     exp,
@@ -581,6 +581,16 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
     rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
 }
 
+fn encode_constness(rbml_w: &mut Encoder, constness: ast::Constness) {
+    rbml_w.start_tag(tag_items_data_item_constness);
+    let ch = match constness {
+        ast::Constness::Const => 'c',
+        ast::Constness::NotConst => 'n',
+    };
+    rbml_w.wr_str(&ch.to_string());
+    rbml_w.end_tag();
+}
+
 fn encode_explicit_self(rbml_w: &mut Encoder,
                         explicit_self: &ty::ExplicitSelfCategory) {
     let tag = tag_item_trait_method_explicit_self;
@@ -713,14 +723,14 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
         abbrevs: &ecx.type_abbrevs
     };
 
-    for param in generics.types.iter() {
+    for param in &generics.types {
         rbml_w.start_tag(tag_type_param_def);
         tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
         rbml_w.end_tag();
     }
 
     // Region parameters
-    for param in generics.regions.iter() {
+    for param in &generics.regions {
         rbml_w.start_tag(tag_region_param_def);
 
         rbml_w.start_tag(tag_region_param_def_ident);
@@ -828,7 +838,7 @@ fn encode_info_for_associated_const(ecx: &EncodeContext,
     encode_stability(rbml_w, stab);
 
     let elem = ast_map::PathName(associated_const.name);
-    encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
+    encode_path(rbml_w, impl_path.chain(Some(elem)));
 
     if let Some(ii) = impl_item_opt {
         encode_attributes(rbml_w, &ii.attrs);
@@ -861,16 +871,19 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_bounds_and_type_for_item(rbml_w, ecx, m.def_id.local_id());
 
     let elem = ast_map::PathName(m.name);
-    encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
+    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 {
             encode_attributes(rbml_w, &impl_item.attrs);
             let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
             let any_types = !scheme.generics.types.is_empty();
-            if any_types || is_default_impl || attr::requests_inline(&impl_item.attrs) {
+            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, IIImplItemRef(local_def(parent_id),
                                                                impl_item));
             }
+            encode_constness(rbml_w, sig.constness);
             if !any_types {
                 encode_symbol(ecx, rbml_w, m.def_id.node);
             }
@@ -881,12 +894,12 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     rbml_w.end_tag();
 }
 
-fn encode_info_for_associated_type(ecx: &EncodeContext,
-                                   rbml_w: &mut Encoder,
-                                   associated_type: &ty::AssociatedType,
-                                   impl_path: PathElems,
-                                   parent_id: NodeId,
-                                   impl_item_opt: Option<&ast::ImplItem>) {
+fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                             rbml_w: &mut Encoder,
+                                             associated_type: &ty::AssociatedType<'tcx>,
+                                             impl_path: PathElems,
+                                             parent_id: NodeId,
+                                             impl_item_opt: Option<&ast::ImplItem>) {
     debug!("encode_info_for_associated_type({:?},{:?})",
            associated_type.def_id,
            token::get_name(associated_type.name));
@@ -900,17 +913,22 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
     encode_parent_item(rbml_w, local_def(parent_id));
     encode_item_sort(rbml_w, 't');
 
-    encode_bounds_and_type_for_item(rbml_w, ecx, associated_type.def_id.local_id());
-
     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
     encode_stability(rbml_w, stab);
 
     let elem = ast_map::PathName(associated_type.name);
-    encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
+    encode_path(rbml_w, impl_path.chain(Some(elem)));
 
     if let Some(ii) = impl_item_opt {
         encode_attributes(rbml_w, &ii.attrs);
-        encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx, ii.id));
+    } else {
+        encode_predicates(rbml_w, ecx,
+                          &ty::lookup_predicates(ecx.tcx, associated_type.def_id),
+                          tag_item_generics);
+    }
+
+    if let Some(ty) = associated_type.ty {
+        encode_type(ecx, rbml_w, ty);
     }
 
     rbml_w.end_tag();
@@ -937,7 +955,7 @@ fn encode_repr_attrs(rbml_w: &mut Encoder,
     let mut repr_attrs = Vec::new();
     for attr in attrs {
         repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
-                                                attr).into_iter());
+                                                attr));
     }
     rbml_w.start_tag(tag_items_data_item_repr);
     repr_attrs.encode(rbml_w);
@@ -963,7 +981,7 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
         None => {}
         Some(implementations) => {
-            for &impl_def_id in &**implementations {
+            for &impl_def_id in implementations.iter() {
                 rbml_w.start_tag(tag_items_data_item_inherent_impl);
                 encode_def_id(rbml_w, impl_def_id);
                 rbml_w.end_tag();
@@ -986,7 +1004,7 @@ fn encode_extension_implementations(ecx: &EncodeContext,
     });
 }
 
-fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
+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);
         stab.encode(rbml_w).unwrap();
@@ -1049,7 +1067,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
       }
-      ast::ItemFn(ref decl, _, _, ref generics, _) => {
+      ast::ItemFn(ref decl, _, constness, _, ref generics, _) => {
         add_to_index(item, rbml_w, index);
         rbml_w.start_tag(tag_items_data_item);
         encode_def_id(rbml_w, def_id);
@@ -1059,12 +1077,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_name(rbml_w, item.ident.name);
         encode_path(rbml_w, path);
         encode_attributes(rbml_w, &item.attrs);
-        if tps_len > 0 || attr::requests_inline(&item.attrs) {
+        let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
+        if needs_inline || constness == ast::Constness::Const {
             encode_inlined_item(ecx, rbml_w, IIItemRef(item));
         }
         if tps_len == 0 {
             encode_symbol(ecx, rbml_w, item.id);
         }
+        encode_constness(rbml_w, constness);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         encode_method_argument_names(rbml_w, &**decl);
@@ -1200,11 +1220,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
           encode_name(rbml_w, item.ident.name);
           encode_unsafety(rbml_w, unsafety);
 
-          let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
+          let trait_ref = ty::impl_trait_ref(tcx, local_def(item.id)).unwrap();
           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
           rbml_w.end_tag();
       }
-      ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
+      ast::ItemImpl(unsafety, polarity, _, _, ref ty, 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();
@@ -1254,8 +1274,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             rbml_w.end_tag();
         }
-        if opt_trait.is_some() {
-            let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
+        if let Some(trait_ref) = ty::impl_trait_ref(tcx, local_def(item.id)) {
             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
@@ -1329,7 +1348,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_attributes(rbml_w, &item.attrs);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
-        for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) {
+        for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
             rbml_w.start_tag(tag_item_trait_item);
             match method_def_id {
                 ty::ConstTraitItemId(const_def_id) => {
@@ -1390,7 +1409,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
                     let elem = ast_map::PathName(associated_const.name);
                     encode_path(rbml_w,
-                                path.clone().chain(Some(elem).into_iter()));
+                                path.clone().chain(Some(elem)));
 
                     encode_item_sort(rbml_w, 'C');
                     encode_family(rbml_w, 'C');
@@ -1407,7 +1426,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
                     let elem = ast_map::PathName(method_ty.name);
                     encode_path(rbml_w,
-                                path.clone().chain(Some(elem).into_iter()));
+                                path.clone().chain(Some(elem)));
 
                     match method_ty.explicit_self {
                         ty::StaticExplicitSelfCategory => {
@@ -1430,7 +1449,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
                     let elem = ast_map::PathName(associated_type.name);
                     encode_path(rbml_w,
-                                path.clone().chain(Some(elem).into_iter()));
+                                path.clone().chain(Some(elem)));
 
                     encode_item_sort(rbml_w, 't');
                     encode_family(rbml_w, 'y');
@@ -1967,7 +1986,7 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
 
     for id in ecx.reachable {
         if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
-            if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
+            if let ast::ItemFn(_, _, _, abi, ref generics, _) = i.node {
                 if abi != abi::Rust && !generics.is_type_parameterized() {
                     rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
                 }
index 9a95120ee686fd5747253818361d1c77dd768c03..2af3c393868d8ef355af0a523ae6f178495e8147 100644 (file)
@@ -429,15 +429,16 @@ impl<'a> Context<'a> {
             let slot = candidates.entry(hash_str)
                                  .or_insert_with(|| (HashMap::new(), HashMap::new()));
             let (ref mut rlibs, ref mut dylibs) = *slot;
-            if rlib {
-                rlibs.insert(fs::canonicalize(path).unwrap(), kind);
-            } else {
-                dylibs.insert(fs::canonicalize(path).unwrap(), kind);
-            }
-
-            FileMatches
+            fs::canonicalize(path).map(|p| {
+                if rlib {
+                    rlibs.insert(p, kind);
+                } else {
+                    dylibs.insert(p, kind);
+                }
+                FileMatches
+            }).unwrap_or(FileDoesntMatch)
         });
-        self.rejected_via_kind.extend(staticlibs.into_iter());
+        self.rejected_via_kind.extend(staticlibs);
 
         // We have now collected all known libraries into a set of candidates
         // keyed of the filename hash listed. For each filename, we also have a
@@ -526,8 +527,7 @@ impl<'a> Context<'a> {
 
         for (lib, kind) in m {
             info!("{} reading metadata from: {}", flavor, lib.display());
-            let metadata = match get_metadata_section(self.target.options.is_like_osx,
-                                                      &lib) {
+            let metadata = match get_metadata_section(self.target, &lib) {
                 Ok(blob) => {
                     if self.crate_matches(blob.as_slice(), &lib) {
                         blob
@@ -715,16 +715,18 @@ impl ArchiveMetadata {
 }
 
 // Just a small wrapper to time how long reading metadata takes.
-fn get_metadata_section(is_osx: bool, filename: &Path) -> Result<MetadataBlob, String> {
+fn get_metadata_section(target: &Target, filename: &Path)
+                        -> Result<MetadataBlob, String> {
     let mut ret = None;
     let dur = Duration::span(|| {
-        ret = Some(get_metadata_section_imp(is_osx, filename));
+        ret = Some(get_metadata_section_imp(target, filename));
     });
     info!("reading {:?} => {}", filename.file_name().unwrap(), dur);
     return ret.unwrap();;
 }
 
-fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlob, String> {
+fn get_metadata_section_imp(target: &Target, filename: &Path)
+                            -> Result<MetadataBlob, String> {
     if !filename.exists() {
         return Err(format!("no such file: '{}'", filename.display()));
     }
@@ -768,7 +770,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
                                              name_len as usize).to_vec();
             let name = String::from_utf8(name).unwrap();
             debug!("get_metadata_section: name {}", name);
-            if read_meta_section_name(is_osx) == name {
+            if read_meta_section_name(target) == name {
                 let cbuf = llvm::LLVMGetSectionContents(si.llsi);
                 let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
                 let cvbuf: *const u8 = cbuf as *const u8;
@@ -798,26 +800,41 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
     }
 }
 
-pub fn meta_section_name(is_osx: bool) -> &'static str {
-    if is_osx {
+pub fn meta_section_name(target: &Target) -> &'static str {
+    if target.options.is_like_osx {
         "__DATA,__note.rustc"
+    } else if target.options.is_like_msvc {
+        // When using link.exe it was seen that the section name `.note.rustc`
+        // was getting shortened to `.note.ru`, and according to the PE and COFF
+        // specification:
+        //
+        // > Executable images do not use a string table and do not support
+        // > section names longer than 8 characters
+        //
+        // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
+        //
+        // As a result, we choose a slightly shorter name! As to why
+        // `.note.rustc` works on MinGW, that's another good question...
+        ".rustc"
     } else {
         ".note.rustc"
     }
 }
 
-pub fn read_meta_section_name(is_osx: bool) -> &'static str {
-    if is_osx {
+pub fn read_meta_section_name(target: &Target) -> &'static str {
+    if target.options.is_like_osx {
         "__note.rustc"
+    } else if target.options.is_like_msvc {
+        ".rustc"
     } else {
         ".note.rustc"
     }
 }
 
 // A diagnostic function for dumping crate metadata to an output stream
-pub fn list_file_metadata(is_osx: bool, path: &Path,
+pub fn list_file_metadata(target: &Target, path: &Path,
                           out: &mut io::Write) -> io::Result<()> {
-    match get_metadata_section(is_osx, path) {
+    match get_metadata_section(target, path) {
         Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
         Err(msg) => {
             write!(out, "{}\n", msg)
index c2d7911d151fbfb7f3a79e2e4d61776a4e851a59..8606cbc53d54468349acaa6f5094cbe2760fb2cb 100644 (file)
@@ -164,14 +164,14 @@ impl<'a> MacroLoader<'a> {
         }
 
         if let Some(sel) = import.as_ref() {
-            for (name, span) in sel.iter() {
+            for (name, span) in sel {
                 if !seen.contains(name) {
                     self.sess.span_err(*span, "imported macro not found");
                 }
             }
         }
 
-        for (name, span) in reexport.iter() {
+        for (name, span) in &reexport {
             if !seen.contains(name) {
                 self.sess.span_err(*span, "reexported macro not found");
             }
index 223a5eef614c1acc4aacf62e4369be359f7e36cc..5f96a71d6e10f978bf775ee5ba555dd19c2c247d 100644 (file)
@@ -28,7 +28,7 @@ use syntax::abi;
 use syntax::ast;
 use syntax::parse::token;
 
-// Compact string representation for Ty values. API ty_str &
+// Compact string representation for Ty values. API TyStr &
 // 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.
 
@@ -50,9 +50,6 @@ pub enum DefIdSource {
     // Identifies a type alias (`type X = ...`).
     TypeWithId,
 
-    // Identifies a type parameter (`fn foo<X>() { ... }`).
-    TypeParameter,
-
     // Identifies a region parameter (`fn foo<'X>() { ... }`).
     RegionParameter,
 
@@ -193,20 +190,11 @@ pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: us
                                   tcx: &ty::ctxt<'tcx>, conv: F) -> subst::Substs<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    debug!("parse_substs_data {}", data_log_string(data, pos));
+    debug!("parse_substs_data{}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_substs(&mut st, conv)
 }
 
-pub fn parse_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
-                                  pos: usize, tcx: &ty::ctxt<'tcx>, conv: F)
-                                  -> ty::ParamBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_bounds(&mut st, conv)
-}
-
 pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
                                               pos: usize, tcx: &ty::ctxt<'tcx>, conv: F)
                                               -> ty::ExistentialBounds<'tcx> where
@@ -542,7 +530,14 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
                                          len: len };
 
         match tcx.rcache.borrow().get(&key).cloned() {
-          Some(tt) => return tt,
+          Some(tt) => {
+            // If there is a closure buried in the type some where, then we
+            // need to re-convert any def ids (see case 'k', below). That means
+            // we can't reuse the cached version.
+            if !ty::type_has_ty_closure(tt) {
+                return tt;
+            }
+          }
           None => {}
         }
         let mut ps = PState {
@@ -848,15 +843,15 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
 
 fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
                                              conv: &mut F)
-                                             -> Option<ty::ObjectLifetimeDefault>
+                                             -> ty::ObjectLifetimeDefault
     where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     match next(st) {
-        'n' => None,
-        'a' => Some(ty::ObjectLifetimeDefault::Ambiguous),
+        'a' => ty::ObjectLifetimeDefault::Ambiguous,
+        'b' => ty::ObjectLifetimeDefault::BaseDefault,
         's' => {
             let region = parse_region_(st, conv);
-            Some(ty::ObjectLifetimeDefault::Specific(region))
+            ty::ObjectLifetimeDefault::Specific(region)
         }
         _ => panic!("parse_object_lifetime_default: bad input")
     }
@@ -875,14 +870,33 @@ fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
                                         -> ty::ExistentialBounds<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let ty::ParamBounds { trait_bounds, mut region_bounds, builtin_bounds, projection_bounds } =
-         parse_bounds_(st, conv);
-    assert_eq!(region_bounds.len(), 1);
-    assert_eq!(trait_bounds.len(), 0);
-    let region_bound = region_bounds.pop().unwrap();
+    let builtin_bounds = parse_builtin_bounds_(st, conv);
+    let region_bound = parse_region_(st, conv);
+    let mut projection_bounds = Vec::new();
+
+    loop {
+        match next(st) {
+            'P' => {
+                projection_bounds.push(
+                    ty::Binder(parse_projection_predicate_(st, conv)));
+                }
+            '.' => { break; }
+            c => {
+                panic!("parse_bounds: bad bounds ('{}')", c)
+            }
+        }
+    }
+
+    let region_bound_will_change = match next(st) {
+        'y' => true,
+        'n' => false,
+        c => panic!("parse_ty: expected y/n not '{}'", c)
+    };
+
     return ty::ExistentialBounds { region_bound: region_bound,
                                    builtin_bounds: builtin_bounds,
-                                   projection_bounds: projection_bounds };
+                                   projection_bounds: projection_bounds,
+                                   region_bound_will_change: region_bound_will_change };
 }
 
 fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds where
@@ -894,7 +908,7 @@ fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds w
 fn parse_builtin_bounds_<F>(st: &mut PState, _conv: &mut F) -> ty::BuiltinBounds where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut builtin_bounds = ty::empty_builtin_bounds();
+    let mut builtin_bounds = ty::BuiltinBounds::empty();
 
     loop {
         match next(st) {
@@ -919,60 +933,3 @@ fn parse_builtin_bounds_<F>(st: &mut PState, _conv: &mut F) -> ty::BuiltinBounds
         }
     }
 }
-
-fn parse_bounds<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F)
-                             -> ty::ParamBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_bounds_(st, &mut conv)
-}
-
-fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
-                              -> ty::ParamBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let builtin_bounds = parse_builtin_bounds_(st, conv);
-
-    let region_bounds = parse_region_bounds_(st, conv);
-
-    let mut param_bounds = ty::ParamBounds {
-        region_bounds: region_bounds,
-        builtin_bounds: builtin_bounds,
-        trait_bounds: Vec::new(),
-        projection_bounds: Vec::new(),
-    };
-
-
-    loop {
-        match next(st) {
-            'I' => {
-                param_bounds.trait_bounds.push(
-                    ty::Binder(parse_trait_ref_(st, conv)));
-            }
-            'P' => {
-                param_bounds.projection_bounds.push(
-                    ty::Binder(parse_projection_predicate_(st, conv)));
-            }
-            '.' => {
-                return param_bounds;
-            }
-            c => {
-                panic!("parse_bounds: bad bounds ('{}')", c)
-            }
-        }
-    }
-}
-
-fn parse_region_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
-                              -> Vec<ty::Region> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut region_bounds = Vec::new();
-    loop {
-        match next(st) {
-            'R' => { region_bounds.push(parse_region_(st, conv)); }
-            '.' => { return region_bounds; }
-            c => { panic!("parse_bounds: bad bounds ('{}')", c); }
-        }
-    }
-}
index f5f520720c62bc1ca5d421bbd91b9fed2cfac57b..441f9f102aea911e4fa67b7f1ffcc2f606f68ff5 100644 (file)
@@ -41,7 +41,7 @@ pub struct ctxt<'a, 'tcx: 'a> {
     pub abbrevs: &'a abbrev_map<'tcx>
 }
 
-// Compact string representation for Ty values. API ty_str & parse_from_str.
+// Compact string representation for Ty values. API TyStr & parse_from_str.
 // 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 {
@@ -60,9 +60,9 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
     let pos = w.mark_stable_position();
 
     match t.sty {
-        ty::ty_bool => mywrite!(w, "b"),
-        ty::ty_char => mywrite!(w, "c"),
-        ty::ty_int(t) => {
+        ty::TyBool => mywrite!(w, "b"),
+        ty::TyChar => mywrite!(w, "c"),
+        ty::TyInt(t) => {
             match t {
                 ast::TyIs => mywrite!(w, "is"),
                 ast::TyI8 => mywrite!(w, "MB"),
@@ -71,7 +71,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
                 ast::TyI64 => mywrite!(w, "MD")
             }
         }
-        ty::ty_uint(t) => {
+        ty::TyUint(t) => {
             match t {
                 ast::TyUs => mywrite!(w, "us"),
                 ast::TyU8 => mywrite!(w, "Mb"),
@@ -80,79 +80,80 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
                 ast::TyU64 => mywrite!(w, "Md")
             }
         }
-        ty::ty_float(t) => {
+        ty::TyFloat(t) => {
             match t {
                 ast::TyF32 => mywrite!(w, "Mf"),
                 ast::TyF64 => mywrite!(w, "MF"),
             }
         }
-        ty::ty_enum(def, substs) => {
+        ty::TyEnum(def, substs) => {
             mywrite!(w, "t[{}|", (cx.ds)(def));
             enc_substs(w, cx, substs);
             mywrite!(w, "]");
         }
-        ty::ty_trait(box ty::TyTrait { ref principal,
+        ty::TyTrait(box ty::TraitTy { ref principal,
                                        ref bounds }) => {
             mywrite!(w, "x[");
             enc_trait_ref(w, cx, principal.0);
             enc_existential_bounds(w, cx, bounds);
             mywrite!(w, "]");
         }
-        ty::ty_tup(ref ts) => {
+        ty::TyTuple(ref ts) => {
             mywrite!(w, "T[");
             for t in ts { enc_ty(w, cx, *t); }
             mywrite!(w, "]");
         }
-        ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
-        ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
-        ty::ty_rptr(r, mt) => {
+        ty::TyBox(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
+        ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
+        ty::TyRef(r, mt) => {
             mywrite!(w, "&");
             enc_region(w, cx, *r);
             enc_mt(w, cx, mt);
         }
-        ty::ty_vec(t, sz) => {
+        ty::TyArray(t, sz) => {
             mywrite!(w, "V");
             enc_ty(w, cx, t);
-            mywrite!(w, "/");
-            match sz {
-                Some(n) => mywrite!(w, "{}|", n),
-                None => mywrite!(w, "|"),
-            }
+            mywrite!(w, "/{}|", sz);
         }
-        ty::ty_str => {
+        ty::TySlice(t) => {
+            mywrite!(w, "V");
+            enc_ty(w, cx, t);
+            mywrite!(w, "/|");
+        }
+        ty::TyStr => {
             mywrite!(w, "v");
         }
-        ty::ty_bare_fn(Some(def_id), f) => {
+        ty::TyBareFn(Some(def_id), f) => {
             mywrite!(w, "F");
             mywrite!(w, "{}|", (cx.ds)(def_id));
             enc_bare_fn_ty(w, cx, f);
         }
-        ty::ty_bare_fn(None, f) => {
+        ty::TyBareFn(None, f) => {
             mywrite!(w, "G");
             enc_bare_fn_ty(w, cx, f);
         }
-        ty::ty_infer(_) => {
+        ty::TyInfer(_) => {
             cx.diag.handler().bug("cannot encode inference variable types");
         }
-        ty::ty_param(ParamTy {space, idx, name}) => {
+        ty::TyParam(ParamTy {space, idx, name}) => {
             mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), token::get_name(name))
         }
-        ty::ty_struct(def, substs) => {
+        ty::TyStruct(def, substs) => {
             mywrite!(w, "a[{}|", (cx.ds)(def));
             enc_substs(w, cx, substs);
             mywrite!(w, "]");
         }
-        ty::ty_closure(def, substs) => {
+        ty::TyClosure(def, substs) => {
             mywrite!(w, "k[{}|", (cx.ds)(def));
             enc_substs(w, cx, substs);
             mywrite!(w, "]");
         }
-        ty::ty_projection(ref data) => {
+        ty::TyProjection(ref data) => {
             mywrite!(w, "P[");
             enc_trait_ref(w, cx, data.trait_ref);
             mywrite!(w, "{}]", token::get_name(data.item_name));
         }
-        ty::ty_err => {
+        ty::TyError => {
             mywrite!(w, "e");
         }
     }
@@ -379,23 +380,9 @@ pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) {
 pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder,
                                        cx: &ctxt<'a,'tcx>,
                                        bs: &ty::ExistentialBounds<'tcx>) {
-    let param_bounds = ty::ParamBounds { trait_bounds: vec!(),
-                                         region_bounds: vec!(bs.region_bound),
-                                         builtin_bounds: bs.builtin_bounds,
-                                         projection_bounds: bs.projection_bounds.clone() };
-    enc_bounds(w, cx, &param_bounds);
-}
-
-pub fn enc_bounds<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
-                            bs: &ty::ParamBounds<'tcx>) {
     enc_builtin_bounds(w, cx, &bs.builtin_bounds);
 
-    enc_region_bounds(w, cx, &bs.region_bounds);
-
-    for tp in &bs.trait_bounds {
-        mywrite!(w, "I");
-        enc_trait_ref(w, cx, tp.0);
-    }
+    enc_region(w, cx, bs.region_bound);
 
     for tp in &bs.projection_bounds {
         mywrite!(w, "P");
@@ -403,6 +390,8 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
     }
 
     mywrite!(w, ".");
+
+    mywrite!(w, "{}", if bs.region_bound_will_change {'y'} else {'n'});
 }
 
 pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder,
@@ -427,12 +416,12 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
 
 fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder,
                                          cx: &ctxt<'a, 'tcx>,
-                                         default: Option<ty::ObjectLifetimeDefault>)
+                                         default: ty::ObjectLifetimeDefault)
 {
     match default {
-        None => mywrite!(w, "n"),
-        Some(ty::ObjectLifetimeDefault::Ambiguous) => mywrite!(w, "a"),
-        Some(ty::ObjectLifetimeDefault::Specific(r)) => {
+        ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"),
+        ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"),
+        ty::ObjectLifetimeDefault::Specific(r) => {
             mywrite!(w, "s");
             enc_region(w, cx, r);
         }
index 698cf105ae53c12d6b1a5d4dabec5175f1dc6c63..33d37b285890add380cb4af184013d386dba25db 100644 (file)
@@ -17,7 +17,6 @@
 use middle::def;
 use middle::ty::{self, Ty};
 use syntax::ast;
-use util::ppaux::Repr;
 
 pub const NO_REGIONS: usize = 1;
 pub const NO_TPS: usize = 2;
@@ -63,7 +62,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
         let def = match tcx.def_map.borrow().get(&ast_ty.id) {
             None => {
                 tcx.sess.span_bug(ast_ty.span,
-                                  &format!("unbound path {}", path.repr(tcx)))
+                                  &format!("unbound path {:?}", path))
             }
             Some(d) => d.full_def()
         };
index 4bfc4c5b850fd43f8dfe3ffe834cad4aa66662c6..21e2ad198810efc4a62bfc0f76b538a52ec2a78b 100644 (file)
@@ -12,6 +12,7 @@
 // FIXME: remove this after snapshot, and Results are handled
 #![allow(unused_must_use)]
 
+use ast_map;
 use metadata::common as c;
 use metadata::cstore as cstore;
 use session::Session;
@@ -20,18 +21,18 @@ use middle::def;
 use metadata::encoder as e;
 use middle::region;
 use metadata::tydecode;
-use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
+use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
 use metadata::tydecode::{RegionParameter, ClosureSource};
 use metadata::tyencode;
+use middle::cast;
 use middle::check_const::ConstQualif;
 use middle::mem_categorization::Typer;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
-use util::ppaux::ty_to_string;
 
-use syntax::{ast, ast_map, ast_util, codemap, fold};
+use syntax::{ast, ast_util, codemap, fold};
 use syntax::codemap::Span;
 use syntax::fold::Folder;
 use syntax::parse::token;
@@ -232,8 +233,6 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
     /// codemap as a side-effect of creating the crate_metadata's
     /// `codemap_import_info`.
     pub fn tr_span(&self, span: Span) -> Span {
-        let imported_filemaps = &self.cdata.codemap_import_info[..];
-
         let span = if span.lo > span.hi {
             // Currently macro expansion sometimes produces invalid Span values
             // where lo > hi. In order not to crash the compiler when trying to
@@ -247,16 +246,18 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
             span
         };
 
-        let filemap_index = {
+        let imported_filemaps = self.cdata.imported_filemaps(self.tcx.sess.codemap());
+        let filemap = {
             // Optimize for the case that most spans within a translated item
             // originate from the same filemap.
             let last_filemap_index = self.last_filemap_index.get();
+            let last_filemap = &imported_filemaps[last_filemap_index];
 
-            if span.lo >= imported_filemaps[last_filemap_index].original_start_pos &&
-               span.lo <= imported_filemaps[last_filemap_index].original_end_pos &&
-               span.hi >= imported_filemaps[last_filemap_index].original_start_pos &&
-               span.hi <= imported_filemaps[last_filemap_index].original_end_pos {
-                last_filemap_index
+            if span.lo >= last_filemap.original_start_pos &&
+               span.lo <= last_filemap.original_end_pos &&
+               span.hi >= last_filemap.original_start_pos &&
+               span.hi <= last_filemap.original_end_pos {
+                last_filemap
             } else {
                 let mut a = 0;
                 let mut b = imported_filemaps.len();
@@ -271,14 +272,14 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
                 }
 
                 self.last_filemap_index.set(a);
-                a
+                &imported_filemaps[a]
             }
         };
 
-        let lo = (span.lo - imported_filemaps[filemap_index].original_start_pos) +
-                  imported_filemaps[filemap_index].translated_filemap.start_pos;
-        let hi = (span.hi - imported_filemaps[filemap_index].original_start_pos) +
-                  imported_filemaps[filemap_index].translated_filemap.start_pos;
+        let lo = (span.lo - filemap.original_start_pos) +
+                  filemap.translated_filemap.start_pos;
+        let hi = (span.hi - filemap.original_start_pos) +
+                  filemap.translated_filemap.start_pos;
 
         codemap::mk_sp(lo, hi)
     }
@@ -345,13 +346,6 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
 // ______________________________________________________________________
 // Encoding and decoding the AST itself
 //
-// The hard work is done by an autogenerated module astencode_gen.  To
-// regenerate astencode_gen, run src/etc/gen-astencode.  It will
-// replace astencode_gen with a dummy file and regenerate its
-// contents.  If you get compile errors, the dummy file
-// remains---resolve the errors and then rerun astencode_gen.
-// Annoying, I know, but hopefully only temporary.
-//
 // When decoding, we have to renumber the AST so that the node ids that
 // appear within are disjoint from the node ids in our existing ASTs.
 // We also have to adjust the spans: for now we just insert a dummy span,
@@ -655,55 +649,17 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
     }
 }
 
-impl<'tcx> tr for MethodOrigin<'tcx> {
-    fn tr(&self, dcx: &DecodeContext) -> MethodOrigin<'tcx> {
-        match *self {
-            ty::MethodStatic(did) => ty::MethodStatic(did.tr(dcx)),
-            ty::MethodStaticClosure(did) => {
-                ty::MethodStaticClosure(did.tr(dcx))
-            }
-            ty::MethodTypeParam(ref mp) => {
-                ty::MethodTypeParam(
-                    ty::MethodParam {
-                        // def-id is already translated when we read it out
-                        trait_ref: mp.trait_ref.clone(),
-                        method_num: mp.method_num,
-                        impl_def_id: mp.impl_def_id.tr(dcx),
-                    }
-                )
-            }
-            ty::MethodTraitObject(ref mo) => {
-                ty::MethodTraitObject(
-                    ty::MethodObject {
-                        trait_ref: mo.trait_ref.clone(),
-                        .. *mo
-                    }
-                )
-            }
-        }
-    }
+pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
+    kind.encode(ebml_w).unwrap();
 }
 
-pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
+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;
-    fn read_vtable_res_with_key(&mut self,
-                                tcx: &ty::ctxt<'tcx>,
-                                cdata: &cstore::crate_metadata)
-                                -> (u32, ty::vtable_res<'tcx>);
-    fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_res<'tcx>;
-    fn read_vtable_param_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_param_res<'tcx>;
-    fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                          -> ty::vtable_origin<'tcx>;
 }
 
 impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
@@ -715,85 +671,6 @@ impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
         let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
         VecPerParamSpace::new(types, selfs, fns)
     }
-
-    fn read_vtable_res_with_key(&mut self,
-                                tcx: &ty::ctxt<'tcx>,
-                                cdata: &cstore::crate_metadata)
-                                -> (u32, ty::vtable_res<'tcx>) {
-        self.read_struct("VtableWithKey", 2, |this| {
-            let autoderef = this.read_struct_field("autoderef", 0, |this| {
-                Decodable::decode(this)
-            }).unwrap();
-            Ok((autoderef, this.read_struct_field("vtable_res", 1, |this| {
-                Ok(this.read_vtable_res(tcx, cdata))
-            }).unwrap()))
-        }).unwrap()
-    }
-
-    fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>,
-                       cdata: &cstore::crate_metadata)
-                       -> ty::vtable_res<'tcx>
-    {
-        self.read_vec_per_param_space(
-            |this| this.read_vtable_param_res(tcx, cdata))
-    }
-
-    fn read_vtable_param_res(&mut self,
-                             tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_param_res<'tcx> {
-        self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
-             .unwrap().into_iter().collect()
-    }
-
-    fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-        -> ty::vtable_origin<'tcx> {
-        self.read_enum("vtable_origin", |this| {
-            this.read_enum_variant(&["vtable_static",
-                                     "vtable_param",
-                                     "vtable_error",
-                                     "vtable_closure"],
-                                   |this, i| {
-                Ok(match i {
-                  0 => {
-                    ty::vtable_static(
-                        this.read_enum_variant_arg(0, |this| {
-                            Ok(this.read_def_id_nodcx(cdata))
-                        }).unwrap(),
-                        this.read_enum_variant_arg(1, |this| {
-                            Ok(this.read_substs_nodcx(tcx, cdata))
-                        }).unwrap(),
-                        this.read_enum_variant_arg(2, |this| {
-                            Ok(this.read_vtable_res(tcx, cdata))
-                        }).unwrap()
-                    )
-                  }
-                  1 => {
-                    ty::vtable_param(
-                        this.read_enum_variant_arg(0, |this| {
-                            Decodable::decode(this)
-                        }).unwrap(),
-                        this.read_enum_variant_arg(1, |this| {
-                            this.read_uint()
-                        }).unwrap()
-                    )
-                  }
-                  2 => {
-                    ty::vtable_closure(
-                        this.read_enum_variant_arg(0, |this| {
-                            Ok(this.read_def_id_nodcx(cdata))
-                        }).unwrap()
-                    )
-                  }
-                  3 => {
-                    ty::vtable_error
-                  }
-                  _ => panic!("bad enum variant")
-                })
-            })
-        }).unwrap()
-    }
 }
 
 // ___________________________________________________________________________
@@ -1204,13 +1081,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    if let Some(trait_ref) = tcx.object_cast_map.borrow().get(&id) {
-        rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_trait_ref(ecx, &trait_ref.0);
-        })
-    }
-
     if let Some(adjustment) = tcx.adjustments.borrow().get(&id) {
         match *adjustment {
             ty::AdjustDerefRef(ref adj) => {
@@ -1248,7 +1118,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for &qualif in tcx.const_qualif_map.borrow().get(&id).iter() {
+    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);
+            encode_cast_kind(rbml_w, *cast_kind)
+        })
+    }
+
+    if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) {
         rbml_w.tag(c::tag_table_const_qualif, |rbml_w| {
             rbml_w.id(id);
             qualif.encode(rbml_w).unwrap()
@@ -1289,6 +1166,8 @@ trait rbml_decoder_decoder_helpers<'tcx> {
                            -> subst::Substs<'tcx>;
     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                     -> ty::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>)
@@ -1558,10 +1437,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                            -> subst::Substs<'tcx> {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_substs_data(doc.data,
-                                        dcx.cdata.cnum,
-                                        doc.start,
-                                        dcx.tcx,
-                                        |s, a| this.convert_def_id(dcx, s, a)))
+                                           dcx.cdata.cnum,
+                                           doc.start,
+                                           dcx.tcx,
+                                           |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap()
     }
 
@@ -1641,6 +1520,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         }).unwrap()
     }
 
+    fn read_cast_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
+                              -> cast::CastKind
+    {
+        Decodable::decode(self).unwrap()
+    }
+
     fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
                                  -> ty::ClosureKind
     {
@@ -1696,7 +1581,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                       -> ast::DefId {
         let r = match source {
             NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
-            TypeParameter | ClosureSource => dcx.tr_intern_def_id(did)
+            ClosureSource => dcx.tr_intern_def_id(did)
         };
         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
         return r;
@@ -1706,7 +1591,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
 fn decode_side_tables(dcx: &DecodeContext,
                       ast_doc: rbml::Doc) {
     let tbl_doc = ast_doc.get(c::tag_table as usize);
-    reader::docs(tbl_doc, |tag, entry_doc| {
+    for (tag, entry_doc) in reader::docs(tbl_doc) {
         let mut entry_dsr = reader::Decoder::new(entry_doc);
         let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap();
         let id = dcx.tr_id(id0);
@@ -1737,8 +1622,8 @@ fn decode_side_tables(dcx: &DecodeContext,
                     }
                     c::tag_table_node_type => {
                         let ty = val_dsr.read_ty(dcx);
-                        debug!("inserting ty for node {}: {}",
-                               id, ty_to_string(dcx.tcx, ty));
+                        debug!("inserting ty for node {}: {:?}",
+                               id,  ty);
                         dcx.tcx.node_type_insert(id, ty);
                     }
                     c::tag_table_item_subst => {
@@ -1780,11 +1665,6 @@ fn decode_side_tables(dcx: &DecodeContext,
                         };
                         dcx.tcx.method_map.borrow_mut().insert(method_call, method);
                     }
-                    c::tag_table_object_cast_map => {
-                        let trait_ref = val_dsr.read_poly_trait_ref(dcx);
-                        dcx.tcx.object_cast_map.borrow_mut()
-                                               .insert(id, trait_ref);
-                    }
                     c::tag_table_adjustments => {
                         let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
@@ -1801,6 +1681,11 @@ fn decode_side_tables(dcx: &DecodeContext,
                         dcx.tcx.closure_kinds.borrow_mut().insert(ast_util::local_def(id),
                                                                   closure_kind);
                     }
+                    c::tag_table_cast_kinds => {
+                        let cast_kind =
+                            val_dsr.read_cast_kind(dcx);
+                        dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind);
+                    }
                     c::tag_table_const_qualif => {
                         let qualif: ConstQualif = Decodable::decode(val_dsr).unwrap();
                         dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif);
@@ -1815,8 +1700,7 @@ fn decode_side_tables(dcx: &DecodeContext,
         }
 
         debug!(">< Side table doc loaded");
-        true
-    });
+    }
 }
 
 // ______________________________________________________________________
@@ -1866,7 +1750,7 @@ impl FakeExtCtxt for parse::ParseSess {
 
 #[cfg(test)]
 fn mk_ctxt() -> parse::ParseSess {
-    parse::new_parse_sess()
+    parse::ParseSess::new()
 }
 
 #[cfg(test)]
diff --git a/src/librustc/middle/cast.rs b/src/librustc/middle/cast.rs
new file mode 100644 (file)
index 0000000..34088d5
--- /dev/null
@@ -0,0 +1,77 @@
+// 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.
+
+// Helpers for handling cast expressions, used in both
+// typeck and trans.
+
+use middle::ty::{self, Ty};
+
+use syntax::ast;
+
+/// Types that are represented as ints.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum IntTy {
+    U(ast::UintTy),
+    I,
+    CEnum,
+    Bool,
+    Char
+}
+
+// Valid types for the result of a non-coercion cast
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum CastTy<'tcx> {
+    /// Various types that are represented as ints and handled mostly
+    /// in the same way, merged for easier matching.
+    Int(IntTy),
+    /// Floating-Point types
+    Float,
+    /// Function Pointers
+    FnPtr,
+    /// Raw pointers
+    Ptr(&'tcx ty::mt<'tcx>),
+    /// References
+    RPtr(&'tcx ty::mt<'tcx>),
+}
+
+/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum CastKind {
+    CoercionCast,
+    PtrPtrCast,
+    PtrAddrCast,
+    AddrPtrCast,
+    NumericCast,
+    EnumCast,
+    PrimIntCast,
+    U8CharCast,
+    ArrayPtrCast,
+    FnPtrPtrCast,
+    FnPtrAddrCast
+}
+
+impl<'tcx> CastTy<'tcx> {
+    pub fn from_ty(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
+                   -> Option<CastTy<'tcx>> {
+        match t.sty {
+            ty::TyBool => Some(CastTy::Int(IntTy::Bool)),
+            ty::TyChar => Some(CastTy::Int(IntTy::Char)),
+            ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
+            ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
+            ty::TyFloat(_) => Some(CastTy::Float),
+            ty::TyEnum(..) if ty::type_is_c_like_enum(
+                tcx, t) => Some(CastTy::Int(IntTy::CEnum)),
+            ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
+            ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
+            ty::TyBareFn(..) => Some(CastTy::FnPtr),
+            _ => None,
+        }
+    }
+}
index a7950a701f8c4fce0c96045d6ca81dcfa2c24db2..e782a03176d67d5b1649e6f7480a0a5b057e2f74 100644 (file)
@@ -338,7 +338,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
             ast::ExprRange(ref start, ref end) => {
                 let fields = start.as_ref().map(|e| &**e).into_iter()
-                    .chain(end.as_ref().map(|e| &**e).into_iter());
+                    .chain(end.as_ref().map(|e| &**e));
                 self.straightline(expr, pred, fields)
             }
 
index 3a6966ab112905bee06966be07b48ff0c911175c..76050671cc4c503d2e2313fbfb3379842d8a2fa3 100644 (file)
@@ -17,8 +17,8 @@ use std::borrow::IntoCow;
 use graphviz as dot;
 
 use syntax::ast;
-use syntax::ast_map;
 
+use ast_map;
 use middle::cfg;
 
 pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
index 3ca221c9630be93c92aefaecad46fd3462da9ea8..c33caaa3c03e7cd80e13066588be0e471e3ae621 100644 (file)
@@ -63,6 +63,7 @@ impl CFG {
     }
 
     pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
-        self.graph.depth_traverse(self.entry).any(|node| node.id() == id)
+        self.graph.depth_traverse(self.entry)
+                  .any(|idx| self.graph.node_data(idx).id() == id)
     }
 }
index 8bb83c54da8a3681d92ff8b8410ea0951f4832ce..8af6946d3c3b13981348069d19c9375274bb47aa 100644 (file)
 //
 // - For each *mutable* static item, it checks that its **type**:
 //     - doesn't have a destructor
-//     - doesn't own an owned pointer
+//     - doesn't own a box
 //
 // - For each *immutable* static item, it checks that its **value**:
-//       - doesn't own owned, managed pointers
+//       - doesn't own a box
 //       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
 //           - the type of the struct/enum has a dtor
 //
@@ -24,6 +24,7 @@
 // - It's not possible to take the address of a static item with unsafe interior. This is enforced
 // by borrowck::gather_loans
 
+use middle::cast::{CastKind};
 use middle::const_eval;
 use middle::def;
 use middle::expr_use_visitor as euv;
@@ -32,11 +33,9 @@ use middle::mem_categorization as mc;
 use middle::traits;
 use middle::ty::{self, Ty};
 use util::nodemap::NodeMap;
-use util::ppaux;
 
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
 
 use std::collections::hash_map::Entry;
@@ -79,6 +78,7 @@ bitflags! {
 #[derive(Copy, Clone, Eq, PartialEq)]
 enum Mode {
     Const,
+    ConstFn,
     Static,
     StaticMut,
 
@@ -136,10 +136,111 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         })
     }
 
+    fn fn_like(&mut self,
+               fk: visit::FnKind,
+               fd: &ast::FnDecl,
+               b: &ast::Block,
+               s: Span,
+               fn_id: ast::NodeId)
+               -> ConstQualif {
+        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
+            Entry::Occupied(entry) => return *entry.get(),
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(ConstQualif::empty());
+            }
+        }
+
+        let mode = match fk {
+            visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
+                Mode::ConstFn
+            }
+            visit::FkMethod(_, m, _) => {
+                if m.constness == ast::Constness::Const {
+                    Mode::ConstFn
+                } else {
+                    Mode::Var
+                }
+            }
+            _ => Mode::Var
+        };
+
+        // Ensure the arguments are simple, not mutable/by-ref or patterns.
+        if mode == Mode::ConstFn {
+            for arg in &fd.inputs {
+                match arg.pat.node {
+                    ast::PatIdent(ast::BindByValue(ast::MutImmutable), _, None) => {}
+                    _ => {
+                        span_err!(self.tcx.sess, arg.pat.span, E0022,
+                                  "arguments of constant functions can only \
+                                   be immutable by-value bindings");
+                    }
+                }
+            }
+        }
+
+        let qualif = self.with_mode(mode, |this| {
+            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
+            visit::walk_fn(this, fk, fd, b, s);
+            this.qualif
+        });
+
+        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
+        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
+        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
+
+        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
+        qualif
+    }
+
     fn add_qualif(&mut self, qualif: ConstQualif) {
         self.qualif = self.qualif | qualif;
     }
 
+    /// Returns true if the call is to a const fn or method.
+    fn handle_const_fn_call(&mut self,
+                            expr: &ast::Expr,
+                            def_id: ast::DefId,
+                            ret_ty: Ty<'tcx>)
+                            -> bool {
+        if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
+            if
+                // we are in a static/const initializer
+                self.mode != Mode::Var &&
+
+                // feature-gate is not enabled
+                !self.tcx.sess.features.borrow().const_fn &&
+
+                // this doesn't come from a macro that has #[allow_internal_unstable]
+                !self.tcx.sess.codemap().span_allows_unstable(expr.span)
+            {
+                self.tcx.sess.span_err(
+                    expr.span,
+                    &format!("const fns are an unstable feature"));
+                fileline_help!(
+                    self.tcx.sess,
+                    expr.span,
+                    "in Nightly builds, add `#![feature(const_fn)]` to the crate \
+                     attributes to enable");
+            }
+
+            let qualif = self.fn_like(fn_like.kind(),
+                                      fn_like.decl(),
+                                      fn_like.body(),
+                                      fn_like.span(),
+                                      fn_like.id());
+            self.add_qualif(qualif);
+
+            if ty::type_contents(self.tcx, ret_ty).interior_unsafe() {
+                self.add_qualif(ConstQualif::MUTABLE_MEM);
+            }
+
+            true
+        } else {
+            false
+        }
+    }
+
     fn record_borrow(&mut self, id: ast::NodeId, mutbl: ast::Mutability) {
         match self.rvalue_borrows.entry(id) {
             Entry::Occupied(mut entry) => {
@@ -158,6 +259,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
     fn msg(&self) -> &'static str {
         match self.mode {
             Mode::Const => "constant",
+            Mode::ConstFn => "constant function",
             Mode::StaticMut | Mode::Static => "static",
             Mode::Var => unreachable!(),
         }
@@ -170,19 +272,19 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         let suffix = if tcontents.has_dtor() {
             "destructors"
         } else if tcontents.owns_owned() {
-            "owned pointers"
+            "boxes"
         } else {
             return
         };
 
-        self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \
-                                                 to have {}", suffix));
+        span_err!(self.tcx.sess, e.span, E0397,
+                 "mutable statics are not allowed to have {}", suffix);
     }
 
     fn check_static_type(&self, e: &ast::Expr) {
         let ty = ty::node_id_to_type(self.tcx, e.id);
         let infcx = infer::new_infer_ctxt(self.tcx);
-        let mut fulfill_cx = traits::FulfillmentContext::new();
+        let mut fulfill_cx = traits::FulfillmentContext::new(false);
         let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
         fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
         let env = ty::empty_parameter_environment(self.tcx);
@@ -197,7 +299,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
     fn visit_item(&mut self, i: &ast::Item) {
-        debug!("visit_item(item={})", pprust::item_to_string(i));
+        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
         match i.node {
             ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
                 self.check_static_type(&**expr);
@@ -251,9 +353,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 b: &'v ast::Block,
                 s: Span,
                 fn_id: ast::NodeId) {
-        assert!(self.mode == Mode::Var);
-        self.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
-        visit::walk_fn(self, fk, fd, b, s);
+        self.fn_like(fk, fd, b, s, fn_id);
     }
 
     fn visit_pat(&mut self, p: &ast::Pat) {
@@ -269,6 +369,35 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
+    fn visit_block(&mut self, block: &ast::Block) {
+        // Check all statements in the block
+        for stmt in &block.stmts {
+            let span = match stmt.node {
+                ast::StmtDecl(ref decl, _) => {
+                    match decl.node {
+                        ast::DeclLocal(_) => decl.span,
+
+                        // Item statements are allowed
+                        ast::DeclItem(_) => continue
+                    }
+                }
+                ast::StmtExpr(ref expr, _) => expr.span,
+                ast::StmtSemi(ref semi, _) => semi.span,
+                ast::StmtMac(..) => {
+                    self.tcx.sess.span_bug(stmt.span, "unexpanded statement \
+                                                       macro in const?!")
+                }
+            };
+            self.add_qualif(ConstQualif::NOT_CONST);
+            if self.mode != Mode::Var {
+                span_err!(self.tcx.sess, span, E0016,
+                          "blocks in {}s are limited to items and \
+                           tail expressions", self.msg());
+            }
+        }
+        visit::walk_block(self, block);
+    }
+
     fn visit_expr(&mut self, ex: &ast::Expr) {
         let mut outer = self.qualif;
         self.qualif = ConstQualif::empty();
@@ -279,7 +408,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         // Special-case some expressions to avoid certain flags bubbling up.
         match ex.node {
             ast::ExprCall(ref callee, ref args) => {
-                for arg in args.iter() {
+                for arg in args {
                     self.visit_expr(&**arg)
                 }
 
@@ -293,7 +422,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 self.visit_expr(&**element);
                 // The count is checked elsewhere (typeck).
                 let count = match node_ty.sty {
-                    ty::ty_vec(_, Some(n)) => n,
+                    ty::TyArray(_, n) => n,
                     _ => unreachable!()
                 };
                 // [element; 0] is always zero-sized.
@@ -305,7 +434,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 // Compute the most demanding borrow from all the arms'
                 // patterns and set that on the discriminator.
                 let mut borrow = None;
-                for pat in arms.iter().flat_map(|arm| arm.pats.iter()) {
+                for pat in arms.iter().flat_map(|arm| &arm.pats) {
                     let pat_borrow = self.rvalue_borrows.remove(&pat.id);
                     match (borrow, pat_borrow) {
                         (None, _) | (_, Some(ast::MutMutable)) => {
@@ -324,7 +453,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 visit::walk_expr(self, ex);
                 let div_or_rem = op.node == ast::BiDiv || op.node == ast::BiRem;
                 match node_ty.sty {
-                    ty::ty_uint(_) | ty::ty_int(_) if div_or_rem => {
+                    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, None) {
                                 Ok(_) => {}
@@ -399,8 +528,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                         e: &ast::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
-        ty::ty_struct(did, _) |
-        ty::ty_enum(did, _) if ty::has_dtor(v.tcx, did) => {
+        ty::TyStruct(did, _) |
+        ty::TyEnum(did, _) if ty::has_dtor(v.tcx, did) => {
             v.add_qualif(ConstQualif::NEEDS_DROP);
             if v.mode != Mode::Var {
                 v.tcx.sess.span_err(e.span,
@@ -430,36 +559,48 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                           "allocations are not allowed in {}s", v.msg());
             }
         }
-        ast::ExprUnary(ast::UnDeref, ref ptr) => {
-            match ty::node_id_to_type(v.tcx, ptr.id).sty {
-                ty::ty_ptr(_) => {
-                    // This shouldn't be allowed in constants at all.
+        ast::ExprUnary(op, ref inner) => {
+            match ty::node_id_to_type(v.tcx, inner.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op == ast::UnDeref);
+
                     v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0396,
+                                  "raw pointers cannot be dereferenced in {}s", v.msg());
+                    }
                 }
                 _ => {}
             }
         }
-        ast::ExprCast(ref from, _) => {
-            let toty = ty::expr_ty(v.tcx, e);
-            let fromty = ty::expr_ty(v.tcx, &**from);
-            let is_legal_cast =
-                ty::type_is_numeric(toty) ||
-                ty::type_is_unsafe_ptr(toty) ||
-                (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
-            if !is_legal_cast {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0012,
-                              "can not cast to `{}` in {}s",
-                              ppaux::ty_to_string(v.tcx, toty), v.msg());
+        ast::ExprBinary(op, ref lhs, _) => {
+            match ty::node_id_to_type(v.tcx, lhs.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op.node == ast::BiEq || op.node == ast::BiNe ||
+                            op.node == ast::BiLe || op.node == ast::BiLt ||
+                            op.node == ast::BiGe || op.node == ast::BiGt);
+
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0395,
+                                  "raw pointers cannot be compared in {}s", v.msg());
+                    }
                 }
+                _ => {}
             }
-            if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0018,
-                              "can not cast a pointer to an integer in {}s", v.msg());
+        }
+        ast::ExprCast(ref from, _) => {
+            debug!("Checking const cast(id={})", from.id);
+            match v.tcx.cast_kinds.borrow().get(&from.id) {
+                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
+                Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0018,
+                                  "raw pointers cannot be cast to integers in {}s", v.msg());
+                    }
                 }
+                _ => {}
             }
         }
         ast::ExprPath(..) => {
@@ -470,7 +611,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                     v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                 }
                 Some(def::DefStruct(_)) => {
-                    if let ty::ty_bare_fn(..) = node_ty.sty {
+                    if let ty::TyBareFn(..) = node_ty.sty {
                         // Count the function pointer.
                         v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                     }
@@ -482,10 +623,10 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 Some(def::DefStatic(..)) => {
                     match v.mode {
                         Mode::Static | Mode::StaticMut => {}
-                        Mode::Const => {
+                        Mode::Const | Mode::ConstFn => {
                             span_err!(v.tcx.sess, e.span, E0013,
-                                "constants cannot refer to other statics, \
-                                 insert an intermediate constant instead");
+                                "{}s cannot refer to other statics, insert \
+                                 an intermediate constant instead", v.msg());
                         }
                         Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
                     }
@@ -502,6 +643,10 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                                              doesn't point to a constant");
                     }
                 }
+                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);
+                }
                 def => {
                     v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
@@ -526,48 +671,44 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 };
             }
             let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
-            match def {
-                Some(def::DefStruct(..)) => {}
+            let is_const = match def {
+                Some(def::DefStruct(..)) => true,
                 Some(def::DefVariant(..)) => {
                     // Count the discriminator.
                     v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                    true
                 }
-                _ => {
-                    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 \
-                                   struct and enum constructors", v.msg());
-                    }
+                Some(def::DefMethod(did, def::FromImpl(_))) |
+                Some(def::DefFn(did, _)) => {
+                    v.handle_const_fn_call(e, did, node_ty)
                 }
-            }
-        }
-        ast::ExprBlock(ref block) => {
-            // Check all statements in the block
-            let mut block_span_err = |span| {
+                _ => false
+            };
+            if !is_const {
                 v.add_qualif(ConstQualif::NOT_CONST);
                 if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, span, E0016,
-                              "blocks in {}s are limited to items and \
-                               tail expressions", v.msg());
+                    span_err!(v.tcx.sess, e.span, E0015,
+                              "function calls in {}s are limited to \
+                               constant functions, \
+                               struct and enum constructors", v.msg());
                 }
+            }
+        }
+        ast::ExprMethodCall(..) => {
+            let method_did = match v.tcx.method_map.borrow()[&method_call].origin {
+                ty::MethodStatic(did) => Some(did),
+                _ => None
             };
-            for stmt in &block.stmts {
-                match stmt.node {
-                    ast::StmtDecl(ref decl, _) => {
-                        match decl.node {
-                            ast::DeclLocal(_) => block_span_err(decl.span),
-
-                            // Item statements are allowed
-                            ast::DeclItem(_) => {}
-                        }
-                    }
-                    ast::StmtExpr(ref expr, _) => block_span_err(expr.span),
-                    ast::StmtSemi(ref semi, _) => block_span_err(semi.span),
-                    ast::StmtMac(..) => {
-                        v.tcx.sess.span_bug(e.span, "unexpanded statement \
-                                                     macro in const?!")
-                    }
+            let is_const = match method_did {
+                Some(did) => v.handle_const_fn_call(e, did, node_ty),
+                None => false
+            };
+            if !is_const {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    span_err!(v.tcx.sess, e.span, E0378,
+                              "method calls in {}s are limited to \
+                               constant inherent methods", v.msg());
                 }
             }
         }
@@ -588,7 +729,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         }
 
         ast::ExprClosure(..) => {
-            // Paths in constant constexts cannot refer to local variables,
+            // Paths in constant contexts cannot refer to local variables,
             // as there are none, and thus closures can't have upvars there.
             if ty::with_freevars(v.tcx, e.id, |fv| !fv.is_empty()) {
                 assert!(v.mode == Mode::Var,
@@ -597,8 +738,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             }
         }
 
-        ast::ExprUnary(..) |
-        ast::ExprBinary(..) |
+        ast::ExprBlock(_) |
         ast::ExprIndex(..) |
         ast::ExprField(..) |
         ast::ExprTupField(..) |
@@ -625,8 +765,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         // Miscellaneous expressions that could be implemented.
         ast::ExprRange(..) |
 
-        // Various other expressions.
-        ast::ExprMethodCall(..) |
+        // Expressions with side-effects.
         ast::ExprAssign(..) |
         ast::ExprAssignOp(..) |
         ast::ExprInlineAsm(_) |
@@ -665,9 +804,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
                         // statics cannot be consumed by value at any time, that would imply
                         // that they're an initializer (what a const is for) or kept in sync
                         // over time (not feasible), so deny it outright.
-                        self.tcx.sess.span_err(consume_span,
-                            "cannot refer to other statics by value, use the \
-                             address-of operator or a constant instead");
+                        span_err!(self.tcx.sess, consume_span, E0394,
+                                  "cannot refer to other statics by value, use the \
+                                   address-of operator or a constant instead");
                     }
                     break;
                 }
@@ -711,10 +850,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
                     }
                     let mutbl = bk.to_mutbl_lossy();
                     if mutbl == ast::MutMutable && self.mode == Mode::StaticMut {
-                        // Mutable slices are the only `&mut` allowed in globals,
-                        // but only in `static mut`, nowhere else.
+                        // Mutable slices are the only `&mut` allowed in
+                        // globals, but only in `static mut`, nowhere else.
+                        // FIXME: This exception is really weird... there isn't
+                        // any fundamental reason to restrict this based on
+                        // type of the expression.  `&mut [1]` has exactly the
+                        // same representation as &mut 1.
                         match cmt.ty.sty {
-                            ty::ty_vec(_, _) => break,
+                            ty::TyArray(_, _) | ty::TySlice(_) => break,
                             _ => {}
                         }
                     }
index a5ea3629abc84ad8fcce386d44764463b80bbd74..1ec6e0d6d80d0b6595ce8acc0b1867fdef74714c 100644 (file)
@@ -12,7 +12,7 @@ pub use self::Constructor::*;
 use self::Usefulness::*;
 use self::WitnessPreference::*;
 
-use middle::const_eval::{compare_const_vals, const_bool, const_float, const_val};
+use middle::const_eval::{compare_const_vals, ConstVal};
 use middle::const_eval::{eval_const_expr, eval_const_expr_partial};
 use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
 use middle::def::*;
@@ -36,7 +36,6 @@ use syntax::print::pprust::pat_to_string;
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax::visit::{self, Visitor, FnKind};
-use util::ppaux::ty_to_string;
 use util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
@@ -112,9 +111,9 @@ pub enum Constructor {
     /// Enum variants.
     Variant(ast::DefId),
     /// Literal values.
-    ConstantValue(const_val),
+    ConstantValue(ConstVal),
     /// Ranges of literal values (2..5).
-    ConstantRange(const_val, const_val),
+    ConstantRange(ConstVal, ConstVal),
     /// Array patterns of length n.
     Slice(usize),
     /// Array patterns with a subslice.
@@ -187,7 +186,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
 
             for pat in inlined_arms
                 .iter()
-                .flat_map(|&(ref pats, _)| pats.iter()) {
+                .flat_map(|&(ref pats, _)| pats) {
                 // Third, check legality of move bindings.
                 check_legality_of_bindings_in_at_patterns(cx, &**pat);
 
@@ -209,9 +208,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
                 if !type_is_empty(cx.tcx, pat_ty) {
                     // We know the type is inhabited, so this must be wrong
                     span_err!(cx.tcx.sess, ex.span, E0002,
-                        "non-exhaustive patterns: type {} is non-empty",
-                        ty_to_string(cx.tcx, pat_ty)
-                    );
+                              "non-exhaustive patterns: type {} is non-empty",
+                              pat_ty);
                 }
                 // If the type *is* empty, it's vacuously exhaustive
                 return;
@@ -220,7 +218,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
             let matrix: Matrix = inlined_arms
                 .iter()
                 .filter(|&&(_, guard)| guard.is_none())
-                .flat_map(|arm| arm.0.iter())
+                .flat_map(|arm| &arm.0)
                 .map(|pat| vec![&**pat])
                 .collect();
             check_exhaustive(cx, ex.span, &matrix, source);
@@ -234,7 +232,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
         match p.node {
             ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
                 let pat_ty = ty::pat_ty(cx.tcx, p);
-                if let ty::ty_enum(def_id, _) = pat_ty.sty {
+                if let ty::TyEnum(def_id, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(_)) = def {
                         if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
@@ -244,11 +242,11 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                             span_warn!(cx.tcx.sess, p.span, E0170,
                                 "pattern binding `{}` is named the same as one \
                                  of the variants of the type `{}`",
-                                &token::get_ident(ident.node), ty_to_string(cx.tcx, pat_ty));
+                                &token::get_ident(ident.node), pat_ty);
                             fileline_help!(cx.tcx.sess, p.span,
                                 "if you meant to match on a variant, \
                                  consider making the path in the pattern qualified: `{}::{}`",
-                                ty_to_string(cx.tcx, pat_ty), &token::get_ident(ident.node));
+                                pat_ty, &token::get_ident(ident.node));
                         }
                     }
                 }
@@ -264,7 +262,7 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
     ast_util::walk_pat(pat, |p| {
         if let ast::PatLit(ref expr) = p.node {
             match eval_const_expr_partial(cx.tcx, &**expr, None) {
-                Ok(const_float(f)) if f.is_nan() => {
+                Ok(ConstVal::Float(f)) if f.is_nan() => {
                     span_warn!(cx.tcx.sess, p.span, E0003,
                                "unmatchable NaN in pattern, \
                                 use the is_nan method in a guard instead");
@@ -393,9 +391,9 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
     }
 }
 
-fn const_val_to_expr(value: &const_val) -> P<ast::Expr> {
+fn const_val_to_expr(value: &ConstVal) -> P<ast::Expr> {
     let node = match value {
-        &const_bool(b) => ast::LitBool(b),
+        &ConstVal::Bool(b) => ast::LitBool(b),
         _ => unreachable!()
     };
     P(ast::Expr {
@@ -506,9 +504,9 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
     let pats_len = pats.len();
     let mut pats = pats.into_iter().map(|p| P((*p).clone()));
     let pat = match left_ty.sty {
-        ty::ty_tup(_) => ast::PatTup(pats.collect()),
+        ty::TyTuple(_) => ast::PatTup(pats.collect()),
 
-        ty::ty_enum(cid, _) | ty::ty_struct(cid, _)  => {
+        ty::TyEnum(cid, _) | ty::TyStruct(cid, _)  => {
             let (vid, is_structure) = match ctor {
                 &Variant(vid) =>
                     (vid, ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
@@ -535,23 +533,23 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
             }
         }
 
-        ty::ty_rptr(_, ty::mt { ty, mutbl }) => {
+        ty::TyRef(_, ty::mt { ty, mutbl }) => {
             match ty.sty {
-               ty::ty_vec(_, Some(n)) => match ctor {
+               ty::TyArray(_, n) => match ctor {
                     &Single => {
                         assert_eq!(pats_len, n);
                         ast::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
-                ty::ty_vec(_, None) => match ctor {
+                ty::TySlice(_) => match ctor {
                     &Slice(n) => {
                         assert_eq!(pats_len, n);
                         ast::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
-                ty::ty_str => ast::PatWild(ast::PatWildSingle),
+                ty::TyStr => ast::PatWild(ast::PatWildSingle),
 
                 _ => {
                     assert_eq!(pats_len, 1);
@@ -560,7 +558,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
             }
         }
 
-        ty::ty_vec(_, Some(len)) => {
+        ty::TyArray(_, len) => {
             assert_eq!(pats_len, len);
             ast::PatVec(pats.collect(), None, vec![])
         }
@@ -583,7 +581,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
 fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
                        left_ty: Ty, max_slice_length: usize) -> Option<Constructor> {
     let used_constructors: Vec<Constructor> = rows.iter()
-        .flat_map(|row| pat_constructors(cx, row[0], left_ty, max_slice_length).into_iter())
+        .flat_map(|row| pat_constructors(cx, row[0], left_ty, max_slice_length))
         .collect();
     all_constructors(cx, left_ty, max_slice_length)
         .into_iter()
@@ -597,16 +595,16 @@ fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
 fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
                     max_slice_length: usize) -> Vec<Constructor> {
     match left_ty.sty {
-        ty::ty_bool =>
-            [true, false].iter().map(|b| ConstantValue(const_bool(*b))).collect(),
+        ty::TyBool =>
+            [true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
 
-        ty::ty_rptr(_, ty::mt { ty, .. }) => match ty.sty {
-            ty::ty_vec(_, None) =>
+        ty::TyRef(_, ty::mt { ty, .. }) => match ty.sty {
+            ty::TySlice(_) =>
                 range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
             _ => vec!(Single)
         },
 
-        ty::ty_enum(eid, _) =>
+        ty::TyEnum(eid, _) =>
             ty::enum_variants(cx.tcx, eid)
                 .iter()
                 .map(|va| Variant(va.id))
@@ -705,7 +703,7 @@ fn is_useful(cx: &MatchCheckCtxt,
                         let wild_pats: Vec<_> = repeat(DUMMY_WILD_PAT).take(arity).collect();
                         let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
                         let mut new_pats = vec![enum_pat];
-                        new_pats.extend(pats.into_iter());
+                        new_pats.extend(pats);
                         UsefulWithWitness(new_pats)
                     },
                     result => result
@@ -779,7 +777,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
             vec!(ConstantRange(eval_const_expr(cx.tcx, &**lo), eval_const_expr(cx.tcx, &**hi))),
         ast::PatVec(ref before, ref slice, ref after) =>
             match left_ty.sty {
-                ty::ty_vec(_, Some(_)) => vec!(Single),
+                ty::TyArray(_, _) => vec!(Single),
                 _                      => if slice.is_some() {
                     range_inclusive(before.len() + after.len(), max_slice_length)
                         .map(|length| Slice(length))
@@ -804,31 +802,31 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
 /// A struct pattern's arity is the number of fields it contains, etc.
 pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
     match ty.sty {
-        ty::ty_tup(ref fs) => fs.len(),
-        ty::ty_uniq(_) => 1,
-        ty::ty_rptr(_, ty::mt { ty, .. }) => match ty.sty {
-            ty::ty_vec(_, None) => match *ctor {
+        ty::TyTuple(ref fs) => fs.len(),
+        ty::TyBox(_) => 1,
+        ty::TyRef(_, ty::mt { ty, .. }) => match ty.sty {
+            ty::TySlice(_) => match *ctor {
                 Slice(length) => length,
                 ConstantValue(_) => 0,
                 _ => unreachable!()
             },
-            ty::ty_str => 0,
+            ty::TyStr => 0,
             _ => 1
         },
-        ty::ty_enum(eid, _) => {
+        ty::TyEnum(eid, _) => {
             match *ctor {
                 Variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
                 _ => unreachable!()
             }
         }
-        ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
-        ty::ty_vec(_, Some(n)) => n,
+        ty::TyStruct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
+        ty::TyArray(_, n) => n,
         _ => 0
     }
 }
 
 fn range_covered_by_constructor(ctor: &Constructor,
-                                from: &const_val, to: &const_val) -> Option<bool> {
+                                from: &ConstVal, to: &ConstVal) -> Option<bool> {
     let (c_from, c_to) = match *ctor {
         ConstantValue(ref value)        => (value, value),
         ConstantRange(ref from, ref to) => (from, to),
index 5ff1f36f0e06abae12e525a013003809e6539d3f..f5934751c58b282528c85fd6de0a76eb5aaeca3c 100644 (file)
@@ -15,7 +15,6 @@ use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::ty::ParameterEnvironment;
 use middle::ty;
-use util::ppaux::ty_to_string;
 
 use syntax::ast;
 use syntax::codemap::Span;
@@ -59,11 +58,11 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
                span: Span,
                cmt: mc::cmt<'tcx>,
                _: euv::ConsumeMode) {
-        debug!("consume; cmt: {:?}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
-        if !ty::type_is_sized(self.param_env, span, cmt.ty) {
+        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
+        if !ty::type_is_sized(Some(self.param_env), self.tcx, span, cmt.ty) {
             span_err!(self.tcx.sess, span, E0161,
                 "cannot move a value of type {0}: the size of {0} cannot be statically determined",
-                ty_to_string(self.tcx, cmt.ty));
+                cmt.ty);
         }
     }
 
index a521c4531c9a7e50e932eb81596c520754e0618d..41beabc9588d2cb91073af6f66b50b01e857e5c6 100644 (file)
 // This compiler pass detects static items that refer to themselves
 // recursively.
 
+use ast_map;
 use session::Session;
 use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefMap};
 
-use syntax::ast;
-use syntax::{ast_util, ast_map};
+use syntax::{ast, ast_util};
 use syntax::codemap::Span;
 use syntax::visit::Visitor;
 use syntax::visit;
index 091092e3b607992adc637a8fd0ffc0ac80e8c484..ed06ccf1ec649990b8f82f2942eade35761da25f 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.
 //
 #![allow(non_camel_case_types)]
 #![allow(unsigned_negation)]
 
-pub use self::const_val::*;
+use self::ConstVal::*;
 
 use self::ErrKind::*;
 
+use ast_map;
+use ast_map::blocks::FnLikeNode;
 use metadata::csearch;
 use middle::{astencode, def, infer, subst, traits};
 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::ppaux::Repr;
 
 use syntax::ast::{self, Expr};
+use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::feature_gate;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
-use syntax::{ast_map, ast_util, codemap};
+use syntax::{codemap, visit};
 
 use std::borrow::{Cow, IntoCow};
 use std::num::wrapping::OverflowingOps;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry::Vacant;
-use std::{i8, i16, i32, i64};
+use std::{i8, i16, i32, i64, u8, u16, u32, u64};
 use std::rc::Rc;
 
 fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
@@ -126,8 +128,10 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                         Some(ref_id) => {
                             let trait_id = ty::trait_of_item(tcx, def_id)
                                               .unwrap();
+                            let substs = ty::node_id_item_substs(tcx, ref_id)
+                                            .substs;
                             resolve_trait_associated_const(tcx, ti, trait_id,
-                                                           ref_id)
+                                                           substs)
                         }
                         // Technically, without knowing anything about the
                         // expression that generates the obligation, we could
@@ -172,8 +176,10 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                         // a trait-associated const if the caller gives us
                         // the expression that refers to it.
                         Some(ref_id) => {
+                            let substs = ty::node_id_item_substs(tcx, ref_id)
+                                            .substs;
                             resolve_trait_associated_const(tcx, ti, trait_id,
-                                                           ref_id).map(|e| e.id)
+                                                           substs).map(|e| e.id)
                         }
                         None => None
                     }
@@ -198,16 +204,73 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
     }
 }
 
+fn inline_const_fn_from_external_crate(tcx: &ty::ctxt, def_id: ast::DefId)
+                                       -> Option<ast::NodeId> {
+    match tcx.extern_const_fns.borrow().get(&def_id) {
+        Some(&ast::DUMMY_NODE_ID) => return None,
+        Some(&fn_id) => return Some(fn_id),
+        None => {}
+    }
+
+    if !csearch::is_const_fn(&tcx.sess.cstore, def_id) {
+        tcx.extern_const_fns.borrow_mut().insert(def_id, ast::DUMMY_NODE_ID);
+        return None;
+    }
+
+    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)) {
+        csearch::FoundAst::Found(&ast::IIItem(ref item)) => Some(item.id),
+        csearch::FoundAst::Found(&ast::IIImplItem(_, ref item)) => Some(item.id),
+        _ => None
+    };
+    tcx.extern_const_fns.borrow_mut().insert(def_id,
+                                             fn_id.unwrap_or(ast::DUMMY_NODE_ID));
+    fn_id
+}
+
+pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: ast::DefId)
+                                   -> Option<FnLikeNode<'tcx>>
+{
+    let fn_id = if !ast_util::is_local(def_id) {
+        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)) {
+        Some(fn_like) => fn_like,
+        None => return None
+    };
+
+    match fn_like.kind() {
+        visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
+            Some(fn_like)
+        }
+        visit::FkMethod(_, m, _) => {
+            if m.constness == ast::Constness::Const {
+                Some(fn_like)
+            } else {
+                None
+            }
+        }
+        _ => None
+    }
+}
+
 #[derive(Clone, PartialEq)]
-pub enum const_val {
-    const_float(f64),
-    const_int(i64),
-    const_uint(u64),
-    const_str(InternedString),
-    const_binary(Rc<Vec<u8>>),
-    const_bool(bool),
+pub enum ConstVal {
+    Float(f64),
+    Int(i64),
+    Uint(u64),
+    Str(InternedString),
+    Binary(Rc<Vec<u8>>),
+    Bool(bool),
     Struct(ast::NodeId),
-    Tuple(ast::NodeId)
+    Tuple(ast::NodeId),
 }
 
 pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
@@ -267,7 +330,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
     P(ast::Pat { id: expr.id, node: pat, span: span })
 }
 
-pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
+pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> ConstVal {
     match eval_const_expr_partial(tcx, e, None) {
         Ok(r) => r,
         Err(s) => tcx.sess.span_fatal(s.span, &s.description())
@@ -370,8 +433,8 @@ impl ConstEvalErr {
     }
 }
 
-pub type EvalResult = Result<const_val, ConstEvalErr>;
-pub type CastResult = Result<const_val, ErrKind>;
+pub type EvalResult = Result<ConstVal, ConstEvalErr>;
+pub type CastResult = Result<ConstVal, ErrKind>;
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum IntTy { I8, I16, I32, I64 }
@@ -451,14 +514,24 @@ pub fn const_int_checked_neg<'a>(
     if oflo {
         signal!(e, NegateWithOverflow(a));
     } else {
-        Ok(const_int(-a))
+        Ok(Int(-a))
     }
 }
 
 pub fn const_uint_checked_neg<'a>(
     a: u64, _e: &'a Expr, _opt_ety: Option<UintTy>) -> EvalResult {
     // This always succeeds, and by definition, returns `(!a)+1`.
-    Ok(const_uint((!a).wrapping_add(1)))
+    Ok(Uint((!a).wrapping_add(1)))
+}
+
+fn const_uint_not(a: u64, opt_ety: Option<UintTy>) -> ConstVal {
+    let mask = match opt_ety {
+        Some(UintTy::U8) => u8::MAX as u64,
+        Some(UintTy::U16) => u16::MAX as u64,
+        Some(UintTy::U32) => u32::MAX as u64,
+        None | Some(UintTy::U64) => u64::MAX,
+    };
+    Uint(!a & mask)
 }
 
 macro_rules! overflow_checking_body {
@@ -550,93 +623,107 @@ macro_rules! pub_fn_checked_op {
 }
 
 pub_fn_checked_op!{ const_int_checked_add(a: i64, b: i64,.. IntTy) {
-           int_arith_body overflowing_add const_int AddiWithOverflow(a, b)
+           int_arith_body overflowing_add Int AddiWithOverflow(a, b)
 }}
 
 pub_fn_checked_op!{ const_int_checked_sub(a: i64, b: i64,.. IntTy) {
-           int_arith_body overflowing_sub const_int SubiWithOverflow(a, b)
+           int_arith_body overflowing_sub Int SubiWithOverflow(a, b)
 }}
 
 pub_fn_checked_op!{ const_int_checked_mul(a: i64, b: i64,.. IntTy) {
-           int_arith_body overflowing_mul const_int MuliWithOverflow(a, b)
+           int_arith_body overflowing_mul Int MuliWithOverflow(a, b)
 }}
 
 pub fn const_int_checked_div<'a>(
     a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
     if b == 0 { signal!(e, DivideByZero); }
     let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_div);
-    if !oflo { Ok(const_int(ret)) } else { signal!(e, DivideWithOverflow) }
+    if !oflo { Ok(Int(ret)) } else { signal!(e, DivideWithOverflow) }
 }
 
 pub fn const_int_checked_rem<'a>(
     a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
     if b == 0 { signal!(e, ModuloByZero); }
     let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_rem);
-    if !oflo { Ok(const_int(ret)) } else { signal!(e, ModuloWithOverflow) }
+    if !oflo { Ok(Int(ret)) } else { signal!(e, ModuloWithOverflow) }
 }
 
 pub_fn_checked_op!{ const_int_checked_shl(a: i64, b: i64,.. IntTy) {
-           int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
+           int_shift_body overflowing_shl Int ShiftLeftWithOverflow
 }}
 
 pub_fn_checked_op!{ const_int_checked_shl_via_uint(a: i64, b: u64,.. IntTy) {
-           int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
+           int_shift_body overflowing_shl Int ShiftLeftWithOverflow
 }}
 
 pub_fn_checked_op!{ const_int_checked_shr(a: i64, b: i64,.. IntTy) {
-           int_shift_body overflowing_shr const_int ShiftRightWithOverflow
+           int_shift_body overflowing_shr Int ShiftRightWithOverflow
 }}
 
 pub_fn_checked_op!{ const_int_checked_shr_via_uint(a: i64, b: u64,.. IntTy) {
-           int_shift_body overflowing_shr const_int ShiftRightWithOverflow
+           int_shift_body overflowing_shr Int ShiftRightWithOverflow
 }}
 
 pub_fn_checked_op!{ const_uint_checked_add(a: u64, b: u64,.. UintTy) {
-           uint_arith_body overflowing_add const_uint AdduWithOverflow(a, b)
+           uint_arith_body overflowing_add Uint AdduWithOverflow(a, b)
 }}
 
 pub_fn_checked_op!{ const_uint_checked_sub(a: u64, b: u64,.. UintTy) {
-           uint_arith_body overflowing_sub const_uint SubuWithOverflow(a, b)
+           uint_arith_body overflowing_sub Uint SubuWithOverflow(a, b)
 }}
 
 pub_fn_checked_op!{ const_uint_checked_mul(a: u64, b: u64,.. UintTy) {
-           uint_arith_body overflowing_mul const_uint MuluWithOverflow(a, b)
+           uint_arith_body overflowing_mul Uint MuluWithOverflow(a, b)
 }}
 
 pub fn const_uint_checked_div<'a>(
     a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
     if b == 0 { signal!(e, DivideByZero); }
     let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_div);
-    if !oflo { Ok(const_uint(ret)) } else { signal!(e, DivideWithOverflow) }
+    if !oflo { Ok(Uint(ret)) } else { signal!(e, DivideWithOverflow) }
 }
 
 pub fn const_uint_checked_rem<'a>(
     a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
     if b == 0 { signal!(e, ModuloByZero); }
     let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_rem);
-    if !oflo { Ok(const_uint(ret)) } else { signal!(e, ModuloWithOverflow) }
+    if !oflo { Ok(Uint(ret)) } else { signal!(e, ModuloWithOverflow) }
 }
 
 pub_fn_checked_op!{ const_uint_checked_shl(a: u64, b: u64,.. UintTy) {
-           uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
+           uint_shift_body overflowing_shl Uint ShiftLeftWithOverflow
 }}
 
 pub_fn_checked_op!{ const_uint_checked_shl_via_int(a: u64, b: i64,.. UintTy) {
-           uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
+           uint_shift_body overflowing_shl Uint ShiftLeftWithOverflow
 }}
 
 pub_fn_checked_op!{ const_uint_checked_shr(a: u64, b: u64,.. UintTy) {
-           uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
+           uint_shift_body overflowing_shr Uint ShiftRightWithOverflow
 }}
 
 pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) {
-           uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
+           uint_shift_body overflowing_shr Uint ShiftRightWithOverflow
 }}
 
+// After type checking, `eval_const_expr_partial` should always suffice. The
+// reason for providing `eval_const_expr_with_substs` is to allow
+// trait-associated consts to be evaluated *during* type checking, when the
+// substs for each expression have not been written into `tcx` yet.
 pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      e: &Expr,
                                      ty_hint: Option<Ty<'tcx>>) -> EvalResult {
-    fn fromb(b: bool) -> const_val { const_int(b as i64) }
+    eval_const_expr_with_substs(tcx, e, ty_hint, |id| {
+        ty::node_id_item_substs(tcx, id).substs
+    })
+}
+
+pub fn eval_const_expr_with_substs<'tcx, S>(tcx: &ty::ctxt<'tcx>,
+                                            e: &Expr,
+                                            ty_hint: Option<Ty<'tcx>>,
+                                            get_substs: S) -> EvalResult
+        where S: Fn(ast::NodeId) -> subst::Substs<'tcx> {
+    fn fromb(b: bool) -> ConstVal { Int(b as i64) }
 
     let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e));
 
@@ -644,20 +731,20 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
     // bindings so that isize/usize is mapped to a type with an
     // inherently known bitwidth.
     let expr_int_type = ety.and_then(|ty| {
-        if let ty::ty_int(t) = ty.sty {
+        if let ty::TyInt(t) = ty.sty {
             Some(IntTy::from(tcx, t)) } else { None }
     });
     let expr_uint_type = ety.and_then(|ty| {
-        if let ty::ty_uint(t) = ty.sty {
+        if let ty::TyUint(t) = ty.sty {
             Some(UintTy::from(tcx, t)) } else { None }
     });
 
     let result = match e.node {
       ast::ExprUnary(ast::UnNeg, ref inner) => {
         match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
-          const_float(f) => const_float(-f),
-          const_int(n) =>  try!(const_int_checked_neg(n, e, expr_int_type)),
-          const_uint(i) => {
+          Float(f) => Float(-f),
+          Int(n) =>  try!(const_int_checked_neg(n, e, expr_int_type)),
+          Uint(i) => {
               if !tcx.sess.features.borrow().negate_unsigned {
                   feature_gate::emit_feature_err(
                       &tcx.sess.parse_sess.span_diagnostic,
@@ -667,23 +754,23 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               }
               try!(const_uint_checked_neg(i, e, expr_uint_type))
           }
-          const_str(_) => signal!(e, NegateOnString),
-          const_bool(_) => signal!(e, NegateOnBoolean),
-          const_binary(_) => signal!(e, NegateOnBinary),
-          const_val::Tuple(_) => signal!(e, NegateOnTuple),
-          const_val::Struct(..) => signal!(e, NegateOnStruct),
+          Str(_) => signal!(e, NegateOnString),
+          Bool(_) => signal!(e, NegateOnBoolean),
+          Binary(_) => signal!(e, NegateOnBinary),
+          Tuple(_) => signal!(e, NegateOnTuple),
+          Struct(..) => signal!(e, NegateOnStruct),
         }
       }
       ast::ExprUnary(ast::UnNot, ref inner) => {
         match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
-          const_int(i) => const_int(!i),
-          const_uint(i) => const_uint(!i),
-          const_bool(b) => const_bool(!b),
-          const_str(_) => signal!(e, NotOnString),
-          const_float(_) => signal!(e, NotOnFloat),
-          const_binary(_) => signal!(e, NotOnBinary),
-          const_val::Tuple(_) => signal!(e, NotOnTuple),
-          const_val::Struct(..) => signal!(e, NotOnStruct),
+          Int(i) => Int(!i),
+          Uint(i) => const_uint_not(i, expr_uint_type),
+          Bool(b) => Bool(!b),
+          Str(_) => signal!(e, NotOnString),
+          Float(_) => signal!(e, NotOnFloat),
+          Binary(_) => signal!(e, NotOnBinary),
+          Tuple(_) => signal!(e, NotOnTuple),
+          Struct(..) => signal!(e, NotOnStruct),
         }
       }
       ast::ExprBinary(op, ref a, ref b) => {
@@ -693,13 +780,13 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         };
         match (try!(eval_const_expr_partial(tcx, &**a, ety)),
                try!(eval_const_expr_partial(tcx, &**b, b_ty))) {
-          (const_float(a), const_float(b)) => {
+          (Float(a), Float(b)) => {
             match op.node {
-              ast::BiAdd => const_float(a + b),
-              ast::BiSub => const_float(a - b),
-              ast::BiMul => const_float(a * b),
-              ast::BiDiv => const_float(a / b),
-              ast::BiRem => const_float(a % b),
+              ast::BiAdd => Float(a + b),
+              ast::BiSub => Float(a - b),
+              ast::BiMul => Float(a * b),
+              ast::BiDiv => Float(a / b),
+              ast::BiRem => Float(a % b),
               ast::BiEq => fromb(a == b),
               ast::BiLt => fromb(a < b),
               ast::BiLe => fromb(a <= b),
@@ -709,16 +796,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               _ => signal!(e, InvalidOpForFloats(op.node))
             }
           }
-          (const_int(a), const_int(b)) => {
+          (Int(a), Int(b)) => {
             match op.node {
               ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
               ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
               ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
               ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
               ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
-              ast::BiAnd | ast::BiBitAnd => const_int(a & b),
-              ast::BiOr | ast::BiBitOr => const_int(a | b),
-              ast::BiBitXor => const_int(a ^ b),
+              ast::BiAnd | ast::BiBitAnd => Int(a & b),
+              ast::BiOr | ast::BiBitOr => Int(a | b),
+              ast::BiBitXor => Int(a ^ b),
               ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
               ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
               ast::BiEq => fromb(a == b),
@@ -729,16 +816,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               ast::BiGt => fromb(a > b)
             }
           }
-          (const_uint(a), const_uint(b)) => {
+          (Uint(a), Uint(b)) => {
             match op.node {
               ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
               ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
               ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
               ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
               ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
-              ast::BiAnd | ast::BiBitAnd => const_uint(a & b),
-              ast::BiOr | ast::BiBitOr => const_uint(a | b),
-              ast::BiBitXor => const_uint(a ^ b),
+              ast::BiAnd | ast::BiBitAnd => Uint(a & b),
+              ast::BiOr | ast::BiBitOr => Uint(a | b),
+              ast::BiBitXor => Uint(a ^ b),
               ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
               ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
               ast::BiEq => fromb(a == b),
@@ -750,22 +837,22 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
           }
           // shifts can have any integral type as their rhs
-          (const_int(a), const_uint(b)) => {
+          (Int(a), Uint(b)) => {
             match op.node {
               ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
               ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
               _ => signal!(e, InvalidOpForIntUint(op.node)),
             }
           }
-          (const_uint(a), const_int(b)) => {
+          (Uint(a), Int(b)) => {
             match op.node {
               ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
               ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
               _ => signal!(e, InvalidOpForUintInt(op.node)),
             }
           }
-          (const_bool(a), const_bool(b)) => {
-            const_bool(match op.node {
+          (Bool(a), Bool(b)) => {
+            Bool(match op.node {
               ast::BiAnd => a && b,
               ast::BiOr => a || b,
               ast::BiBitXor => a ^ b,
@@ -826,8 +913,11 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                           def::FromTrait(trait_id) => match tcx.map.find(def_id.node) {
                               Some(ast_map::NodeTraitItem(ti)) => match ti.node {
                                   ast::ConstTraitItem(ref ty, _) => {
-                                      (resolve_trait_associated_const(tcx, ti,
-                                                                      trait_id, e.id),
+                                      let substs = get_substs(e.id);
+                                      (resolve_trait_associated_const(tcx,
+                                                                      ti,
+                                                                      trait_id,
+                                                                      substs),
                                        Some(&**ty))
                                   }
                                   _ => (None, None)
@@ -867,18 +957,14 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
       ast::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ety)),
-            None => const_int(0)
+            None => Int(0)
         }
       }
-      ast::ExprTup(_) => {
-        const_val::Tuple(e.id)
-      }
-      ast::ExprStruct(..) => {
-        const_val::Struct(e.id)
-      }
+      ast::ExprTup(_) => Tuple(e.id),
+      ast::ExprStruct(..) => Struct(e.id),
       ast::ExprTupField(ref base, index) => {
         if let Ok(c) = eval_const_expr_partial(tcx, base, None) {
-            if let const_val::Tuple(tup_id) = c {
+            if let Tuple(tup_id) = c {
                 if let ast::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
                     if index.node < fields.len() {
                         return eval_const_expr_partial(tcx, &fields[index.node], None)
@@ -898,7 +984,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
       ast::ExprField(ref base, field_name) => {
         // Get the base expression if it is a struct and it is constant
         if let Ok(c) = eval_const_expr_partial(tcx, base, None) {
-            if let const_val::Struct(struct_id) = c {
+            if let Struct(struct_id) = c {
                 if let ast::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node {
                     // Check that the given field exists and evaluate it
                     if let Some(f) = fields.iter().find(|f| f.ident.node.as_str()
@@ -926,10 +1012,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                                                 ti: &'tcx ast::TraitItem,
                                                 trait_id: ast::DefId,
-                                                ref_id: ast::NodeId)
+                                                rcvr_substs: subst::Substs<'tcx>)
                                                 -> Option<&'tcx Expr>
 {
-    let rcvr_substs = ty::node_id_item_substs(tcx, ref_id).substs;
     let subst::SeparateVecsPerParamSpace {
         types: rcvr_type,
         selfs: rcvr_self,
@@ -940,8 +1025,8 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                                                            rcvr_self,
                                                            Vec::new()));
     let trait_substs = tcx.mk_substs(trait_substs);
-    debug!("resolve_trait_associated_const: trait_substs={}",
-           trait_substs.repr(tcx));
+    debug!("resolve_trait_associated_const: trait_substs={:?}",
+           trait_substs);
     let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
                                               substs: trait_substs });
 
@@ -962,10 +1047,10 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         }
         Err(e) => {
             tcx.sess.span_bug(ti.span,
-                              &format!("Encountered error `{}` when trying \
+                              &format!("Encountered error `{:?}` when trying \
                                         to select an implementation for \
                                         constant trait item reference.",
-                                       e.repr(tcx)))
+                                       e))
         }
     };
 
@@ -988,14 +1073,14 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
     }
 }
 
-fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult {
+fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: ConstVal, ty: Ty) -> CastResult {
     macro_rules! convert_val {
         ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
             match val {
-                const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
-                const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
-                const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
-                const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
+                Bool(b) => Ok($const_type(b as u64 as $intermediate_ty as $target_ty)),
+                Uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
+                Int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
+                Float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
                 _ => Err(ErrKind::CannotCastTo(stringify!($const_type))),
             }
         }
@@ -1003,68 +1088,68 @@ fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, 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::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64),
-        (&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64),
-        (&ty::ty_int(ast::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::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64),
-        (&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64),
-        (&ty::ty_uint(ast::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::ty_int(ast::TyIs) => unreachable!(),
-        ty::ty_uint(ast::TyUs) => unreachable!(),
+        ty::TyInt(ast::TyIs) => unreachable!(),
+        ty::TyUint(ast::TyUs) => unreachable!(),
 
-        ty::ty_int(ast::TyI8) => convert_val!(i8, const_int, i64),
-        ty::ty_int(ast::TyI16) => convert_val!(i16, const_int, i64),
-        ty::ty_int(ast::TyI32) => convert_val!(i32, const_int, i64),
-        ty::ty_int(ast::TyI64) => convert_val!(i64, const_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::ty_uint(ast::TyU8) => convert_val!(u8, const_uint, u64),
-        ty::ty_uint(ast::TyU16) => convert_val!(u16, const_uint, u64),
-        ty::ty_uint(ast::TyU32) => convert_val!(u32, const_uint, u64),
-        ty::ty_uint(ast::TyU64) => convert_val!(u64, const_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::ty_float(ast::TyF32) => convert_val!(f32, const_float, f64),
-        ty::ty_float(ast::TyF64) => convert_val!(f64, const_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: &ast::Lit, ty_hint: Option<Ty>) -> const_val {
+fn lit_to_const(lit: &ast::Lit, ty_hint: Option<Ty>) -> ConstVal {
     match lit.node {
-        ast::LitStr(ref s, _) => const_str((*s).clone()),
+        ast::LitStr(ref s, _) => Str((*s).clone()),
         ast::LitBinary(ref data) => {
-            const_binary(data.clone())
+            Binary(data.clone())
         }
-        ast::LitByte(n) => const_uint(n as u64),
-        ast::LitChar(n) => const_uint(n as u64),
-        ast::LitInt(n, ast::SignedIntLit(_, ast::Plus)) => const_int(n as i64),
+        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::ty_uint(_)) => const_uint(n),
-                _ => const_int(n as i64)
+                Some(&ty::TyUint(_)) => Uint(n),
+                _ => Int(n as i64)
             }
         }
         ast::LitInt(n, ast::SignedIntLit(_, ast::Minus)) |
-        ast::LitInt(n, ast::UnsuffixedIntLit(ast::Minus)) => const_int(-(n as i64)),
-        ast::LitInt(n, ast::UnsignedIntLit(_)) => const_uint(n),
+        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) => {
-            const_float(n.parse::<f64>().unwrap() as f64)
+            Float(n.parse::<f64>().unwrap() as f64)
         }
-        ast::LitBool(b) => const_bool(b)
+        ast::LitBool(b) => Bool(b)
     }
 }
 
-pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<Ordering> {
+pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
     Some(match (a, b) {
-        (&const_int(a), &const_int(b)) => a.cmp(&b),
-        (&const_uint(a), &const_uint(b)) => a.cmp(&b),
-        (&const_float(a), &const_float(b)) => {
+        (&Int(a), &Int(b)) => a.cmp(&b),
+        (&Uint(a), &Uint(b)) => a.cmp(&b),
+        (&Float(a), &Float(b)) => {
             // This is pretty bad but it is the existing behavior.
             if a == b {
                 Ordering::Equal
@@ -1074,26 +1159,28 @@ pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<Ordering> {
                 Ordering::Greater
             }
         }
-        (&const_str(ref a), &const_str(ref b)) => a.cmp(b),
-        (&const_bool(a), &const_bool(b)) => a.cmp(&b),
-        (&const_binary(ref a), &const_binary(ref b)) => a.cmp(b),
+        (&Str(ref a), &Str(ref b)) => a.cmp(b),
+        (&Bool(a), &Bool(b)) => a.cmp(&b),
+        (&Binary(ref a), &Binary(ref b)) => a.cmp(b),
         _ => return None
     })
 }
 
-pub fn compare_lit_exprs<'tcx>(tcx: &ty::ctxt<'tcx>,
-                               a: &Expr,
-                               b: &Expr,
-                               ty_hint: Option<Ty<'tcx>>)
-                               -> Option<Ordering> {
-    let a = match eval_const_expr_partial(tcx, a, ty_hint) {
+pub fn compare_lit_exprs<'tcx, S>(tcx: &ty::ctxt<'tcx>,
+                                  a: &Expr,
+                                  b: &Expr,
+                                  ty_hint: Option<Ty<'tcx>>,
+                                  get_substs: S) -> Option<Ordering>
+        where S: Fn(ast::NodeId) -> subst::Substs<'tcx> {
+    let a = match eval_const_expr_with_substs(tcx, a, ty_hint,
+                                              |id| {get_substs(id)}) {
         Ok(a) => a,
         Err(e) => {
             tcx.sess.span_err(a.span, &e.description());
             return None;
         }
     };
-    let b = match eval_const_expr_partial(tcx, b, ty_hint) {
+    let b = match eval_const_expr_with_substs(tcx, b, ty_hint, get_substs) {
         Ok(b) => b,
         Err(e) => {
             tcx.sess.span_err(b.span, &e.description());
index 1d5d4f72fc2da7693531a303e7e89a8927c2fe02..b69a086257341dc0994a4abcdef5aed5b91b6cc8 100644 (file)
@@ -634,7 +634,7 @@ fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
                                op: &Op) -> bool {
     assert_eq!(out_vec.len(), in_vec.len());
     let mut changed = false;
-    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec.iter()) {
+    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
         let old_val = *out_elt;
         let new_val = op.join(old_val, *in_elt);
         *out_elt = new_val;
index 1aa2ca9115d2f61429d3d62b36921c1254138db2..fd810429c86e03dc79fb4250ed5a50457ed5d2fc 100644 (file)
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.
 
+use ast_map;
 use middle::{def, pat_util, privacy, ty};
 use lint;
 use util::nodemap::NodeSet;
 
 use std::collections::HashSet;
-use syntax::{ast, ast_map, codemap};
+use syntax::{ast, codemap};
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr::{self, AttrMetaMethods};
 use syntax::visit::{self, Visitor};
@@ -47,6 +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>,
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
@@ -59,6 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             struct_has_extern_repr: false,
             ignore_non_const_paths: false,
             inherited_pub_visibility: false,
+            ignore_variant_stack: vec![],
         }
     }
 
@@ -79,7 +82,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 def::DefPrimTy(_) => (),
                 def::DefVariant(enum_id, variant_id, _) => {
                     self.check_def_id(enum_id);
-                    self.check_def_id(variant_id);
+                    if !self.ignore_variant_stack.contains(&variant_id.node) {
+                        self.check_def_id(variant_id);
+                    }
                 }
                 _ => {
                     self.check_def_id(def.def_id());
@@ -128,7 +133,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
     fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) {
         match ty::expr_ty_adjusted(self.tcx, lhs).sty {
-            ty::ty_struct(id, _) => {
+            ty::TyStruct(id, _) => {
                 let fields = ty::lookup_struct_fields(self.tcx, id);
                 let field_id = fields.iter()
                     .find(|field| field.name == name).unwrap().id;
@@ -140,7 +145,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
     fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: usize) {
         match ty::expr_ty_adjusted(self.tcx, lhs).sty {
-            ty::ty_struct(id, _) => {
+            ty::TyStruct(id, _) => {
                 let fields = ty::lookup_struct_fields(self.tcx, id);
                 let field_id = fields[idx].id;
                 self.live_symbols.insert(field_id.node);
@@ -167,6 +172,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         };
         let fields = ty::lookup_struct_fields(self.tcx, id);
         for pat in pats {
+            if let ast::PatWild(ast::PatWildSingle) = pat.node.pat.node {
+                continue;
+            }
             let field_id = fields.iter()
                 .find(|field| field.name == pat.node.ident.name).unwrap().id;
             self.live_symbols.insert(field_id.node);
@@ -271,6 +279,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         visit::walk_expr(self, expr);
     }
 
+    fn visit_arm(&mut self, arm: &ast::Arm) {
+        if arm.pats.len() == 1 {
+            let pat = &*arm.pats[0];
+            let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
+
+            // Inside the body, ignore constructions of variants
+            // necessary for the pattern to match. Those construction sites
+            // can't be reached unless the variant is constructed elsewhere.
+            let len = self.ignore_variant_stack.len();
+            self.ignore_variant_stack.push_all(&*variants);
+            visit::walk_arm(self, arm);
+            self.ignore_variant_stack.truncate(len);
+        } else {
+            visit::walk_arm(self, arm);
+        }
+    }
+
     fn visit_pat(&mut self, pat: &ast::Pat) {
         let def_map = &self.tcx.def_map;
         match pat.node {
@@ -392,6 +417,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
         worklist.push(*id);
     }
     for id in reachable_symbols {
+        // Reachable variants can be dead, because we warn about
+        // variants never constructed, not variants never used.
+        if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
+            continue;
+        }
         worklist.push(*id);
     }
 
@@ -490,8 +520,8 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
         match self.tcx.inherent_impls.borrow().get(&local_def(id)) {
             None => (),
             Some(impl_list) => {
-                for impl_did in &**impl_list {
-                    for item_did in &*impl_items.get(impl_did).unwrap() {
+                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;
index 0b688e1e08a2e3eabdc7a7324b3eb2cf05c0784c..ff5178fbefc102a4df631580814373b53496c5ad 100644 (file)
@@ -85,7 +85,7 @@ pub type Dependencies = FnvHashMap<config::CrateType, DependencyList>;
 
 pub fn calculate(tcx: &ty::ctxt) {
     let mut fmts = tcx.dependency_formats.borrow_mut();
-    for &ty in &*tcx.sess.crate_types.borrow() {
+    for &ty in tcx.sess.crate_types.borrow().iter() {
         fmts.insert(ty, calculate_type(&tcx.sess, ty));
     }
     tcx.sess.abort_if_errors();
index b6a070c9332fda45b3e894ec19eab99a20252319..bb63ec42d8c0cb9c87473545e46ea77e8f5b6cdb 100644 (file)
@@ -15,7 +15,6 @@ use self::UnsafeContext::*;
 use middle::def;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
-use util::ppaux;
 
 use syntax::ast;
 use syntax::codemap::Span;
@@ -31,7 +30,7 @@ enum UnsafeContext {
 
 fn type_is_unsafe_function(ty: Ty) -> bool {
     match ty.sty {
-        ty::ty_bare_fn(_, ref f) => f.unsafety == ast::Unsafety::Unsafe,
+        ty::TyBareFn(_, ref f) => f.unsafety == ast::Unsafety::Unsafe,
         _ => false,
     }
 }
@@ -66,14 +65,14 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
             ast::ExprIndex(ref base, _) => ty::node_id_to_type(self.tcx, base.id),
             _ => return
         };
-        debug!("effect: checking index with base type {}",
-                ppaux::ty_to_string(self.tcx, base_type));
+        debug!("effect: checking index with base type {:?}",
+                 base_type);
         match base_type.sty {
-            ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => if ty::ty_str == ty.sty {
+            ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => if ty::TyStr == ty.sty {
                 span_err!(self.tcx.sess, e.span, E0134,
                           "modification of string types is not allowed");
             },
-            ty::ty_str => {
+            ty::TyStr => {
                 span_err!(self.tcx.sess, e.span, E0135,
                           "modification of string types is not allowed");
             }
@@ -87,8 +86,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 block: &'v ast::Block, span: Span, _: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
-            visit::FkItemFn(_, _, fn_style, _, _) =>
-                (true, fn_style == ast::Unsafety::Unsafe),
+            visit::FkItemFn(_, _, unsafety, _, _, _) =>
+                (true, unsafety == ast::Unsafety::Unsafe),
             visit::FkMethod(_, sig, _) =>
                 (true, sig.unsafety == ast::Unsafety::Unsafe),
             _ => (false, false),
@@ -142,8 +141,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
             ast::ExprMethodCall(_, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
                 let base_type = self.tcx.method_map.borrow().get(&method_call).unwrap().ty;
-                debug!("effect: method call case, base type is {}",
-                       ppaux::ty_to_string(self.tcx, base_type));
+                debug!("effect: method call case, base type is {:?}",
+                        base_type);
                 if type_is_unsafe_function(base_type) {
                     self.require_unsafe(expr.span,
                                         "invocation of unsafe method")
@@ -151,18 +150,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
             }
             ast::ExprCall(ref base, _) => {
                 let base_type = ty::node_id_to_type(self.tcx, base.id);
-                debug!("effect: call case, base type is {}",
-                       ppaux::ty_to_string(self.tcx, base_type));
+                debug!("effect: call case, base type is {:?}",
+                        base_type);
                 if type_is_unsafe_function(base_type) {
                     self.require_unsafe(expr.span, "call to unsafe function")
                 }
             }
             ast::ExprUnary(ast::UnDeref, ref base) => {
                 let base_type = ty::node_id_to_type(self.tcx, base.id);
-                debug!("effect: unary case, base type is {}",
-                       ppaux::ty_to_string(self.tcx, base_type));
-                if let ty::ty_ptr(_) = base_type.sty {
-                    self.require_unsafe(expr.span, "dereference of unsafe pointer")
+                debug!("effect: unary case, base type is {:?}",
+                        base_type);
+                if let ty::TyRawPtr(_) = base_type.sty {
+                    self.require_unsafe(expr.span, "dereference of raw pointer")
                 }
             }
             ast::ExprAssign(ref base, _) | ast::ExprAssignOp(_, ref base, _) => {
index 0ce9db1c80f3f21c4741083a46e983a4bb37ea23..c6e5b654f9a5c6ba05de3680c4395d3929a9c171 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 
+use ast_map;
 use session::{config, Session};
 use syntax::ast::{Name, NodeId, Item, ItemFn};
-use syntax::ast_map;
 use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token;
index 7366ad9453498df06de1420ce02609040bcb3fb2..ab67c68be124bd0938f31f5f5e52776acc99b481 100644 (file)
@@ -27,7 +27,6 @@ use middle::ty::{self};
 use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
 use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
 use middle::ty::{MethodStatic, MethodStaticClosure};
-use util::ppaux::Repr;
 
 use syntax::{ast, ast_util};
 use syntax::ptr::P;
@@ -212,11 +211,11 @@ enum OverloadedCallType {
 impl OverloadedCallType {
     fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId)
                      -> OverloadedCallType {
-        for &(maybe_function_trait, overloaded_call_type) in [
+        for &(maybe_function_trait, overloaded_call_type) in &[
             (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall),
             (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall),
             (tcx.lang_items.fn_trait(), FnOverloadedCall)
-        ].iter() {
+        ] {
             match maybe_function_trait {
                 Some(function_trait) if function_trait == trait_id => {
                     return overloaded_call_type
@@ -362,8 +361,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         consume_id: ast::NodeId,
                         consume_span: Span,
                         cmt: mc::cmt<'tcx>) {
-        debug!("delegate_consume(consume_id={}, cmt={})",
-               consume_id, cmt.repr(self.tcx()));
+        debug!("delegate_consume(consume_id={}, cmt={:?})",
+               consume_id, cmt);
 
         let mode = copy_or_move(self.typer, &cmt, DirectRefMove);
         self.delegate.consume(consume_id, consume_span, cmt, mode);
@@ -376,7 +375,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     }
 
     pub fn consume_expr(&mut self, expr: &ast::Expr) {
-        debug!("consume_expr(expr={})", expr.repr(self.tcx()));
+        debug!("consume_expr(expr={:?})", expr);
 
         let cmt = return_if_err!(self.mc.cat_expr(expr));
         self.delegate_consume(expr.id, expr.span, cmt);
@@ -397,8 +396,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                    r: ty::Region,
                    bk: ty::BorrowKind,
                    cause: LoanCause) {
-        debug!("borrow_expr(expr={}, r={}, bk={})",
-               expr.repr(self.tcx()), r.repr(self.tcx()), bk.repr(self.tcx()));
+        debug!("borrow_expr(expr={:?}, r={:?}, bk={:?})",
+               expr, r, bk);
 
         let cmt = return_if_err!(self.mc.cat_expr(expr));
         self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
@@ -414,7 +413,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     }
 
     pub fn walk_expr(&mut self, expr: &ast::Expr) {
-        debug!("walk_expr(expr={})", expr.repr(self.tcx()));
+        debug!("walk_expr(expr={:?})", expr);
 
         self.walk_adjustment(expr);
 
@@ -618,14 +617,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
 
     fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
         let callee_ty = return_if_err!(self.typer.expr_ty_adjusted(callee));
-        debug!("walk_callee: callee={} callee_ty={}",
-               callee.repr(self.tcx()), callee_ty.repr(self.tcx()));
+        debug!("walk_callee: callee={:?} callee_ty={:?}",
+               callee, callee_ty);
         let call_scope = region::CodeExtent::from_node_id(call.id);
         match callee_ty.sty {
-            ty::ty_bare_fn(..) => {
+            ty::TyBareFn(..) => {
                 self.consume_expr(callee);
             }
-            ty::ty_err => { }
+            ty::TyError => { }
             _ => {
                 let overloaded_call_type =
                     match self.typer.node_method_origin(MethodCall::expr(call.id)) {
@@ -637,7 +636,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         None => {
                             self.tcx().sess.span_bug(
                                 callee.span,
-                                &format!("unexpected callee type {}", callee_ty.repr(self.tcx())))
+                                &format!("unexpected callee type {}", callee_ty))
                         }
                     };
                 match overloaded_call_type {
@@ -740,7 +739,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         // Select just those fields of the `with`
         // expression that will actually be used
         let with_fields = match with_cmt.ty.sty {
-            ty::ty_struct(did, substs) => {
+            ty::TyStruct(did, substs) => {
                 ty::struct_fields(self.tcx(), did, substs)
             }
             _ => {
@@ -811,7 +810,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     fn walk_autoderefs(&mut self,
                        expr: &ast::Expr,
                        autoderefs: usize) {
-        debug!("walk_autoderefs expr={} autoderefs={}", expr.repr(self.tcx()), autoderefs);
+        debug!("walk_autoderefs expr={:?} autoderefs={}", expr, autoderefs);
 
         for i in 0..autoderefs {
             let deref_id = ty::MethodCall::autoderef(expr.id, i as u32);
@@ -826,10 +825,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     let self_ty = ty::no_late_bound_regions(self.tcx(), &self_ty).unwrap();
 
                     let (m, r) = match self_ty.sty {
-                        ty::ty_rptr(r, ref m) => (m.mutbl, r),
+                        ty::TyRef(r, ref m) => (m.mutbl, r),
                         _ => self.tcx().sess.span_bug(expr.span,
-                                &format!("bad overloaded deref type {}",
-                                    method_ty.repr(self.tcx())))
+                                &format!("bad overloaded deref type {:?}",
+                                    method_ty))
                     };
                     let bk = ty::BorrowKind::from_mutbl(m);
                     self.delegate.borrow(expr.id, expr.span, cmt,
@@ -842,9 +841,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     fn walk_autoderefref(&mut self,
                          expr: &ast::Expr,
                          adj: &ty::AutoDerefRef<'tcx>) {
-        debug!("walk_autoderefref expr={} adj={}",
-               expr.repr(self.tcx()),
-               adj.repr(self.tcx()));
+        debug!("walk_autoderefref expr={:?} adj={:?}",
+               expr,
+               adj);
 
         self.walk_autoderefs(expr, adj.autoderefs);
 
@@ -875,9 +874,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     opt_autoref: Option<ty::AutoRef<'tcx>>)
                     -> mc::cmt<'tcx>
     {
-        debug!("walk_autoref(expr.id={} cmt_derefd={} opt_autoref={:?})",
+        debug!("walk_autoref(expr.id={} cmt_derefd={:?} opt_autoref={:?})",
                expr.id,
-               cmt_base.repr(self.tcx()),
+               cmt_base,
                opt_autoref);
 
         let cmt_base_ty = cmt_base.ty;
@@ -901,9 +900,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
 
             ty::AutoUnsafe(m) => {
-                debug!("walk_autoref: expr.id={} cmt_base={}",
+                debug!("walk_autoref: expr.id={} cmt_base={:?}",
                        expr.id,
-                       cmt_base.repr(self.tcx()));
+                       cmt_base);
 
                 // Converting from a &T to *T (or &mut T to *mut T) is
                 // treated as borrowing it for the enclosing temporary
@@ -1011,8 +1010,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                                cmt_discr: mc::cmt<'tcx>,
                                pat: &ast::Pat,
                                mode: &mut TrackMatchMode) {
-        debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
-               pat.repr(self.tcx()));
+        debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
+               pat);
         return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
             let tcx = self.tcx();
             let def_map = &self.tcx().def_map;
@@ -1043,8 +1042,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 cmt_discr: mc::cmt<'tcx>,
                 pat: &ast::Pat,
                 match_mode: MatchMode) {
-        debug!("walk_pat cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
-               pat.repr(self.tcx()));
+        debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
+               pat);
 
         let mc = &self.mc;
         let typer = self.typer;
@@ -1054,9 +1053,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             if pat_util::pat_is_binding(def_map, pat) {
                 let tcx = typer.tcx();
 
-                debug!("binding cmt_pat={} pat={} match_mode={:?}",
-                       cmt_pat.repr(tcx),
-                       pat.repr(tcx),
+                debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
+                       cmt_pat,
+                       pat,
                        match_mode);
 
                 // pat_ty: the type of the binding being produced.
@@ -1160,9 +1159,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                                     mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
                                 };
 
-                            debug!("variant downcast_cmt={} pat={}",
-                                   downcast_cmt.repr(tcx),
-                                   pat.repr(tcx));
+                            debug!("variant downcast_cmt={:?} pat={:?}",
+                                   downcast_cmt,
+                                   pat);
 
                             delegate.matched_pat(pat, downcast_cmt, match_mode);
                         }
@@ -1172,9 +1171,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                             // namespace; we encounter the former on
                             // e.g. patterns for unit structs).
 
-                            debug!("struct cmt_pat={} pat={}",
-                                   cmt_pat.repr(tcx),
-                                   pat.repr(tcx));
+                            debug!("struct cmt_pat={:?} pat={:?}",
+                                   cmt_pat,
+                                   pat);
 
                             delegate.matched_pat(pat, cmt_pat, match_mode);
                         }
@@ -1192,9 +1191,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                             // pattern.
 
                             if !tcx.sess.has_errors() {
-                                let msg = format!("Pattern has unexpected type: {:?} and type {}",
+                                let msg = format!("Pattern has unexpected type: {:?} and type {:?}",
                                                   def,
-                                                  cmt_pat.ty.repr(tcx));
+                                                  cmt_pat.ty);
                                 tcx.sess.span_bug(pat.span, &msg)
                             }
                         }
@@ -1209,9 +1208,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                             // reported.
 
                             if !tcx.sess.has_errors() {
-                                let msg = format!("Pattern has unexpected def: {:?} and type {}",
+                                let msg = format!("Pattern has unexpected def: {:?} and type {:?}",
                                                   def,
-                                                  cmt_pat.ty.repr(tcx));
+                                                  cmt_pat.ty);
                                 tcx.sess.span_bug(pat.span, &msg[..])
                             }
                         }
@@ -1237,7 +1236,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     }
 
     fn walk_captures(&mut self, closure_expr: &ast::Expr) {
-        debug!("walk_captures({})", closure_expr.repr(self.tcx()));
+        debug!("walk_captures({:?})", closure_expr);
 
         ty::with_freevars(self.tcx(), closure_expr.id, |freevars| {
             for freevar in freevars {
index 36065aaca57f33b4708d7ce721d95cc54238b6fa..168494043e5c452ec46dfc296a6c6c7555a89f6d 100644 (file)
@@ -48,51 +48,51 @@ pub fn simplify_type(tcx: &ty::ctxt,
                      -> Option<SimplifiedType>
 {
     match ty.sty {
-        ty::ty_bool => Some(BoolSimplifiedType),
-        ty::ty_char => Some(CharSimplifiedType),
-        ty::ty_int(int_type) => Some(IntSimplifiedType(int_type)),
-        ty::ty_uint(uint_type) => Some(UintSimplifiedType(uint_type)),
-        ty::ty_float(float_type) => Some(FloatSimplifiedType(float_type)),
-        ty::ty_enum(def_id, _) => Some(EnumSimplifiedType(def_id)),
-        ty::ty_str => Some(StrSimplifiedType),
-        ty::ty_vec(..) => Some(VecSimplifiedType),
-        ty::ty_ptr(_) => Some(PtrSimplifiedType),
-        ty::ty_trait(ref trait_info) => {
+        ty::TyBool => Some(BoolSimplifiedType),
+        ty::TyChar => Some(CharSimplifiedType),
+        ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)),
+        ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)),
+        ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)),
+        ty::TyEnum(def_id, _) => Some(EnumSimplifiedType(def_id)),
+        ty::TyStr => Some(StrSimplifiedType),
+        ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType),
+        ty::TyRawPtr(_) => Some(PtrSimplifiedType),
+        ty::TyTrait(ref trait_info) => {
             Some(TraitSimplifiedType(trait_info.principal_def_id()))
         }
-        ty::ty_struct(def_id, _) => {
+        ty::TyStruct(def_id, _) => {
             Some(StructSimplifiedType(def_id))
         }
-        ty::ty_rptr(_, mt) => {
+        ty::TyRef(_, mt) => {
             // since we introduce auto-refs during method lookup, we
             // just treat &T and T as equivalent from the point of
             // view of possibly unifying
             simplify_type(tcx, mt.ty, can_simplify_params)
         }
-        ty::ty_uniq(_) => {
+        ty::TyBox(_) => {
             // treat like we would treat `Box`
             let def_id = tcx.lang_items.owned_box().unwrap();
             Some(StructSimplifiedType(def_id))
         }
-        ty::ty_closure(def_id, _) => {
+        ty::TyClosure(def_id, _) => {
             Some(ClosureSimplifiedType(def_id))
         }
-        ty::ty_tup(ref tys) => {
+        ty::TyTuple(ref tys) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::ty_bare_fn(_, ref f) => {
+        ty::TyBareFn(_, ref f) => {
             Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
         }
-        ty::ty_projection(_) => {
+        ty::TyProjection(_) => {
             None
         }
-        ty::ty_param(_) => {
+        ty::TyParam(_) => {
             if can_simplify_params {
                 Some(ParameterSimplifiedType)
             } else {
                 None
             }
         }
-        ty::ty_infer(_) | ty::ty_err => None,
+        ty::TyInfer(_) | ty::TyError => None,
     }
 }
index 0c8a956f686a215f536d2dba73f7716ab461bf05..e08da94c7314a0b5c364c9181a44f8ecfaef604c 100644 (file)
@@ -14,7 +14,6 @@ use middle::implicator::Implication;
 use middle::ty::{self, FreeRegion};
 use util::common::can_reach;
 use util::nodemap::FnvHashMap;
-use util::ppaux::Repr;
 
 #[derive(Clone)]
 pub struct FreeRegionMap {
@@ -29,11 +28,10 @@ impl FreeRegionMap {
     }
 
     pub fn relate_free_regions_from_implications<'tcx>(&mut self,
-                                                       tcx: &ty::ctxt<'tcx>,
                                                        implications: &[Implication<'tcx>])
     {
         for implication in implications {
-            debug!("implication: {}", implication.repr(tcx));
+            debug!("implication: {:?}", implication);
             match *implication {
                 Implication::RegionSubRegion(_, ty::ReFree(free_a), ty::ReFree(free_b)) => {
                     self.relate_free_regions(free_a, free_b);
@@ -50,7 +48,7 @@ impl FreeRegionMap {
     pub fn relate_free_regions_from_predicates<'tcx>(&mut self,
                                                      tcx: &ty::ctxt<'tcx>,
                                                      predicates: &[ty::Predicate<'tcx>]) {
-        debug!("relate_free_regions_from_predicates(predicates={})", predicates.repr(tcx));
+        debug!("relate_free_regions_from_predicates(predicates={:?})", predicates);
         for predicate in predicates {
             match *predicate {
                 ty::Predicate::Projection(..) |
@@ -68,9 +66,9 @@ impl FreeRegionMap {
                         _ => {
                             // All named regions are instantiated with free regions.
                             tcx.sess.bug(
-                                &format!("record_region_bounds: non free region: {} / {}",
-                                         r_a.repr(tcx),
-                                         r_b.repr(tcx)));
+                                &format!("record_region_bounds: non free region: {:?} / {:?}",
+                                         r_a,
+                                         r_b));
                         }
                     }
                 }
index 86deca0c1449d5eac1773c7fa62979bcf3ab4aa4..bbfa3c9fdfa3f986a0dfa75fba1580384ee6d118 100644 (file)
@@ -13,7 +13,7 @@
 use middle::infer::{InferCtxt, GenericKind};
 use middle::subst::Substs;
 use middle::traits;
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, AsPredicate, Ty};
 use middle::ty_fold::{TypeFoldable, TypeFolder};
 
 use syntax::ast;
@@ -21,10 +21,10 @@ use syntax::codemap::Span;
 
 use util::common::ErrorReported;
 use util::nodemap::FnvHashSet;
-use util::ppaux::Repr;
 
 // Helper functions related to manipulating region types.
 
+#[derive(Debug)]
 pub enum Implication<'tcx> {
     RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
     RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
@@ -53,10 +53,10 @@ pub fn implications<'a,'tcx>(
     span: Span)
     -> Vec<Implication<'tcx>>
 {
-    debug!("implications(body_id={}, ty={}, outer_region={})",
+    debug!("implications(body_id={}, ty={:?}, outer_region={:?})",
            body_id,
-           ty.repr(closure_typer.tcx()),
-           outer_region.repr(closure_typer.tcx()));
+           ty,
+           outer_region);
 
     let mut stack = Vec::new();
     stack.push((outer_region, None));
@@ -68,7 +68,7 @@ pub fn implications<'a,'tcx>(
                               out: Vec::new(),
                               visited: FnvHashSet() };
     wf.accumulate_from_ty(ty);
-    debug!("implications: out={}", wf.out.repr(closure_typer.tcx()));
+    debug!("implications: out={:?}", wf.out);
     wf.out
 }
 
@@ -78,8 +78,8 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
     }
 
     fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
-        debug!("accumulate_from_ty(ty={})",
-               ty.repr(self.tcx()));
+        debug!("accumulate_from_ty(ty={:?})",
+               ty);
 
         // When expanding out associated types, we can visit a cyclic
         // set of types. Issue #23003.
@@ -88,61 +88,62 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
         }
 
         match ty.sty {
-            ty::ty_bool |
-            ty::ty_char |
-            ty::ty_int(..) |
-            ty::ty_uint(..) |
-            ty::ty_float(..) |
-            ty::ty_bare_fn(..) |
-            ty::ty_err |
-            ty::ty_str => {
+            ty::TyBool |
+            ty::TyChar |
+            ty::TyInt(..) |
+            ty::TyUint(..) |
+            ty::TyFloat(..) |
+            ty::TyBareFn(..) |
+            ty::TyError |
+            ty::TyStr => {
                 // No borrowed content reachable here.
             }
 
-            ty::ty_closure(def_id, substs) => {
+            ty::TyClosure(def_id, substs) => {
                 let &(r_a, opt_ty) = self.stack.last().unwrap();
                 self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs));
             }
 
-            ty::ty_trait(ref t) => {
+            ty::TyTrait(ref t) => {
                 let required_region_bounds =
                     object_region_bounds(self.tcx(), &t.principal, t.bounds.builtin_bounds);
                 self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
             }
 
-            ty::ty_enum(def_id, substs) |
-            ty::ty_struct(def_id, substs) => {
+            ty::TyEnum(def_id, substs) |
+            ty::TyStruct(def_id, substs) => {
                 let item_scheme = ty::lookup_item_type(self.tcx(), def_id);
                 self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
             }
 
-            ty::ty_vec(t, _) |
-            ty::ty_ptr(ty::mt { ty: t, .. }) |
-            ty::ty_uniq(t) => {
+            ty::TyArray(t, _) |
+            ty::TySlice(t) |
+            ty::TyRawPtr(ty::mt { ty: t, .. }) |
+            ty::TyBox(t) => {
                 self.accumulate_from_ty(t)
             }
 
-            ty::ty_rptr(r_b, mt) => {
+            ty::TyRef(r_b, mt) => {
                 self.accumulate_from_rptr(ty, *r_b, mt.ty);
             }
 
-            ty::ty_param(p) => {
+            ty::TyParam(p) => {
                 self.push_param_constraint_from_top(p);
             }
 
-            ty::ty_projection(ref data) => {
+            ty::TyProjection(ref data) => {
                 // `<T as TraitRef<..>>::Name`
 
                 self.push_projection_constraint_from_top(data);
             }
 
-            ty::ty_tup(ref tuptys) => {
+            ty::TyTuple(ref tuptys) => {
                 for &tupty in tuptys {
                     self.accumulate_from_ty(tupty);
                 }
             }
 
-            ty::ty_infer(_) => {
+            ty::TyInfer(_) => {
                 // This should not happen, BUT:
                 //
                 //   Currently we uncover region relationships on
@@ -276,7 +277,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
 
         let variances = ty::item_variances(self.tcx(), def_id);
 
-        for (&region, &variance) in substs.regions().iter().zip(variances.regions.iter()) {
+        for (&region, &variance) in substs.regions().iter().zip(&variances.regions) {
             match variance {
                 ty::Contravariant | ty::Invariant => {
                     // If any data with this lifetime is reachable
@@ -287,7 +288,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
             }
         }
 
-        for (&ty, &variance) in substs.types.iter().zip(variances.types.iter()) {
+        for (&ty, &variance) in substs.types.iter().zip(&variances.types) {
             match variance {
                 ty::Covariant | ty::Invariant => {
                     // If any data of this type is reachable within,
@@ -311,8 +312,8 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
     fn accumulate_from_assoc_types_transitive(&mut self,
                                               data: &ty::PolyTraitPredicate<'tcx>)
     {
-        debug!("accumulate_from_assoc_types_transitive({})",
-               data.repr(self.tcx()));
+        debug!("accumulate_from_assoc_types_transitive({:?})",
+               data);
 
         for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
             match ty::no_late_bound_regions(self.tcx(), &poly_trait_ref) {
@@ -325,8 +326,8 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
     fn accumulate_from_assoc_types(&mut self,
                                    trait_ref: ty::TraitRef<'tcx>)
     {
-        debug!("accumulate_from_assoc_types({})",
-               trait_ref.repr(self.tcx()));
+        debug!("accumulate_from_assoc_types({:?})",
+               trait_ref);
 
         let trait_def_id = trait_ref.def_id;
         let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
@@ -335,8 +336,8 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                      .iter()
                      .map(|&name| ty::mk_projection(self.tcx(), trait_ref.clone(), name))
                      .collect();
-        debug!("accumulate_from_assoc_types: assoc_type_projections={}",
-               assoc_type_projections.repr(self.tcx()));
+        debug!("accumulate_from_assoc_types: assoc_type_projections={:?}",
+               assoc_type_projections);
         let tys = match self.fully_normalize(&assoc_type_projections) {
             Ok(tys) => { tys }
             Err(ErrorReported) => { return; }
@@ -399,7 +400,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
     }
 
     fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
-        where T : TypeFoldable<'tcx> + ty::HasProjectionTypes + Clone + Repr<'tcx>
+        where T : TypeFoldable<'tcx> + ty::HasProjectionTypes
     {
         let value =
             traits::fully_normalize(self.infcx,
@@ -443,44 +444,8 @@ pub fn object_region_bounds<'tcx>(
     let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
     let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
 
-    let param_bounds = ty::ParamBounds {
-        region_bounds: Vec::new(),
-        builtin_bounds: others,
-        trait_bounds: trait_refs,
-        projection_bounds: Vec::new(), // not relevant to computing region bounds
-    };
+    let mut predicates = others.to_predicates(tcx, open_ty);
+    predicates.extend(trait_refs.iter().map(|t| t.as_predicate()));
 
-    let predicates = ty::predicates(tcx, open_ty, &param_bounds);
     ty::required_region_bounds(tcx, open_ty, predicates)
 }
-
-impl<'tcx> Repr<'tcx> for Implication<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            Implication::RegionSubRegion(_, ref r_a, ref r_b) => {
-                format!("RegionSubRegion({}, {})",
-                        r_a.repr(tcx),
-                        r_b.repr(tcx))
-            }
-
-            Implication::RegionSubGeneric(_, ref r, ref p) => {
-                format!("RegionSubGeneric({}, {})",
-                        r.repr(tcx),
-                        p.repr(tcx))
-            }
-
-            Implication::RegionSubClosure(_, ref a, ref b, ref c) => {
-                format!("RegionSubClosure({}, {}, {})",
-                        a.repr(tcx),
-                        b.repr(tcx),
-                        c.repr(tcx))
-            }
-
-            Implication::Predicate(ref def_id, ref p) => {
-                format!("Predicate({}, {})",
-                        def_id.repr(tcx),
-                        p.repr(tcx))
-            }
-        }
-    }
-}
index 940dc75271c22f0a33d1585ab2af2a0eee1aede9..b9e1b36d6b5c8521e86026176364a99f7a90683c 100644 (file)
@@ -31,7 +31,6 @@ use super::type_variable::{BiTo};
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
-use util::ppaux::{Repr};
 
 pub struct Bivariate<'a, 'tcx: 'a> {
     fields: CombineFields<'a, 'tcx>
@@ -50,6 +49,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
+    fn will_change(&mut self, _: bool, _: bool) -> bool {
+        // since we are not comparing regions, we don't care
+        false
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                variance: ty::Variance,
                                                a: &T,
@@ -73,25 +77,25 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
     }
 
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+        debug!("{}.tys({:?}, {:?})", self.tag(),
+               a, b);
         if a == b { return Ok(a); }
 
         let infcx = self.fields.infcx;
         let a = infcx.type_variables.borrow().replace_if_possible(a);
         let b = infcx.type_variables.borrow().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
+            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
                 infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id);
                 Ok(a)
             }
 
-            (&ty::ty_infer(TyVar(a_id)), _) => {
+            (&ty::TyInfer(TyVar(a_id)), _) => {
                 try!(self.fields.instantiate(b, BiTo, a_id));
                 Ok(a)
             }
 
-            (_, &ty::ty_infer(TyVar(b_id))) => {
+            (_, &ty::TyInfer(TyVar(b_id))) => {
                 try!(self.fields.instantiate(a, BiTo, b_id));
                 Ok(a)
             }
index 86f12b669b35ebe42f714835d26cb2c5cb7a74dd..a1608f57cd19d650d2dc11a8ad997cd4f5e5731e 100644 (file)
@@ -47,7 +47,6 @@ use middle::ty::{self, Ty};
 use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use middle::ty_relate::{self, Relate, RelateResult, TypeRelation};
-use util::ppaux::Repr;
 
 use syntax::ast;
 use syntax::codemap::Span;
@@ -57,6 +56,7 @@ pub struct CombineFields<'a, 'tcx: 'a> {
     pub infcx: &'a InferCtxt<'a, 'tcx>,
     pub a_is_expected: bool,
     pub trace: TypeTrace<'tcx>,
+    pub cause: Option<ty_relate::Cause>,
 }
 
 pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
@@ -70,44 +70,44 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
 
     match (&a.sty, &b.sty) {
         // Relate integral variables to other types
-        (&ty::ty_infer(ty::IntVar(a_id)), &ty::ty_infer(ty::IntVar(b_id))) => {
+        (&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => {
             try!(infcx.int_unification_table
                       .borrow_mut()
                       .unify_var_var(a_id, b_id)
                       .map_err(|e| int_unification_error(a_is_expected, e)));
             Ok(a)
         }
-        (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_int(v)) => {
+        (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
             unify_integral_variable(infcx, a_is_expected, v_id, IntType(v))
         }
-        (&ty::ty_int(v), &ty::ty_infer(ty::IntVar(v_id))) => {
+        (&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => {
             unify_integral_variable(infcx, !a_is_expected, v_id, IntType(v))
         }
-        (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_uint(v)) => {
+        (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => {
             unify_integral_variable(infcx, a_is_expected, v_id, UintType(v))
         }
-        (&ty::ty_uint(v), &ty::ty_infer(ty::IntVar(v_id))) => {
+        (&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => {
             unify_integral_variable(infcx, !a_is_expected, v_id, UintType(v))
         }
 
         // Relate floating-point variables to other types
-        (&ty::ty_infer(ty::FloatVar(a_id)), &ty::ty_infer(ty::FloatVar(b_id))) => {
+        (&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => {
             try!(infcx.float_unification_table
                       .borrow_mut()
                       .unify_var_var(a_id, b_id)
                       .map_err(|e| float_unification_error(relation.a_is_expected(), e)));
             Ok(a)
         }
-        (&ty::ty_infer(ty::FloatVar(v_id)), &ty::ty_float(v)) => {
+        (&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
             unify_float_variable(infcx, a_is_expected, v_id, v)
         }
-        (&ty::ty_float(v), &ty::ty_infer(ty::FloatVar(v_id))) => {
+        (&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => {
             unify_float_variable(infcx, !a_is_expected, v_id, v)
         }
 
         // All other cases of inference are errors
-        (&ty::ty_infer(_), _) |
-        (_, &ty::ty_infer(_)) => {
+        (&ty::TyInfer(_), _) |
+        (_, &ty::TyInfer(_)) => {
             Err(ty::terr_sorts(ty_relate::expected_found(relation, &a, &b)))
         }
 
@@ -187,7 +187,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
                        b_vid: ty::TyVid)
                        -> RelateResult<'tcx, ()>
     {
-        let tcx = self.infcx.tcx;
         let mut stack = Vec::new();
         stack.push((a_ty, dir, b_vid));
         loop {
@@ -213,10 +212,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
                 Some(e) => e,
             };
 
-            debug!("instantiate(a_ty={} dir={:?} b_vid={})",
-                   a_ty.repr(tcx),
+            debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})",
+                   a_ty,
                    dir,
-                   b_vid.repr(tcx));
+                   b_vid);
 
             // Check whether `vid` has been instantiated yet.  If not,
             // make a generalized form of `ty` and instantiate with
@@ -230,10 +229,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
                         EqTo => self.generalize(a_ty, b_vid, false),
                         BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
                     });
-                    debug!("instantiate(a_ty={}, dir={:?}, \
-                                        b_vid={}, generalized_ty={})",
-                           a_ty.repr(tcx), dir, b_vid.repr(tcx),
-                           generalized_ty.repr(tcx));
+                    debug!("instantiate(a_ty={:?}, dir={:?}, \
+                                        b_vid={:?}, generalized_ty={:?})",
+                           a_ty, dir, b_vid,
+                           generalized_ty);
                     self.infcx.type_variables
                         .borrow_mut()
                         .instantiate_and_push(
@@ -262,7 +261,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
 
     /// Attempts to generalize `ty` for the type variable `for_vid`.  This checks for cycle -- that
     /// is, whether the type `ty` references `for_vid`. If `make_region_vars` is true, it will also
-    /// replace all regions with fresh variables. Returns `ty_err` in the case of a cycle, `Ok`
+    /// replace all regions with fresh variables. Returns `TyError` in the case of a cycle, `Ok`
     /// otherwise.
     fn generalize(&self,
                   ty: Ty<'tcx>,
@@ -308,7 +307,7 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
         // (In particular, you could have something like `$0 = Box<$1>`
         //  where `$1` has already been instantiated with `Box<$0>`)
         match t.sty {
-            ty::ty_infer(ty::TyVar(vid)) => {
+            ty::TyInfer(ty::TyVar(vid)) => {
                 if vid == self.for_vid {
                     self.cycle_detected = true;
                     self.tcx().types.err
@@ -335,8 +334,8 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
             ty::ReEarlyBound(..) => {
                 self.tcx().sess.span_bug(
                     self.span,
-                    &format!("Encountered early bound region when generalizing: {}",
-                            r.repr(self.tcx())));
+                    &format!("Encountered early bound region when generalizing: {:?}",
+                            r));
             }
 
             // Always make a fresh region variable for skolemized regions;
index 2003f459d89b42cb895625da636b8d3e74ecb04f..c0dcda1792be526426dfaabb383f8c43e8b2466c 100644 (file)
@@ -16,7 +16,6 @@ use super::type_variable::{EqTo};
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
-use util::ppaux::{Repr};
 
 pub struct Equate<'a, 'tcx: 'a> {
     fields: CombineFields<'a, 'tcx>
@@ -35,6 +34,11 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
+    fn will_change(&mut self, a: bool, b: bool) -> bool {
+        // if either side changed from what it was, that could cause equality to fail
+        a || b
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                _: ty::Variance,
                                                a: &T,
@@ -45,25 +49,25 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
     }
 
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+        debug!("{}.tys({:?}, {:?})", self.tag(),
+               a, b);
         if a == b { return Ok(a); }
 
         let infcx = self.fields.infcx;
         let a = infcx.type_variables.borrow().replace_if_possible(a);
         let b = infcx.type_variables.borrow().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
+            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
                 infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
                 Ok(a)
             }
 
-            (&ty::ty_infer(TyVar(a_id)), _) => {
+            (&ty::TyInfer(TyVar(a_id)), _) => {
                 try!(self.fields.instantiate(b, EqTo, a_id));
                 Ok(a)
             }
 
-            (_, &ty::ty_infer(TyVar(b_id))) => {
+            (_, &ty::TyInfer(TyVar(b_id))) => {
                 try!(self.fields.instantiate(a, EqTo, b_id));
                 Ok(a)
             }
@@ -75,10 +79,10 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
     }
 
     fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
+        debug!("{}.regions({:?}, {:?})",
                self.tag(),
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
+               a,
+               b);
         let origin = Subtype(self.fields.trace.clone());
         self.fields.infcx.region_vars.make_eqregion(origin, a, b);
         Ok(a)
index 8aca64484bf4506d43b9d4bbcff305477fbe7edf..7602f0b83764f53b35493be0c61c2ca7a94b3170 100644 (file)
@@ -72,28 +72,144 @@ use super::region_inference::ProcessedErrors;
 use super::region_inference::SameRegions;
 
 use std::collections::HashSet;
+use ast_map;
 use middle::def;
 use middle::infer;
+use middle::region;
 use middle::subst;
 use middle::ty::{self, Ty};
 use middle::ty::{Region, ReFree};
+
 use std::cell::{Cell, RefCell};
 use std::char::from_u32;
-use std::string::String;
+use std::fmt;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util::name_to_dummy_lifetime;
 use syntax::owned_slice::OwnedSlice;
-use syntax::codemap;
+use syntax::codemap::{Pos, Span};
 use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use util::ppaux::bound_region_to_string;
-use util::ppaux::note_and_explain_region;
 
-// Note: only import UserString, not Repr, since user-facing error
-// messages shouldn't include debug serializations.
-use util::ppaux::UserString;
+pub fn note_and_explain_region(tcx: &ty::ctxt,
+                               prefix: &str,
+                               region: ty::Region,
+                               suffix: &str) {
+    fn item_scope_tag(item: &ast::Item) -> &'static str {
+        match item.node {
+            ast::ItemImpl(..) => "impl",
+            ast::ItemStruct(..) => "struct",
+            ast::ItemEnum(..) => "enum",
+            ast::ItemTrait(..) => "trait",
+            ast::ItemFn(..) => "function body",
+            _ => "item"
+        }
+    }
+
+    fn explain_span(tcx: &ty::ctxt, heading: &str, span: Span)
+                    -> (String, Option<Span>) {
+        let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
+        (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
+         Some(span))
+    }
+
+    let (description, span) = match region {
+        ty::ReScope(scope) => {
+            let new_string;
+            let unknown_scope = || {
+                format!("{}unknown scope: {:?}{}.  Please report a bug.",
+                        prefix, scope, suffix)
+            };
+            let span = match scope.span(&tcx.map) {
+                Some(s) => s,
+                None => return tcx.sess.note(&unknown_scope())
+            };
+            let tag = match tcx.map.find(scope.node_id()) {
+                Some(ast_map::NodeBlock(_)) => "block",
+                Some(ast_map::NodeExpr(expr)) => match expr.node {
+                    ast::ExprCall(..) => "call",
+                    ast::ExprMethodCall(..) => "method call",
+                    ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
+                    ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) =>  "while let",
+                    ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) =>  "for",
+                    ast::ExprMatch(..) => "match",
+                    _ => "expression",
+                },
+                Some(ast_map::NodeStmt(_)) => "statement",
+                Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
+                Some(_) | None => {
+                    return tcx.sess.span_note(span, &unknown_scope());
+                }
+            };
+            let scope_decorated_tag = match scope {
+                region::CodeExtent::Misc(_) => tag,
+                region::CodeExtent::ParameterScope { .. } => {
+                    "scope of parameters for function"
+                }
+                region::CodeExtent::DestructionScope(_) => {
+                    new_string = format!("destruction scope surrounding {}", tag);
+                    &new_string[..]
+                }
+                region::CodeExtent::Remainder(r) => {
+                    new_string = format!("block suffix following statement {}",
+                                         r.first_statement_index);
+                    &new_string[..]
+                }
+            };
+            explain_span(tcx, scope_decorated_tag, span)
+        }
+
+        ty::ReFree(ref fr) => {
+            let prefix = match fr.bound_region {
+                ty::BrAnon(idx) => {
+                    format!("the anonymous lifetime #{} defined on", idx + 1)
+                }
+                ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
+                _ => {
+                    format!("the lifetime {} as defined on",
+                            fr.bound_region)
+                }
+            };
+
+            match tcx.map.find(fr.scope.node_id) {
+                Some(ast_map::NodeBlock(ref blk)) => {
+                    let (msg, opt_span) = explain_span(tcx, "block", blk.span);
+                    (format!("{} {}", prefix, msg), opt_span)
+                }
+                Some(ast_map::NodeItem(it)) => {
+                    let tag = item_scope_tag(&*it);
+                    let (msg, opt_span) = explain_span(tcx, tag, it.span);
+                    (format!("{} {}", prefix, msg), opt_span)
+                }
+                Some(_) | None => {
+                    // this really should not happen
+                    (format!("{} unknown free region bounded by scope {:?}",
+                             prefix, fr.scope), None)
+                }
+            }
+        }
+
+        ty::ReStatic => ("the static lifetime".to_owned(), None),
+
+        ty::ReEmpty => ("the empty lifetime".to_owned(), None),
+
+        ty::ReEarlyBound(ref data) => {
+            (format!("{}", token::get_name(data.name)), None)
+        }
+
+        // I believe these cases should not occur (except when debugging,
+        // perhaps)
+        ty::ReInfer(_) | ty::ReLateBound(..) => {
+            (format!("lifetime {:?}", region), None)
+        }
+    };
+    let message = format!("{}{}{}", prefix, description, suffix);
+    if let Some(span) = span {
+        tcx.sess.span_note(span, &message);
+    } else {
+        tcx.sess.note(&message);
+    }
+}
 
 pub trait ErrorReporting<'tcx> {
     fn report_region_errors(&self,
@@ -110,7 +226,7 @@ pub trait ErrorReporting<'tcx> {
 
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
 
-    fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + Resolvable<'tcx>>(
         &self,
         exp_found: &ty::expected_found<T>)
         -> Option<String>;
@@ -158,10 +274,11 @@ trait ErrorReportingHelpers<'tcx> {
     fn give_expl_lifetime_param(&self,
                                 decl: &ast::FnDecl,
                                 unsafety: ast::Unsafety,
+                                constness: ast::Constness,
                                 ident: ast::Ident,
                                 opt_explicit_self: Option<&ast::ExplicitSelf_>,
                                 generics: &ast::Generics,
-                                span: codemap::Span);
+                                span: Span);
 }
 
 impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
@@ -360,7 +477,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             "{}: {} ({})",
                  trace.origin,
                  expected_found_str,
-                 ty::type_err_to_str(self.tcx, terr));
+                 terr);
 
         match trace.origin {
             infer::MatchExpressionArm(_, arm_span) =>
@@ -387,7 +504,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         }
     }
 
-    fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + Resolvable<'tcx>>(
         &self,
         exp_found: &ty::expected_found<T>)
         -> Option<String>
@@ -403,8 +520,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         Some(format!("expected `{}`, found `{}`",
-                     expected.user_string(self.tcx),
-                     found.user_string(self.tcx)))
+                     expected,
+                     found))
     }
 
     fn report_generic_bound_failure(&self,
@@ -420,9 +537,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) =>
-                format!("the parameter type `{}`", p.user_string(self.tcx)),
+                format!("the parameter type `{}`", p),
             GenericKind::Projection(ref p) =>
-                format!("the associated type `{}`", p.user_string(self.tcx)),
+                format!("the associated type `{}`", p),
         };
 
         match sub {
@@ -434,8 +551,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     origin.span(),
                     &format!(
                         "consider adding an explicit lifetime bound `{}: {}`...",
-                        bound_kind.user_string(self.tcx),
-                        sub.user_string(self.tcx)));
+                        bound_kind,
+                        sub));
             }
 
             ty::ReStatic => {
@@ -446,7 +563,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     origin.span(),
                     &format!(
                         "consider adding an explicit lifetime bound `{}: 'static`...",
-                        bound_kind.user_string(self.tcx)));
+                        bound_kind));
             }
 
             _ => {
@@ -458,7 +575,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     origin.span(),
                     &format!(
                         "consider adding an explicit lifetime bound for `{}`",
-                        bound_kind.user_string(self.tcx)));
+                        bound_kind));
                 note_and_explain_region(
                     self.tcx,
                     &format!("{} must be valid for ", labeled_user_string),
@@ -475,7 +592,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                sub: Region,
                                sup: Region) {
         match origin {
-            infer::Subtype(trace) => {
+            infer::Subtype(trace) |
+            infer::DefaultExistentialBound(trace) => {
                 let terr = ty::terr_regions_does_not_outlive(sup, sub);
                 self.report_and_explain_type_error(trace, &terr);
             }
@@ -826,8 +944,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => {
-                            Some((fn_decl, gen, pur, item.ident, None, item.span))
+                        ast::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
+                            Some((fn_decl, gen, unsafety, constness,
+                                  item.ident, None, item.span))
                         },
                         _ => None
                     }
@@ -838,6 +957,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
+                                  sig.constness,
                                   item.ident,
                                   Some(&sig.explicit_self.node),
                                   item.span))
@@ -852,6 +972,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
+                                  sig.constness,
                                   item.ident,
                                   Some(&sig.explicit_self.node),
                                   item.span))
@@ -863,12 +984,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             },
             None => None
         };
-        let (fn_decl, generics, unsafety, ident, expl_self, span)
+        let (fn_decl, generics, unsafety, constness, ident, 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, ident,
+        self.give_expl_lifetime_param(&fn_decl, unsafety, constness, ident,
                                       expl_self.as_ref(), &generics, span);
     }
 }
@@ -1423,12 +1544,13 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
     fn give_expl_lifetime_param(&self,
                                 decl: &ast::FnDecl,
                                 unsafety: ast::Unsafety,
+                                constness: ast::Constness,
                                 ident: ast::Ident,
                                 opt_explicit_self: Option<&ast::ExplicitSelf_>,
                                 generics: &ast::Generics,
-                                span: codemap::Span) {
-        let suggested_fn = pprust::fun_to_string(decl, unsafety, ident,
-                                              opt_explicit_self, generics);
+                                span: Span) {
+        let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, ident,
+                                                 opt_explicit_self, generics);
         let msg = format!("consider using an explicit lifetime \
                            parameter as shown: {}", suggested_fn);
         self.tcx.sess.span_help(span, &msg[..]);
@@ -1436,6 +1558,13 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
 
     fn report_inference_failure(&self,
                                 var_origin: RegionVariableOrigin) {
+        let br_string = |br: ty::BoundRegion| {
+            let mut s = br.to_string();
+            if !s.is_empty() {
+                s.push_str(" ");
+            }
+            s
+        };
         let var_description = match var_origin {
             infer::MiscVariable(_) => "".to_string(),
             infer::PatternRegion(_) => " for pattern".to_string(),
@@ -1443,17 +1572,15 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
             infer::Autoref(_) => " for autoref".to_string(),
             infer::Coercion(_) => " for automatic coercion".to_string(),
             infer::LateBoundRegion(_, br, infer::FnCall) => {
-                format!(" for {}in function call",
-                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
+                format!(" for lifetime parameter {}in function call",
+                        br_string(br))
             }
             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
-                format!(" for {}in generic type",
-                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
+                format!(" for lifetime parameter {}in generic type", br_string(br))
             }
             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
-                format!(" for {}in trait containing associated type `{}`",
-                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br),
-                        token::get_name(type_name))
+                format!(" for lifetime parameter {}in trait containing associated type `{}`",
+                        br_string(br), token::get_name(type_name))
             }
             infer::EarlyBoundRegion(_, name) => {
                 format!(" for lifetime parameter `{}`",
@@ -1478,7 +1605,8 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
 
     fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
         match *origin {
-            infer::Subtype(ref trace) => {
+            infer::Subtype(ref trace) |
+            infer::DefaultExistentialBound(ref trace) => {
                 let desc = match trace.origin {
                     infer::Misc(_) => {
                         "types are compatible"
@@ -1710,7 +1838,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
     let method_id_opt = match tcx.map.find(parent) {
         Some(node) => match node {
             ast_map::NodeItem(item) => match item.node {
-                ast::ItemFn(_, _, _, ref gen, _) => {
+                ast::ItemFn(_, _, _, _, ref gen, _) => {
                     taken.push_all(&gen.lifetimes);
                     None
                 },
@@ -1778,7 +1906,7 @@ impl LifeGiver {
     fn give_lifetime(&self) -> ast::Lifetime {
         let mut lifetime;
         loop {
-            let mut s = String::from_str("'");
+            let mut s = String::from("'");
             s.push_str(&num_to_string(self.counter.get()));
             if !self.taken.contains(&s) {
                 lifetime = name_to_dummy_lifetime(
index 111cf68726c61b61d47ee21222dda8ab0adab60e..1aa54863c203af515971f76ee82b2a8366c4fcec 100644 (file)
@@ -104,17 +104,21 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty::type_needs_infer(t) && !ty::type_has_erasable_regions(t) {
+            return t;
+        }
+
         let tcx = self.infcx.tcx;
 
         match t.sty {
-            ty::ty_infer(ty::TyVar(v)) => {
+            ty::TyInfer(ty::TyVar(v)) => {
                 self.freshen(
                     self.infcx.type_variables.borrow().probe(v),
                     ty::TyVar(v),
                     ty::FreshTy)
             }
 
-            ty::ty_infer(ty::IntVar(v)) => {
+            ty::TyInfer(ty::IntVar(v)) => {
                 self.freshen(
                     self.infcx.int_unification_table.borrow_mut()
                                                     .probe(v)
@@ -123,7 +127,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
                     ty::FreshIntTy)
             }
 
-            ty::ty_infer(ty::FloatVar(v)) => {
+            ty::TyInfer(ty::FloatVar(v)) => {
                 self.freshen(
                     self.infcx.float_unification_table.borrow_mut()
                                                       .probe(v)
@@ -132,9 +136,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
                     ty::FreshFloatTy)
             }
 
-            ty::ty_infer(ty::FreshTy(c)) |
-            ty::ty_infer(ty::FreshIntTy(c)) |
-            ty::ty_infer(ty::FreshFloatTy(c)) => {
+            ty::TyInfer(ty::FreshTy(c)) |
+            ty::TyInfer(ty::FreshIntTy(c)) |
+            ty::TyInfer(ty::FreshFloatTy(c)) => {
                 if c >= self.freshen_count {
                     tcx.sess.bug(
                         &format!("Encountered a freshend type with id {} \
@@ -145,25 +149,26 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
                 t
             }
 
-            ty::ty_bool |
-            ty::ty_char |
-            ty::ty_int(..) |
-            ty::ty_uint(..) |
-            ty::ty_float(..) |
-            ty::ty_enum(..) |
-            ty::ty_uniq(..) |
-            ty::ty_str |
-            ty::ty_err |
-            ty::ty_vec(..) |
-            ty::ty_ptr(..) |
-            ty::ty_rptr(..) |
-            ty::ty_bare_fn(..) |
-            ty::ty_trait(..) |
-            ty::ty_struct(..) |
-            ty::ty_closure(..) |
-            ty::ty_tup(..) |
-            ty::ty_projection(..) |
-            ty::ty_param(..) => {
+            ty::TyBool |
+            ty::TyChar |
+            ty::TyInt(..) |
+            ty::TyUint(..) |
+            ty::TyFloat(..) |
+            ty::TyEnum(..) |
+            ty::TyBox(..) |
+            ty::TyStr |
+            ty::TyError |
+            ty::TyArray(..) |
+            ty::TySlice(..) |
+            ty::TyRawPtr(..) |
+            ty::TyRef(..) |
+            ty::TyBareFn(..) |
+            ty::TyTrait(..) |
+            ty::TyStruct(..) |
+            ty::TyClosure(..) |
+            ty::TyTuple(..) |
+            ty::TyProjection(..) |
+            ty::TyParam(..) => {
                 ty_fold::super_fold_ty(self, t)
             }
         }
index 5822fb0f2d432fba8d7c3fe10959268c158d3fc4..adfd1a8a7d7945abf088ad564ae2d0836be68604 100644 (file)
@@ -16,7 +16,6 @@ use super::Subtype;
 
 use middle::ty::{self, Ty};
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
-use util::ppaux::Repr;
 
 /// "Greatest lower bound" (common subtype)
 pub struct Glb<'a, 'tcx: 'a> {
@@ -36,6 +35,16 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
+    fn will_change(&mut self, a: bool, b: bool) -> bool {
+        // Hmm, so the result of GLB will still be a LB if one or both
+        // sides change to 'static, but it may no longer be the GLB.
+        // I'm going to go with `a || b` here to be conservative,
+        // since the result of this operation may be affected, though
+        // I think it would mostly be more accepting than before (since the result
+        // would be a bigger region).
+        a || b
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                variance: ty::Variance,
                                                a: &T,
@@ -55,10 +64,10 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
     }
 
     fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
+        debug!("{}.regions({:?}, {:?})",
                self.tag(),
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
+               a,
+               b);
 
         let origin = Subtype(self.fields.trace.clone());
         Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b))
index b0940aa7ec0ac823afccc51d440547dacd80c898..7b26f6b153733a7f13e8125ead80914a9a48c08c 100644 (file)
@@ -20,7 +20,6 @@ use middle::ty_fold::{self, TypeFoldable};
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use syntax::codemap::Span;
 use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux::Repr;
 
 pub trait HigherRankedRelations<'a,'tcx> {
     fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
@@ -46,10 +45,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                             -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'a,'tcx>
     {
-        let tcx = self.infcx.tcx;
-
-        debug!("higher_ranked_sub(a={}, b={})",
-               a.repr(tcx), b.repr(tcx));
+        debug!("higher_ranked_sub(a={:?}, b={:?})",
+               a, b);
 
         // Rather than checking the subtype relationship between `a` and `b`
         // as-is, we need to do some extra work here in order to make sure
@@ -75,8 +72,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
             let (b_prime, skol_map) =
                 self.infcx.skolemize_late_bound_regions(b, snapshot);
 
-            debug!("a_prime={}", a_prime.repr(tcx));
-            debug!("b_prime={}", b_prime.repr(tcx));
+            debug!("a_prime={:?}", a_prime);
+            debug!("b_prime={:?}", b_prime);
 
             // Compare types now that bound regions have been replaced.
             let result = try!(self.sub().relate(&a_prime, &b_prime));
@@ -98,8 +95,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                 }
             }
 
-            debug!("higher_ranked_sub: OK result={}",
-                   result.repr(tcx));
+            debug!("higher_ranked_sub: OK result={:?}",
+                   result);
 
             Ok(ty::Binder(result))
         });
@@ -125,7 +122,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                 try!(self.lub().relate(&a_with_fresh, &b_with_fresh));
             let result0 =
                 self.infcx.resolve_type_vars_if_possible(&result0);
-            debug!("lub result0 = {}", result0.repr(self.tcx()));
+            debug!("lub result0 = {:?}", result0);
 
             // Generalize the regions appearing in result0 if possible
             let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
@@ -137,10 +134,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                     |r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
                                                     &new_vars, &a_map, r));
 
-            debug!("lub({},{}) = {}",
-                   a.repr(self.tcx()),
-                   b.repr(self.tcx()),
-                   result1.repr(self.tcx()));
+            debug!("lub({:?},{:?}) = {:?}",
+                   a,
+                   b,
+                   result1);
 
             Ok(ty::Binder(result1))
         });
@@ -198,8 +195,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
     fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'a,'tcx>
     {
-        debug!("higher_ranked_glb({}, {})",
-               a.repr(self.tcx()), b.repr(self.tcx()));
+        debug!("higher_ranked_glb({:?}, {:?})",
+               a, b);
 
         // Make a snapshot so we can examine "all bindings that were
         // created as part of this type comparison".
@@ -219,7 +216,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                 try!(self.glb().relate(&a_with_fresh, &b_with_fresh));
             let result0 =
                 self.infcx.resolve_type_vars_if_possible(&result0);
-            debug!("glb result0 = {}", result0.repr(self.tcx()));
+            debug!("glb result0 = {:?}", result0);
 
             // Generalize the regions appearing in result0 if possible
             let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
@@ -233,10 +230,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                                                     &a_map, &a_vars, &b_vars,
                                                     r));
 
-            debug!("glb({},{}) = {}",
-                   a.repr(self.tcx()),
-                   b.repr(self.tcx()),
-                   result1.repr(self.tcx()));
+            debug!("glb({:?},{:?}) = {:?}",
+                   a,
+                   b,
+                   result1);
 
             Ok(ty::Binder(result1))
         });
@@ -443,7 +440,7 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
         let escaping_region_vars: FnvHashSet<_> =
             escaping_types
             .iter()
-            .flat_map(|&t| ty_fold::collect_regions(self.tcx, &t).into_iter())
+            .flat_map(|&t| ty_fold::collect_regions(self.tcx, &t))
             .collect();
 
         region_vars.retain(|&region_vid| {
@@ -451,9 +448,9 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
             !escaping_region_vars.contains(&r)
         });
 
-        debug!("region_vars_confined_to_snapshot: region_vars={} escaping_types={}",
-               region_vars.repr(self.tcx),
-               escaping_types.repr(self.tcx));
+        debug!("region_vars_confined_to_snapshot: region_vars={:?} escaping_types={:?}",
+               region_vars,
+               escaping_types);
 
         region_vars
     }
@@ -520,7 +517,7 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                binder: &ty::Binder<T>,
                                                snapshot: &CombinedSnapshot)
                                                -> (T, SkolemizationMap)
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
     /*!
      * Replace all regions bound by `binder` with skolemized regions and
@@ -530,14 +527,14 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
      * details.
      */
 
-    let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br| {
+    let (result, map) = ty_fold::replace_late_bound_regions(infcx.tcx, binder, |br| {
         infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
     });
 
-    debug!("skolemize_bound_regions(binder={}, result={}, map={})",
-           binder.repr(infcx.tcx),
-           result.repr(infcx.tcx),
-           map.repr(infcx.tcx));
+    debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
+           binder,
+           result,
+           map);
 
     (result, map)
 }
@@ -555,8 +552,8 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
      * hold. See `README.md` for more details.
      */
 
-    debug!("leak_check: skol_map={}",
-           skol_map.repr(infcx.tcx));
+    debug!("leak_check: skol_map={:?}",
+           skol_map);
 
     let new_vars = infcx.region_vars_confined_to_snapshot(snapshot);
     for (&skol_br, &skol) in skol_map {
@@ -573,10 +570,10 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                 }
             };
 
-            debug!("{} (which replaced {}) is tainted by {}",
-                   skol.repr(infcx.tcx),
-                   skol_br.repr(infcx.tcx),
-                   tainted_region.repr(infcx.tcx));
+            debug!("{:?} (which replaced {:?}) is tainted by {:?}",
+                   skol,
+                   skol_br,
+                   tainted_region);
 
             // A is not as polymorphic as B:
             return Err((skol_br, tainted_region));
@@ -618,13 +615,13 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                              snapshot: &CombinedSnapshot,
                              value: &T)
                              -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
     debug_assert!(leak_check(infcx, &skol_map, snapshot).is_ok());
 
-    debug!("plug_leaks(skol_map={}, value={})",
-           skol_map.repr(infcx.tcx),
-           value.repr(infcx.tcx));
+    debug!("plug_leaks(skol_map={:?}, value={:?})",
+           skol_map,
+           value);
 
     // Compute a mapping from the "taint set" of each skolemized
     // region back to the `ty::BoundRegion` that it originally
@@ -640,8 +637,8 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
         })
         .collect();
 
-    debug!("plug_leaks: inv_skol_map={}",
-           inv_skol_map.repr(infcx.tcx));
+    debug!("plug_leaks: inv_skol_map={:?}",
+           inv_skol_map);
 
     // Remove any instantiated type variables from `value`; those can hide
     // references to regions from the `fold_regions` code below.
@@ -669,8 +666,8 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
         }
     });
 
-    debug!("plug_leaks: result={}",
-           result.repr(infcx.tcx));
+    debug!("plug_leaks: result={:?}",
+           result);
 
     result
 }
index 57001083b03e200e410d7fa0e9de3a76854a09a4..7b34fda24064ef7fff78846eae32b6dc220b7230 100644 (file)
@@ -35,7 +35,6 @@ use super::InferCtxt;
 use middle::ty::TyVar;
 use middle::ty::{self, Ty};
 use middle::ty_relate::{RelateResult, TypeRelation};
-use util::ppaux::Repr;
 
 pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
     fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
@@ -51,10 +50,10 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
                                                         -> RelateResult<'tcx, Ty<'tcx>>
     where 'tcx: 'a
 {
-    debug!("{}.lattice_tys({}, {})",
+    debug!("{}.lattice_tys({:?}, {:?})",
            this.tag(),
-           a.repr(this.tcx()),
-           b.repr(this.tcx()));
+           a,
+           b);
 
     if a == b {
         return Ok(a);
@@ -64,15 +63,15 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
     let a = infcx.type_variables.borrow().replace_if_possible(a);
     let b = infcx.type_variables.borrow().replace_if_possible(b);
     match (&a.sty, &b.sty) {
-        (&ty::ty_infer(TyVar(..)), &ty::ty_infer(TyVar(..)))
+        (&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..)))
             if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
             let v = infcx.next_diverging_ty_var();
             try!(this.relate_bound(v, a, b));
             Ok(v)
         }
 
-        (&ty::ty_infer(TyVar(..)), _) |
-        (_, &ty::ty_infer(TyVar(..))) => {
+        (&ty::TyInfer(TyVar(..)), _) |
+        (_, &ty::TyInfer(TyVar(..))) => {
             let v = infcx.next_ty_var();
             try!(this.relate_bound(v, a, b));
             Ok(v)
index f456687be13ac49567537768bfdc0c72f4a4a6a5..f10d4adc8e5f2df62032133480d7b3aac5642fbf 100644 (file)
@@ -16,7 +16,6 @@ use super::Subtype;
 
 use middle::ty::{self, Ty};
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
-use util::ppaux::Repr;
 
 /// "Least upper bound" (common supertype)
 pub struct Lub<'a, 'tcx: 'a> {
@@ -36,6 +35,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
+    fn will_change(&mut self, a: bool, b: bool) -> bool {
+        // result will be 'static if a || b
+        a || b
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                variance: ty::Variance,
                                                a: &T,
@@ -55,10 +59,10 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
     }
 
     fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
+        debug!("{}.regions({:?}, {:?})",
                self.tag(),
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
+               a,
+               b);
 
         let origin = Subtype(self.fields.trace.clone());
         Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b))
index b802f46e28594184eeb8c51853e5d880902dead1..bcd329544a463f4e0cc440f65b0434d9e7d8c291 100644 (file)
@@ -26,9 +26,8 @@ use middle::free_region::FreeRegionMap;
 use middle::subst;
 use middle::subst::Substs;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
-use middle::ty::replace_late_bound_regions;
 use middle::ty::{self, Ty};
-use middle::ty_fold::{TypeFolder, TypeFoldable};
+use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use rustc_data_structures::unify::{self, UnificationTable};
 use std::cell::{RefCell};
@@ -37,8 +36,6 @@ use syntax::ast;
 use syntax::codemap;
 use syntax::codemap::Span;
 use util::nodemap::FnvHashMap;
-use util::ppaux::ty_to_string;
-use util::ppaux::{Repr, UserString};
 
 use self::combine::CombineFields;
 use self::region_inference::{RegionVarBindings, RegionSnapshot};
@@ -162,7 +159,7 @@ pub enum ValuePairs<'tcx> {
 /// encounter an error or subtyping constraint.
 ///
 /// See `error_reporting.rs` for more details.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct TypeTrace<'tcx> {
     origin: TypeOrigin,
     values: ValuePairs<'tcx>,
@@ -176,6 +173,9 @@ pub enum SubregionOrigin<'tcx> {
     // Arose from a subtyping relation
     Subtype(TypeTrace<'tcx>),
 
+    // Arose from a subtyping relation
+    DefaultExistentialBound(TypeTrace<'tcx>),
+
     // Stack-allocated closures cannot outlive innermost loop
     // or function so as to ensure we only require finite stack
     InfStackClosure(Span),
@@ -332,8 +332,8 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                                   b: Ty<'tcx>)
                                   -> Ty<'tcx>
 {
-    debug!("common_supertype({}, {})",
-           a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("common_supertype({:?}, {:?})",
+           a, b);
 
     let trace = TypeTrace {
         origin: origin,
@@ -357,7 +357,7 @@ pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                           b: Ty<'tcx>)
                           -> UnitResult<'tcx>
 {
-    debug!("mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("mk_subty({:?} <: {:?})", a, b);
     cx.sub_types(a_is_expected, origin, a, b)
 }
 
@@ -365,7 +365,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                               a: Ty<'tcx>,
                               b: Ty<'tcx>)
                               -> UnitResult<'tcx> {
-    debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("can_mk_subty({:?} <: {:?})", a, b);
     cx.probe(|_| {
         let trace = TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
@@ -385,7 +385,7 @@ pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                          origin: SubregionOrigin<'tcx>,
                          a: ty::Region,
                          b: ty::Region) {
-    debug!("mk_subr({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("mk_subr({:?} <: {:?})", a, b);
     let snapshot = cx.region_vars.start_snapshot();
     cx.region_vars.make_subregion(origin, a, b);
     cx.region_vars.commit(snapshot);
@@ -398,7 +398,7 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                          b: Ty<'tcx>)
                          -> UnitResult<'tcx>
 {
-    debug!("mk_eqty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("mk_eqty({:?} <: {:?})", a, b);
     cx.commit_if_ok(|_| cx.eq_types(a_is_expected, origin, a, b))
 }
 
@@ -409,8 +409,8 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                                    b: ty::PolyTraitRef<'tcx>)
                                    -> UnitResult<'tcx>
 {
-    debug!("mk_sub_trait_refs({} <: {})",
-           a.repr(cx.tcx), b.repr(cx.tcx));
+    debug!("mk_sub_trait_refs({:?} <: {:?})",
+           a, b);
     cx.commit_if_ok(|_| cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone()))
 }
 
@@ -441,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     pub fn type_var_diverges(&'a self, ty: Ty) -> bool {
         match ty.sty {
-            ty::ty_infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
+            ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
             _ => false
         }
     }
@@ -453,14 +453,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
         use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat};
         match ty.sty {
-            ty::ty_infer(ty::IntVar(vid)) => {
+            ty::TyInfer(ty::IntVar(vid)) => {
                 if self.int_unification_table.borrow_mut().has_value(vid) {
                     Neither
                 } else {
                     UnconstrainedInt
                 }
             },
-            ty::ty_infer(ty::FloatVar(vid)) => {
+            ty::TyInfer(ty::FloatVar(vid)) => {
                 if self.float_unification_table.borrow_mut().has_value(vid) {
                     Neither
                 } else {
@@ -475,7 +475,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                       -> CombineFields<'a, 'tcx> {
         CombineFields {infcx: self,
                        a_is_expected: a_is_expected,
-                       trace: trace}
+                       trace: trace,
+                       cause: None}
     }
 
     // public so that it can be used from the rustc_driver unit tests
@@ -639,7 +640,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                      b: Ty<'tcx>)
                      -> UnitResult<'tcx>
     {
-        debug!("sub_types({} <: {})", a.repr(self.tcx), b.repr(self.tcx));
+        debug!("sub_types({:?} <: {:?})", a, b);
         self.commit_if_ok(|_| {
             let trace = TypeTrace::types(origin, a_is_expected, a, b);
             self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ())
@@ -666,9 +667,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                           b: ty::TraitRef<'tcx>)
                           -> UnitResult<'tcx>
     {
-        debug!("sub_trait_refs({} <: {})",
-               a.repr(self.tcx),
-               b.repr(self.tcx));
+        debug!("sub_trait_refs({:?} <: {:?})",
+               a,
+               b);
         self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
@@ -685,9 +686,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                b: ty::PolyTraitRef<'tcx>)
                                -> UnitResult<'tcx>
     {
-        debug!("sub_poly_trait_refs({} <: {})",
-               a.repr(self.tcx),
-               b.repr(self.tcx));
+        debug!("sub_poly_trait_refs({:?} <: {:?})",
+               a,
+               b);
         self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
@@ -710,7 +711,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                            value: &ty::Binder<T>,
                                            snapshot: &CombinedSnapshot)
                                            -> (T, SkolemizationMap)
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         /*! See `higher_ranked::skolemize_late_bound_regions` */
 
@@ -735,7 +736,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                          snapshot: &CombinedSnapshot,
                          value: &T)
                          -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         /*! See `higher_ranked::plug_leaks` */
 
@@ -863,8 +864,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
-        ty_to_string(self.tcx,
-                     self.resolve_type_vars_if_possible(&t))
+        self.resolve_type_vars_if_possible(&t).to_string()
     }
 
     pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String {
@@ -873,13 +873,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
-        let t = self.resolve_type_vars_if_possible(t);
-        t.user_string(self.tcx)
+        self.resolve_type_vars_if_possible(t).to_string()
     }
 
     pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         match typ.sty {
-            ty::ty_infer(ty::TyVar(v)) => {
+            ty::TyInfer(ty::TyVar(v)) => {
                 // Not entirely obvious: if `typ` is a type variable,
                 // it can be resolved to an int/float variable, which
                 // can then be recursively resolved, hence the
@@ -895,7 +894,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     .unwrap_or(typ)
             }
 
-            ty::ty_infer(ty::IntVar(v)) => {
+            ty::TyInfer(ty::IntVar(v)) => {
                 self.int_unification_table
                     .borrow_mut()
                     .probe(v)
@@ -903,7 +902,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     .unwrap_or(typ)
             }
 
-            ty::ty_infer(ty::FloatVar(v)) => {
+            ty::TyInfer(ty::FloatVar(v)) => {
                 self.float_unification_table
                     .borrow_mut()
                     .probe(v)
@@ -946,13 +945,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     // [Note-Type-error-reporting]
-    // An invariant is that anytime the expected or actual type is ty_err (the special
+    // An invariant is that anytime the expected or actual type is TyError (the special
     // error type, meaning that an error occurred when typechecking this expression),
     // this is a derived error. The error cascaded from another error (that was already
     // reported), so it's not useful to display it to the user.
     // The following four methods -- type_error_message_str, type_error_message_str_with_expected,
     // type_error_message, and report_mismatched_types -- implement this logic.
-    // They check if either the actual or expected type is ty_err, and don't print the error
+    // They check if either the actual or expected type is TyError, and don't print the error
     // in this case. The typechecker should only ever report type errors involving mismatched
     // types using one of these four methods, and should not call span_err directly for such
     // errors.
@@ -982,7 +981,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             Some(t) if ty::type_is_error(t) => (),
             _ => {
                 let error_str = err.map_or("".to_string(), |t_err| {
-                    format!(" ({})", ty::type_err_to_str(self.tcx, t_err))
+                    format!(" ({})", t_err)
                 });
 
                 self.tcx.sess.span_err(sp, &format!("{}{}",
@@ -1005,7 +1004,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
 
-        // Don't report an error if actual type is ty_err.
+        // Don't report an error if actual type is TyError.
         if ty::type_is_error(actual_ty) {
             return;
         }
@@ -1036,9 +1035,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         lbrct: LateBoundRegionConversionTime,
         value: &ty::Binder<T>)
         -> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
-        ty::replace_late_bound_regions(
+        ty_fold::replace_late_bound_regions(
             self.tcx,
             value,
             |br| self.next_region_var(LateBoundRegion(span, br, lbrct)))
@@ -1050,18 +1049,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                 kind: GenericKind<'tcx>,
                                 a: ty::Region,
                                 bs: Vec<ty::Region>) {
-        debug!("verify_generic_bound({}, {} <: {})",
-               kind.repr(self.tcx),
-               a.repr(self.tcx),
-               bs.repr(self.tcx));
+        debug!("verify_generic_bound({:?}, {:?} <: {:?})",
+               kind,
+               a,
+               bs);
 
         self.region_vars.verify_generic_bound(origin, kind, a, bs);
     }
 
     pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx>
-        where T: Relate<'b,'tcx> + Repr<'tcx>
+        where T: Relate<'b,'tcx> + fmt::Debug
     {
-        debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx));
+        debug!("can_equate({:?}, {:?})", a, b);
         self.probe(|_| {
             // Gin up a dummy trace, since this won't be committed
             // anyhow. We should make this typetrace stuff more
@@ -1102,9 +1101,9 @@ impl<'tcx> TypeTrace<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for TypeTrace<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        format!("TypeTrace({})", self.origin.repr(tcx))
+impl<'tcx> fmt::Debug for TypeTrace<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TypeTrace({:?})", self.origin)
     }
 }
 
@@ -1126,48 +1125,11 @@ impl TypeOrigin {
     }
 }
 
-impl<'tcx> Repr<'tcx> for TypeOrigin {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        match *self {
-            MethodCompatCheck(a) => {
-                format!("MethodCompatCheck({})", a.repr(tcx))
-            }
-            ExprAssignable(a) => {
-                format!("ExprAssignable({})", a.repr(tcx))
-            }
-            Misc(a) => format!("Misc({})", a.repr(tcx)),
-            RelateTraitRefs(a) => {
-                format!("RelateTraitRefs({})", a.repr(tcx))
-            }
-            RelateSelfType(a) => {
-                format!("RelateSelfType({})", a.repr(tcx))
-            }
-            RelateOutputImplTypes(a) => {
-                format!("RelateOutputImplTypes({})", a.repr(tcx))
-            }
-            MatchExpressionArm(a, b) => {
-                format!("MatchExpressionArm({}, {})", a.repr(tcx), b.repr(tcx))
-            }
-            IfExpression(a) => {
-                format!("IfExpression({})", a.repr(tcx))
-            }
-            IfExpressionWithNoElse(a) => {
-                format!("IfExpressionWithNoElse({})", a.repr(tcx))
-            }
-            RangeExpression(a) => {
-                format!("RangeExpression({})", a.repr(tcx))
-            }
-            EquatePredicate(a) => {
-                format!("EquatePredicate({})", a.repr(tcx))
-            }
-        }
-    }
-}
-
 impl<'tcx> SubregionOrigin<'tcx> {
     pub fn span(&self) -> Span {
         match *self {
             Subtype(ref a) => a.span(),
+            DefaultExistentialBound(ref a) => a.span(),
             InfStackClosure(a) => a,
             InvokeClosure(a) => a,
             DerefPointer(a) => a,
@@ -1193,70 +1155,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            Subtype(ref a) => {
-                format!("Subtype({})", a.repr(tcx))
-            }
-            InfStackClosure(a) => {
-                format!("InfStackClosure({})", a.repr(tcx))
-            }
-            InvokeClosure(a) => {
-                format!("InvokeClosure({})", a.repr(tcx))
-            }
-            DerefPointer(a) => {
-                format!("DerefPointer({})", a.repr(tcx))
-            }
-            FreeVariable(a, b) => {
-                format!("FreeVariable({}, {})", a.repr(tcx), b)
-            }
-            IndexSlice(a) => {
-                format!("IndexSlice({})", a.repr(tcx))
-            }
-            RelateObjectBound(a) => {
-                format!("RelateObjectBound({})", a.repr(tcx))
-            }
-            RelateParamBound(a, b) => {
-                format!("RelateParamBound({},{})",
-                        a.repr(tcx),
-                        b.repr(tcx))
-            }
-            RelateRegionParamBound(a) => {
-                format!("RelateRegionParamBound({})",
-                        a.repr(tcx))
-            }
-            RelateDefaultParamBound(a, b) => {
-                format!("RelateDefaultParamBound({},{})",
-                        a.repr(tcx),
-                        b.repr(tcx))
-            }
-            Reborrow(a) => format!("Reborrow({})", a.repr(tcx)),
-            ReborrowUpvar(a, b) => {
-                format!("ReborrowUpvar({},{:?})", a.repr(tcx), b)
-            }
-            ReferenceOutlivesReferent(_, a) => {
-                format!("ReferenceOutlivesReferent({})", a.repr(tcx))
-            }
-            ExprTypeIsNotInScope(a, b) => {
-                format!("ExprTypeIsNotInScope({}, {})",
-                        a.repr(tcx),
-                        b.repr(tcx))
-            }
-            BindingTypeIsNotValidAtDecl(a) => {
-                format!("BindingTypeIsNotValidAtDecl({})", a.repr(tcx))
-            }
-            CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)),
-            CallArg(a) => format!("CallArg({})", a.repr(tcx)),
-            CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
-            Operand(a) => format!("Operand({})", a.repr(tcx)),
-            AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
-            AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
-            SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),
-        }
-    }
-}
-
 impl RegionVariableOrigin {
     pub fn span(&self) -> Span {
         match *self {
@@ -1272,33 +1170,3 @@ impl RegionVariableOrigin {
         }
     }
 }
-
-impl<'tcx> Repr<'tcx> for RegionVariableOrigin {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            MiscVariable(a) => {
-                format!("MiscVariable({})", a.repr(tcx))
-            }
-            PatternRegion(a) => {
-                format!("PatternRegion({})", a.repr(tcx))
-            }
-            AddrOfRegion(a) => {
-                format!("AddrOfRegion({})", a.repr(tcx))
-            }
-            Autoref(a) => format!("Autoref({})", a.repr(tcx)),
-            Coercion(a) => format!("Coercion({})", a.repr(tcx)),
-            EarlyBoundRegion(a, b) => {
-                format!("EarlyBoundRegion({},{})", a.repr(tcx), b.repr(tcx))
-            }
-            LateBoundRegion(a, b, c) => {
-                format!("LateBoundRegion({},{},{:?})", a.repr(tcx), b.repr(tcx), c)
-            }
-            BoundRegionInCoherence(a) => {
-                format!("bound_regionInCoherence({})", a.repr(tcx))
-            }
-            UpvarRegion(a, b) => {
-                format!("UpvarRegion({}, {})", a.repr(tcx), b.repr(tcx))
-            }
-        }
-    }
-}
index 054cec68745ade14c5abe630742a9f81232cb018..869f4d011cefe18218eb3752c41f029e3cfdafc3 100644 (file)
@@ -24,7 +24,6 @@ use super::Constraint;
 use middle::infer::SubregionOrigin;
 use middle::infer::region_inference::RegionVarBindings;
 use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux::Repr;
 
 use std::borrow::Cow;
 use std::collections::hash_map::Entry::Vacant;
@@ -32,7 +31,7 @@ use std::env;
 use std::fs::File;
 use std::io;
 use std::io::prelude::*;
-use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
+use std::sync::atomic::{AtomicBool, Ordering};
 use syntax::ast;
 
 fn print_help_message() {
@@ -76,7 +75,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
     let output_path = {
         let output_template = match requested_output {
             Ok(ref s) if &**s == "help" => {
-                static PRINTED_YET: AtomicBool = ATOMIC_BOOL_INIT;
+                static PRINTED_YET: AtomicBool = AtomicBool::new(false);
                 if !PRINTED_YET.load(Ordering::SeqCst) {
                     print_help_message();
                     PRINTED_YET.store(true, Ordering::SeqCst);
@@ -191,13 +190,13 @@ impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
             Node::RegionVid(n_vid) =>
                 dot::LabelText::label(format!("{:?}", n_vid)),
             Node::Region(n_rgn) =>
-                dot::LabelText::label(format!("{}", n_rgn.repr(self.tcx))),
+                dot::LabelText::label(format!("{:?}", n_rgn)),
         }
     }
     fn edge_label(&self, e: &Edge) -> dot::LabelText {
         match *e {
             Edge::Constraint(ref c) =>
-                dot::LabelText::label(format!("{}", self.map.get(c).unwrap().repr(self.tcx))),
+                dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap())),
             Edge::EnclScope(..) =>
                 dot::LabelText::label(format!("(enclosed)")),
         }
index 9de362fe360a625d2b2db0aaa7c41ff8ac8072cb..f79fb6b625292cad22efdbcabeac6e21f83dcb3c 100644 (file)
@@ -30,10 +30,10 @@ use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
 use middle::ty_relate::RelateResult;
 use util::common::indenter;
 use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux::{Repr, UserString};
 
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering::{self, Less, Greater, Equal};
+use std::fmt;
 use std::iter::repeat;
 use std::u32;
 use syntax::ast;
@@ -68,7 +68,7 @@ pub enum Verify<'tcx> {
     VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec<Region>),
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
     Projection(ty::ProjectionTy<'tcx>),
@@ -323,8 +323,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         if self.in_snapshot() {
             self.undo_log.borrow_mut().push(AddVar(vid));
         }
-        debug!("created new region variable {:?} with origin {}",
-               vid, origin.repr(self.tcx));
+        debug!("created new region variable {:?} with origin {:?}",
+               vid, origin);
         return vid;
     }
 
@@ -391,8 +391,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // cannot add constraints once regions are resolved
         assert!(self.values_are_none());
 
-        debug!("RegionVarBindings: add_constraint({})",
-               constraint.repr(self.tcx));
+        debug!("RegionVarBindings: add_constraint({:?})",
+               constraint);
 
         if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
             if self.in_snapshot() {
@@ -406,8 +406,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // cannot add verifys once regions are resolved
         assert!(self.values_are_none());
 
-        debug!("RegionVarBindings: add_verify({})",
-               verify.repr(self.tcx));
+        debug!("RegionVarBindings: add_verify({:?})",
+               verify);
 
         let mut verifys = self.verifys.borrow_mut();
         let index = verifys.len();
@@ -425,8 +425,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 
         let mut givens = self.givens.borrow_mut();
         if givens.insert((sub, sup)) {
-            debug!("add_given({} <= {:?})",
-                   sub.repr(self.tcx),
+            debug!("add_given({:?} <= {:?})",
+                   sub,
                    sup);
 
             self.undo_log.borrow_mut().push(AddGiven(sub, sup));
@@ -452,10 +452,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // cannot add constraints once regions are resolved
         assert!(self.values_are_none());
 
-        debug!("RegionVarBindings: make_subregion({}, {}) due to {}",
-               sub.repr(self.tcx),
-               sup.repr(self.tcx),
-               origin.repr(self.tcx));
+        debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
+               sub,
+               sup,
+               origin);
 
         match (sub, sup) {
           (ReEarlyBound(..), ReEarlyBound(..)) => {
@@ -471,9 +471,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
           (_, ReLateBound(..)) => {
             self.tcx.sess.span_bug(
                 origin.span(),
-                &format!("cannot relate bound region: {} <= {}",
-                        sub.repr(self.tcx),
-                        sup.repr(self.tcx)));
+                &format!("cannot relate bound region: {:?} <= {:?}",
+                        sub,
+                        sup));
           }
           (_, ReStatic) => {
             // all regions are subregions of static, so we can ignore this
@@ -510,9 +510,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // cannot add constraints once regions are resolved
         assert!(self.values_are_none());
 
-        debug!("RegionVarBindings: lub_regions({}, {})",
-               a.repr(self.tcx),
-               b.repr(self.tcx));
+        debug!("RegionVarBindings: lub_regions({:?}, {:?})",
+               a,
+               b);
         match (a, b) {
             (ReStatic, _) | (_, ReStatic) => {
                 ReStatic // nothing lives longer than static
@@ -535,9 +535,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // cannot add constraints once regions are resolved
         assert!(self.values_are_none());
 
-        debug!("RegionVarBindings: glb_regions({}, {})",
-               a.repr(self.tcx),
-               b.repr(self.tcx));
+        debug!("RegionVarBindings: glb_regions({:?}, {:?})",
+               a,
+               b);
         match (a, b) {
             (ReStatic, r) | (r, ReStatic) => {
                 // static lives longer than everything else
@@ -563,7 +563,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             }
             Some(ref values) => {
                 let r = lookup(values, rid);
-                debug!("resolve_var({:?}) = {}", rid, r.repr(self.tcx));
+                debug!("resolve_var({:?}) = {:?}", rid, r);
                 r
             }
         }
@@ -620,7 +620,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     /// made---`r0` itself will be the first entry. This is used when checking whether skolemized
     /// regions are being improperly related to other regions.
     pub fn tainted(&self, mark: &RegionSnapshot, r0: Region) -> Vec<Region> {
-        debug!("tainted(mark={:?}, r0={})", mark, r0.repr(self.tcx));
+        debug!("tainted(mark={:?}, r0={:?})", mark, r0);
         let _indenter = indenter();
 
         // `result_set` acts as a worklist: we explore all outgoing
@@ -731,9 +731,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
           (ReEarlyBound(..), _) |
           (_, ReEarlyBound(..)) => {
             self.tcx.sess.bug(
-                &format!("cannot relate bound region: LUB({}, {})",
-                        a.repr(self.tcx),
-                        b.repr(self.tcx)));
+                &format!("cannot relate bound region: LUB({:?}, {:?})",
+                        a,
+                        b));
           }
 
           (ReStatic, _) | (_, ReStatic) => {
@@ -836,9 +836,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             (ReEarlyBound(..), _) |
             (_, ReEarlyBound(..)) => {
               self.tcx.sess.bug(
-                  &format!("cannot relate bound region: GLB({}, {})",
-                          a.repr(self.tcx),
-                          b.repr(self.tcx)));
+                  &format!("cannot relate bound region: GLB({:?}, {:?})",
+                          a,
+                          b));
             }
 
             (ReStatic, r) | (r, ReStatic) => {
@@ -959,7 +959,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 #[derive(Copy, Clone, PartialEq, Debug)]
 enum Classification { Expanding, Contracting }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum VarValue { NoValue, Value(Region), ErrorValue }
 
 struct VarData {
@@ -984,14 +984,18 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 
         // Dorky hack to cause `dump_constraints` to only get called
         // if debug mode is enabled:
-        debug!("----() End constraint listing {:?}---", self.dump_constraints());
+        debug!("----() End constraint listing (subject={}) {:?}---",
+               subject, self.dump_constraints(subject));
         graphviz::maybe_print_constraints_for(self, subject);
 
+        let graph = self.construct_graph();
+        self.expand_givens(&graph);
         self.expansion(free_regions, &mut var_data);
         self.contraction(free_regions, &mut var_data);
         let values =
             self.extract_values_and_collect_conflicts(free_regions,
-                                                      &var_data[..],
+                                                      &var_data,
+                                                      &graph,
                                                       errors);
         self.collect_concrete_region_errors(free_regions, &values, errors);
         values
@@ -1010,21 +1014,46 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         }).collect()
     }
 
-    fn dump_constraints(&self) {
-        debug!("----() Start constraint listing ()----");
+    fn dump_constraints(&self, subject: ast::NodeId) {
+        debug!("----() Start constraint listing (subject={}) ()----", subject);
         for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
-            debug!("Constraint {} => {}", idx, constraint.repr(self.tcx));
+            debug!("Constraint {} => {:?}", idx, constraint);
+        }
+    }
+
+    fn expand_givens(&self, graph: &RegionGraph) {
+        // Givens are a kind of horrible hack to account for
+        // constraints like 'c <= '0 that are known to hold due to
+        // closure signatures (see the comment above on the `givens`
+        // field). They should go away. But until they do, the role
+        // of this fn is to account for the transitive nature:
+        //
+        //     Given 'c <= '0
+        //     and   '0 <= '1
+        //     then  'c <= '1
+
+        let mut givens = self.givens.borrow_mut();
+        let seeds: Vec<_> = givens.iter().cloned().collect();
+        for (fr, vid) in seeds {
+            let seed_index = NodeIndex(vid.index as usize);
+            for succ_index in graph.depth_traverse(seed_index) {
+                let succ_index = succ_index.0 as u32;
+                if succ_index < self.num_vars() {
+                    let succ_vid = RegionVid { index: succ_index };
+                    givens.insert((fr, succ_vid));
+                }
+            }
         }
     }
 
     fn expansion(&self, free_regions: &FreeRegionMap, var_data: &mut [VarData]) {
         self.iterate_until_fixed_point("Expansion", |constraint| {
-            debug!("expansion: constraint={} origin={}",
-                   constraint.repr(self.tcx),
+            debug!("expansion: constraint={:?} origin={:?}",
+                   constraint,
                    self.constraints.borrow()
                                    .get(constraint)
                                    .unwrap()
-                                   .repr(self.tcx));
+                                   );
             match *constraint {
               ConstrainRegSubVar(a_region, b_vid) => {
                 let b_data = &mut var_data[b_vid.index as usize];
@@ -1054,10 +1083,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                    b_data: &mut VarData)
                    -> bool
     {
-        debug!("expand_node({}, {:?} == {})",
-               a_region.repr(self.tcx),
+        debug!("expand_node({:?}, {:?} == {:?})",
+               a_region,
                b_vid,
-               b_data.value.repr(self.tcx));
+               b_data.value);
 
         // Check if this relationship is implied by a given.
         match a_region {
@@ -1073,8 +1102,8 @@ 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.repr(self.tcx));
+            debug!("Setting initial value of {:?} to {:?}",
+                   b_vid, a_region);
 
             b_data.value = Value(a_region);
             return true;
@@ -1086,10 +1115,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                 return false;
             }
 
-            debug!("Expanding value of {:?} from {} to {}",
+            debug!("Expanding value of {:?} from {:?} to {:?}",
                    b_vid,
-                   cur_region.repr(self.tcx),
-                   lub.repr(self.tcx));
+                   cur_region,
+                   lub);
 
             b_data.value = Value(lub);
             return true;
@@ -1105,12 +1134,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                    free_regions: &FreeRegionMap,
                    var_data: &mut [VarData]) {
         self.iterate_until_fixed_point("Contraction", |constraint| {
-            debug!("contraction: constraint={} origin={}",
-                   constraint.repr(self.tcx),
+            debug!("contraction: constraint={:?} origin={:?}",
+                   constraint,
                    self.constraints.borrow()
                                    .get(constraint)
                                    .unwrap()
-                                   .repr(self.tcx));
+                                   );
             match *constraint {
               ConstrainRegSubVar(..) => {
                 // This is an expansion constraint.  Ignore.
@@ -1139,9 +1168,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                      a_data: &mut VarData,
                      b_region: Region)
                      -> bool {
-        debug!("contract_node({:?} == {}/{:?}, {})",
-               a_vid, a_data.value.repr(self.tcx),
-               a_data.classification, b_region.repr(self.tcx));
+        debug!("contract_node({:?} == {:?}/{:?}, {:?})",
+               a_vid, a_data.value,
+               a_data.classification, b_region);
 
         return match a_data.value {
             NoValue => {
@@ -1171,10 +1200,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                       -> bool
         {
             if !free_regions.is_subregion_of(this.tcx, a_region, b_region) {
-                debug!("Setting {:?} to ErrorValue: {} not subregion of {}",
+                debug!("Setting {:?} to ErrorValue: {:?} not subregion of {:?}",
                        a_vid,
-                       a_region.repr(this.tcx),
-                       b_region.repr(this.tcx));
+                       a_region,
+                       b_region);
                 a_data.value = ErrorValue;
             }
             false
@@ -1192,19 +1221,19 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                     if glb == a_region {
                         false
                     } else {
-                        debug!("Contracting value of {:?} from {} to {}",
+                        debug!("Contracting value of {:?} from {:?} to {:?}",
                                a_vid,
-                               a_region.repr(this.tcx),
-                               glb.repr(this.tcx));
+                               a_region,
+                               glb);
                         a_data.value = Value(glb);
                         true
                     }
                 }
                 Err(_) => {
-                    debug!("Setting {:?} to ErrorValue: no glb of {}, {}",
+                    debug!("Setting {:?} to ErrorValue: no glb of {:?}, {:?}",
                            a_vid,
-                           a_region.repr(this.tcx),
-                           b_region.repr(this.tcx));
+                           a_region,
+                           b_region);
                     a_data.value = ErrorValue;
                     false
                 }
@@ -1218,7 +1247,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                                       errors: &mut Vec<RegionResolutionError<'tcx>>)
     {
         let mut reg_reg_dups = FnvHashSet();
-        for verify in &*self.verifys.borrow() {
+        for verify in self.verifys.borrow().iter() {
             match *verify {
                 VerifyRegSubReg(ref origin, sub, sup) => {
                     if free_regions.is_subregion_of(self.tcx, sub, sup) {
@@ -1229,9 +1258,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                         continue;
                     }
 
-                    debug!("ConcreteFailure: !(sub <= sup): sub={}, sup={}",
-                           sub.repr(self.tcx),
-                           sup.repr(self.tcx));
+                    debug!("ConcreteFailure: !(sub <= sup): sub={:?}, sup={:?}",
+                           sub,
+                           sup);
                     errors.push(ConcreteFailure((*origin).clone(), sub, sup));
                 }
 
@@ -1258,6 +1287,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         &self,
         free_regions: &FreeRegionMap,
         var_data: &[VarData],
+        graph: &RegionGraph,
         errors: &mut Vec<RegionResolutionError<'tcx>>)
         -> Vec<VarValue>
     {
@@ -1276,8 +1306,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // overlapping locations.
         let mut dup_vec: Vec<_> = repeat(u32::MAX).take(self.num_vars() as usize).collect();
 
-        let mut opt_graph = None;
-
         for idx in 0..self.num_vars() as usize {
             match var_data[idx].value {
                 Value(_) => {
@@ -1313,11 +1341,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                        starts to create problems we'll have to revisit
                        this portion of the code and think hard about it. =) */
 
-                    if opt_graph.is_none() {
-                        opt_graph = Some(self.construct_graph());
-                    }
-                    let graph = opt_graph.as_ref().unwrap();
-
                     let node_vid = RegionVid { index: idx as u32 };
                     match var_data[idx].classification {
                         Expanding => {
@@ -1335,9 +1358,56 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             }
         }
 
+        // Check for future hostile edges tied to a bad default
+        self.report_future_hostility(&graph);
+
         (0..self.num_vars() as usize).map(|idx| var_data[idx].value).collect()
     }
 
+    fn report_future_hostility(&self, graph: &RegionGraph) {
+        let constraints = self.constraints.borrow();
+        for edge in graph.all_edges() {
+            match constraints[&edge.data] {
+                SubregionOrigin::DefaultExistentialBound(_) => {
+                    // this will become 'static in the future
+                }
+                _ => { continue; }
+            }
+
+            // this constraint will become a 'static constraint in the
+            // future, so walk outward and see if we have any hard
+            // bounds that could not be inferred to 'static
+            for nid in graph.depth_traverse(edge.target()) {
+                for (_, succ) in graph.outgoing_edges(nid) {
+                    match succ.data {
+                        ConstrainVarSubReg(_, r) => {
+                            match r {
+                                ty::ReStatic | ty::ReInfer(_) => {
+                                    /* OK */
+                                }
+                                ty::ReFree(_) | ty::ReScope(_) | ty::ReEmpty => {
+                                    span_warn!(
+                                        self.tcx.sess,
+                                        constraints[&edge.data].span(),
+                                        E0398,
+                                        "this code may fail to compile in Rust 1.3 due to \
+                                         the proposed change in object lifetime bound defaults");
+                                    return; // only issue the warning once per fn
+                                }
+                                ty::ReEarlyBound(..) | ty::ReLateBound(..) => {
+                                    self.tcx.sess.span_bug(
+                                        constraints[&succ.data].span(),
+                                        "relation to bound region");
+                                }
+                            }
+                        }
+                        _ => { }
+                    }
+                }
+            }
+        }
+    }
+
     fn construct_graph(&self) -> RegionGraph {
         let num_vars = self.num_vars();
 
@@ -1350,7 +1420,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         }
         let dummy_idx = graph.add_node(());
 
-        for (constraint, _) in &*constraints {
+        for (constraint, _) in constraints.iter() {
             match *constraint {
                 ConstrainVarSubVar(a_id, b_id) => {
                     graph.add_edge(NodeIndex(a_id.index as usize),
@@ -1431,10 +1501,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         self.tcx.sess.span_bug(
             (*self.var_origins.borrow())[node_idx.index as usize].span(),
             &format!("collect_error_for_expanding_node() could not find error \
-                    for var {:?}, lower_bounds={}, upper_bounds={}",
+                    for var {:?}, lower_bounds={:?}, upper_bounds={:?}",
                     node_idx,
-                    lower_bounds.repr(self.tcx),
-                    upper_bounds.repr(self.tcx)));
+                    lower_bounds,
+                    upper_bounds));
     }
 
     fn collect_error_for_contracting_node(
@@ -1478,9 +1548,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         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={}",
+                     for var {:?}, upper_bounds={:?}",
                     node_idx,
-                    upper_bounds.repr(self.tcx)));
+                    upper_bounds));
     }
 
     fn collect_concrete_regions(&self,
@@ -1575,11 +1645,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             changed = false;
             iteration += 1;
             debug!("---- {} Iteration {}{}", "#", tag, iteration);
-            for (constraint, _) in &*self.constraints.borrow() {
+            for (constraint, _) in self.constraints.borrow().iter() {
                 let edge_changed = body(constraint);
                 if edge_changed {
-                    debug!("Updated due to constraint {}",
-                           constraint.repr(self.tcx));
+                    debug!("Updated due to constraint {:?}",
+                           constraint);
                     changed = true;
                 }
             }
@@ -1589,31 +1659,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 
 }
 
-impl<'tcx> Repr<'tcx> for Constraint {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        match *self {
-            ConstrainVarSubVar(a, b) => {
-                format!("ConstrainVarSubVar({}, {})", a.repr(tcx), b.repr(tcx))
-            }
-            ConstrainRegSubVar(a, b) => {
-                format!("ConstrainRegSubVar({}, {})", a.repr(tcx), b.repr(tcx))
-            }
-            ConstrainVarSubReg(a, b) => {
-                format!("ConstrainVarSubReg({}, {})", a.repr(tcx), b.repr(tcx))
-            }
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for Verify<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for Verify<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             VerifyRegSubReg(_, ref a, ref b) => {
-                format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx))
+                write!(f, "VerifyRegSubReg({:?}, {:?})", a, b)
             }
             VerifyGenericBound(_, ref p, ref a, ref bs) => {
-                format!("VerifyGenericBound({}, {}, {})",
-                        p.repr(tcx), a.repr(tcx), bs.repr(tcx))
+                write!(f, "VerifyGenericBound({:?}, {:?}, {:?})", p, a, bs)
             }
         }
     }
@@ -1634,38 +1687,28 @@ fn lookup(values: &Vec<VarValue>, rid: ty::RegionVid) -> ty::Region {
     }
 }
 
-impl<'tcx> Repr<'tcx> for VarValue {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        match *self {
-            NoValue => format!("NoValue"),
-            Value(r) => format!("Value({})", r.repr(tcx)),
-            ErrorValue => format!("ErrorValue"),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for RegionAndOrigin<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("RegionAndOrigin({},{})",
-                self.region.repr(tcx),
-                self.origin.repr(tcx))
+impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "RegionAndOrigin({:?},{:?})",
+               self.region,
+               self.origin)
     }
 }
 
-impl<'tcx> Repr<'tcx> for GenericKind<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for GenericKind<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            GenericKind::Param(ref p) => p.repr(tcx),
-            GenericKind::Projection(ref p) => p.repr(tcx),
+            GenericKind::Param(ref p) => write!(f, "{:?}", p),
+            GenericKind::Projection(ref p) => write!(f, "{:?}", p),
         }
     }
 }
 
-impl<'tcx> UserString<'tcx> for GenericKind<'tcx> {
-    fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Display for GenericKind<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            GenericKind::Param(ref p) => p.user_string(tcx),
-            GenericKind::Projection(ref p) => p.user_string(tcx),
+            GenericKind::Param(ref p) => write!(f, "{}", p),
+            GenericKind::Projection(ref p) => write!(f, "{}", p),
         }
     }
 }
index b9025d01068cc9fc76c2cb7eeb011ad5ea807cc6..b67437fd12781d0c2e9791e01504e0eca95fa779 100644 (file)
@@ -11,7 +11,6 @@
 use super::{InferCtxt, fixup_err, fres, unresolved_ty, unresolved_int_ty, unresolved_float_ty};
 use middle::ty::{self, Ty};
 use middle::ty_fold::{self, TypeFoldable};
-use util::ppaux::Repr;
 
 ///////////////////////////////////////////////////////////////////////////
 // OPPORTUNISTIC TYPE RESOLVER
@@ -81,22 +80,22 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
         } else {
             let t = self.infcx.shallow_resolve(t);
             match t.sty {
-                ty::ty_infer(ty::TyVar(vid)) => {
+                ty::TyInfer(ty::TyVar(vid)) => {
                     self.err = Some(unresolved_ty(vid));
                     self.tcx().types.err
                 }
-                ty::ty_infer(ty::IntVar(vid)) => {
+                ty::TyInfer(ty::IntVar(vid)) => {
                     self.err = Some(unresolved_int_ty(vid));
                     self.tcx().types.err
                 }
-                ty::ty_infer(ty::FloatVar(vid)) => {
+                ty::TyInfer(ty::FloatVar(vid)) => {
                     self.err = Some(unresolved_float_ty(vid));
                     self.tcx().types.err
                 }
-                ty::ty_infer(_) => {
+                ty::TyInfer(_) => {
                     self.infcx.tcx.sess.bug(
-                        &format!("Unexpected type in full type resolver: {}",
-                                t.repr(self.infcx.tcx)));
+                        &format!("Unexpected type in full type resolver: {:?}",
+                                t));
                 }
                 _ => {
                     ty_fold::super_fold_ty(self, t)
index 31b654a5b3fd3b5fcfba885019ade59349aa69a6..7c40e96a2f7a5c8e43eb922c7b6fcd0cb7aae133 100644 (file)
 
 use super::combine::{self, CombineFields};
 use super::higher_ranked::HigherRankedRelations;
-use super::Subtype;
+use super::SubregionOrigin;
 use super::type_variable::{SubtypeOf, SupertypeOf};
 
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
-use middle::ty_relate::{Relate, RelateResult, TypeRelation};
-use util::ppaux::{Repr};
+use middle::ty_relate::{Cause, Relate, RelateResult, TypeRelation};
+use std::mem;
 
 /// "Greatest lower bound" (common subtype)
 pub struct Sub<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>
+    fields: CombineFields<'a, 'tcx>,
 }
 
 impl<'a, 'tcx> Sub<'a, 'tcx> {
@@ -34,6 +34,25 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
     fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx }
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
+    fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
+        where F: FnOnce(&mut Self) -> R
+    {
+        debug!("sub with_cause={:?}", cause);
+        let old_cause = mem::replace(&mut self.fields.cause, Some(cause));
+        let r = f(self);
+        debug!("sub old_cause={:?}", old_cause);
+        self.fields.cause = old_cause;
+        r
+    }
+
+    fn will_change(&mut self, a: bool, b: bool) -> bool {
+        // if we have (Foo+'a) <: (Foo+'b), this requires that 'a:'b.
+        // So if 'a becomes 'static, no additional errors can occur.
+        // OTOH, if 'a stays the same, but 'b becomes 'static, we
+        // could have a problem.
+        !a && b
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                variance: ty::Variance,
                                                a: &T,
@@ -49,7 +68,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
     }
 
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({}, {})", self.tag(), a.repr(self.tcx()), b.repr(self.tcx()));
+        debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
 
         if a == b { return Ok(a); }
 
@@ -57,24 +76,24 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
         let a = infcx.type_variables.borrow().replace_if_possible(a);
         let b = infcx.type_variables.borrow().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
+            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
                 infcx.type_variables
                     .borrow_mut()
                     .relate_vars(a_id, SubtypeOf, b_id);
                 Ok(a)
             }
-            (&ty::ty_infer(TyVar(a_id)), _) => {
+            (&ty::TyInfer(TyVar(a_id)), _) => {
                 try!(self.fields
                          .switch_expected()
                          .instantiate(b, SupertypeOf, a_id));
                 Ok(a)
             }
-            (_, &ty::ty_infer(TyVar(b_id))) => {
+            (_, &ty::TyInfer(TyVar(b_id))) => {
                 try!(self.fields.instantiate(a, SubtypeOf, b_id));
                 Ok(a)
             }
 
-            (&ty::ty_err, _) | (_, &ty::ty_err) => {
+            (&ty::TyError, _) | (_, &ty::TyError) => {
                 Ok(self.tcx().types.err)
             }
 
@@ -85,11 +104,14 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
     }
 
     fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
-               self.tag(),
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
-        let origin = Subtype(self.fields.trace.clone());
+        debug!("{}.regions({:?}, {:?}) self.cause={:?}",
+               self.tag(), a, b, self.fields.cause);
+        let origin = match self.fields.cause {
+            Some(Cause::ExistentialRegionBound(true)) =>
+                SubregionOrigin::DefaultExistentialBound(self.fields.trace.clone()),
+            _ =>
+                SubregionOrigin::Subtype(self.fields.trace.clone()),
+        };
         self.fields.infcx.region_vars.make_subregion(origin, a, b);
         Ok(a)
     }
index b3e3e016d85c2cbde4a6fa559ccd63b08c49a9a4..6f1de3ee63597cf24f94a0b08951f5d13ae08062 100644 (file)
@@ -131,7 +131,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
 
     pub fn replace_if_possible(&self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::ty_infer(ty::TyVar(v)) => {
+            ty::TyInfer(ty::TyVar(v)) => {
                 match self.probe(v) {
                     None => t,
                     Some(u) => u
index 2a4c25345447fb84e980525862e8b8b984fafbd5..c4d924d676c89ff93d8bd0999c546c9e46801a17 100644 (file)
@@ -8,17 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use ast_map::NodeForeignItem;
 use metadata::csearch;
 use middle::def::DefFn;
 use middle::subst::{Subst, Substs, EnumeratedItems};
-use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn};
+use middle::ty::{TransmuteRestriction, ctxt, TyBareFn};
 use middle::ty::{self, Ty};
-use util::ppaux::Repr;
+
+use std::fmt;
 
 use syntax::abi::RustIntrinsic;
 use syntax::ast::DefId;
 use syntax::ast;
-use syntax::ast_map::NodeForeignItem;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::visit::Visitor;
@@ -54,7 +55,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
         let intrinsic = match ty::lookup_item_type(self.tcx, def_id).ty.sty {
-            ty::ty_bare_fn(_, ref bfty) => bfty.abi == RustIntrinsic,
+            ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
             _ => return false
         };
         if def_id.krate == ast::LOCAL_CRATE {
@@ -202,17 +203,17 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
 
         match types_in_scope.next() {
             None => {
-                debug!("with_each_combination(substs={})",
-                       substs.repr(self.tcx));
+                debug!("with_each_combination(substs={:?})",
+                       substs);
 
                 callback(substs);
             }
 
             Some((space, index, &param_ty)) => {
-                debug!("with_each_combination: space={:?}, index={}, param_ty={}",
-                       space, index, param_ty.repr(self.tcx));
+                debug!("with_each_combination: space={:?}, index={}, param_ty={:?}",
+                       space, index, param_ty);
 
-                if !ty::type_is_sized(param_env, span, param_ty) {
+                if !ty::type_is_sized(Some(param_env), self.tcx, span, param_ty) {
                     debug!("with_each_combination: param_ty is not known to be sized");
 
                     substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
@@ -228,7 +229,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
     }
 
     fn push_transmute_restriction(&self, restriction: TransmuteRestriction<'tcx>) {
-        debug!("Pushing transmute restriction: {}", restriction.repr(self.tcx));
+        debug!("Pushing transmute restriction: {:?}", restriction);
         self.tcx.transmute_restrictions.borrow_mut().push(restriction);
     }
 }
@@ -256,7 +257,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
                 DefFn(did, _) if self.def_id_is_transmute(did) => {
                     let typ = ty::node_id_to_type(self.tcx, expr.id);
                     match typ.sty {
-                        ty_bare_fn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
+                        TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
                             if let ty::FnConverging(to) = bare_fn_ty.sig.0.output {
                                 let from = bare_fn_ty.sig.0.inputs[0];
                                 self.check_transmute(expr.span, from, to, expr.id);
@@ -277,13 +278,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for TransmuteRestriction<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("TransmuteRestriction(id={}, original=({},{}), substituted=({},{}))",
-                self.id,
-                self.original_from.repr(tcx),
-                self.original_to.repr(tcx),
-                self.substituted_from.repr(tcx),
-                self.substituted_to.repr(tcx))
+impl<'tcx> fmt::Debug for TransmuteRestriction<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TransmuteRestriction(id={}, original=({:?},{:?}), substituted=({:?},{:?}))",
+               self.id,
+               self.original_from,
+               self.original_to,
+               self.substituted_from,
+               self.substituted_to)
     }
 }
index d4136637e585c5391a76fde2bf3b79759aa1875e..9bcc251725c002cc58476ae2b2e661c3b17cd4e0 100644 (file)
@@ -1498,7 +1498,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> {
         let fn_ty = ty::node_id_to_type(self.ir.tcx, id);
         match fn_ty.sty {
-            ty::ty_closure(closure_def_id, substs) =>
+            ty::TyClosure(closure_def_id, substs) =>
                 self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
             _ =>
                 ty::ty_fn_ret(fn_ty),
index 3fff15049930b6d6b80cbd56c7e8cccb548af858..ca8de74b35bda68072c5cff84a29a139bd9f977a 100644 (file)
@@ -65,7 +65,6 @@ pub use self::InteriorKind::*;
 pub use self::FieldName::*;
 pub use self::ElementKind::*;
 pub use self::MutabilityCategory::*;
-pub use self::InteriorSafety::*;
 pub use self::AliasableReason::*;
 pub use self::Note::*;
 pub use self::deref_kind::*;
@@ -73,24 +72,22 @@ pub use self::categorization::*;
 
 use self::Aliasability::*;
 
+use ast_map;
 use middle::check_const;
 use middle::def;
 use middle::region;
 use middle::ty::{self, Ty};
 use util::nodemap::NodeMap;
-use util::ppaux::{Repr, UserString};
 
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
-use syntax::ast_map;
 use syntax::codemap::Span;
-use syntax::print::pprust;
-use syntax::parse::token;
 
 use std::cell::RefCell;
+use std::fmt;
 use std::rc::Rc;
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq)]
 pub enum categorization<'tcx> {
     cat_rvalue(ty::Region),                    // temporary val, argument is its scope
     cat_static_item,
@@ -104,14 +101,14 @@ pub enum categorization<'tcx> {
 }
 
 // Represents any kind of upvar
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq)]
 pub struct Upvar {
     pub id: ty::UpvarId,
     pub kind: ty::ClosureKind
 }
 
 // different kinds of pointers:
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum PointerKind {
     /// `Box<T>`
     Unique,
@@ -128,7 +125,7 @@ pub enum PointerKind {
 
 // We use the term "interior" to mean "something reachable from the
 // base without a pointer dereference", e.g. a field
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum InteriorKind {
     InteriorField(FieldName),
     InteriorElement(InteriorOffsetKind, ElementKind),
@@ -185,7 +182,7 @@ pub enum Note {
 // dereference, but its type is the type *before* the dereference
 // (`@T`). So use `cmt.ty` to find the type of the value in a consistent
 // fashion. For more details, see the method `cat_pattern`
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq)]
 pub struct cmt_<'tcx> {
     pub id: ast::NodeId,           // id of expr/pat producing this value
     pub span: Span,                // span of same expr/pat
@@ -212,25 +209,25 @@ type DerefKindContext = Option<InteriorOffsetKind>;
 // pointer adjustment).
 fn deref_kind(t: Ty, context: DerefKindContext) -> McResult<deref_kind> {
     match t.sty {
-        ty::ty_uniq(_) => {
+        ty::TyBox(_) => {
             Ok(deref_ptr(Unique))
         }
 
-        ty::ty_rptr(r, mt) => {
+        ty::TyRef(r, mt) => {
             let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
             Ok(deref_ptr(BorrowedPtr(kind, *r)))
         }
 
-        ty::ty_ptr(ref mt) => {
+        ty::TyRawPtr(ref mt) => {
             Ok(deref_ptr(UnsafePtr(mt.mutbl)))
         }
 
-        ty::ty_enum(..) |
-        ty::ty_struct(..) => { // newtype
+        ty::TyEnum(..) |
+        ty::TyStruct(..) => { // newtype
             Ok(deref_interior(InteriorField(PositionalField(0))))
         }
 
-        ty::ty_vec(_, _) | ty::ty_str => {
+        ty::TyArray(_, _) | ty::TySlice(_) | ty::TyStr => {
             // no deref of indexed content without supplying InteriorOffsetKind
             if let Some(context) = context {
                 Ok(deref_interior(InteriorElement(context, element_kind(t))))
@@ -419,7 +416,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     }
 
     fn pat_ty(&self, pat: &ast::Pat) -> McResult<Ty<'tcx>> {
-        let tcx = self.typer.tcx();
         let base_ty = try!(self.typer.node_ty(pat.id));
         // FIXME (Issue #18207): This code detects whether we are
         // looking at a `ref x`, and if so, figures out what the type
@@ -437,8 +433,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             }
             _ => base_ty,
         };
-        debug!("pat_ty(pat={}) base_ty={} ret_ty={}",
-               pat.repr(tcx), base_ty.repr(tcx), ret_ty.repr(tcx));
+        debug!("pat_ty(pat={:?}) base_ty={:?} ret_ty={:?}",
+               pat, base_ty, ret_ty);
         Ok(ret_ty)
     }
 
@@ -461,9 +457,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     ty::AdjustReifyFnPointer |
                     ty::AdjustUnsafeFnPointer |
                     ty::AdjustDerefRef(_) => {
-                        debug!("cat_expr({}): {}",
-                               adjustment.repr(self.tcx()),
-                               expr.repr(self.tcx()));
+                        debug!("cat_expr({:?}): {:?}",
+                               adjustment,
+                               expr);
                         // Result is an rvalue.
                         let expr_ty = try!(self.expr_ty_adjusted(expr));
                         Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
@@ -478,9 +474,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                autoderefs: usize)
                                -> McResult<cmt<'tcx>> {
         let mut cmt = try!(self.cat_expr_unadjusted(expr));
-        debug!("cat_expr_autoderefd: autoderefs={}, cmt={}",
+        debug!("cat_expr_autoderefd: autoderefs={}, cmt={:?}",
                autoderefs,
-               cmt.repr(self.tcx()));
+               cmt);
         for deref in 1..autoderefs + 1 {
             cmt = try!(self.cat_deref(expr, cmt, deref, None));
         }
@@ -488,7 +484,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     }
 
     pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
-        debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
+        debug!("cat_expr: id={} expr={:?}", expr.id, expr);
 
         let expr_ty = try!(self.expr_ty(expr));
         match expr.node {
@@ -499,10 +495,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
 
           ast::ExprField(ref base, f_name) => {
             let base_cmt = try!(self.cat_expr(&**base));
-            debug!("cat_expr(cat_field): id={} expr={} base={}",
+            debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
                    expr.id,
-                   expr.repr(self.tcx()),
-                   base_cmt.repr(self.tcx()));
+                   expr,
+                   base_cmt);
             Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty))
           }
 
@@ -523,10 +519,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     // The index method always returns an `&T`, so
                     // dereference it to find the result type.
                     let elem_ty = match ret_ty.sty {
-                        ty::ty_rptr(_, mt) => mt.ty,
+                        ty::TyRef(_, mt) => mt.ty,
                         _ => {
-                            debug!("cat_expr_unadjusted: return type of overloaded index is {}?",
-                                   ret_ty.repr(self.tcx()));
+                            debug!("cat_expr_unadjusted: return type of overloaded index is {:?}?",
+                                   ret_ty);
                             return Err(());
                         }
                     };
@@ -584,8 +580,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                    expr_ty: Ty<'tcx>,
                    def: def::Def)
                    -> McResult<cmt<'tcx>> {
-        debug!("cat_def: id={} expr={} def={:?}",
-               id, expr_ty.repr(self.tcx()), def);
+        debug!("cat_def: id={} expr={:?} def={:?}",
+               id, expr_ty, def);
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
@@ -621,7 +617,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           def::DefUpvar(var_id, fn_node_id) => {
               let ty = try!(self.node_ty(fn_node_id));
               match ty.sty {
-                  ty::ty_closure(closure_id, _) => {
+                  ty::TyClosure(closure_id, _) => {
                       match self.typer.closure_kind(closure_id) {
                           Some(kind) => {
                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
@@ -636,9 +632,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                   _ => {
                       self.tcx().sess.span_bug(
                           span,
-                          &format!("Upvar of non-closure {} - {}",
+                          &format!("Upvar of non-closure {} - {:?}",
                                   fn_node_id,
-                                  ty.repr(self.tcx())));
+                                  ty));
                   }
               }
           }
@@ -747,7 +743,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         };
 
         let ret = Rc::new(cmt_result);
-        debug!("cat_upvar ret={}", ret.repr(self.tcx()));
+        debug!("cat_upvar ret={:?}", ret);
         Ok(ret)
     }
 
@@ -791,7 +787,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         // that the above is actually immutable and
         // has a ref type.  However, nothing should
         // actually look at the type, so we can get
-        // away with stuffing a `ty_err` in there
+        // away with stuffing a `TyError` in there
         // instead of bothering to construct a proper
         // one.
         let cmt_result = cmt_ {
@@ -818,7 +814,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             note: NoteClosureEnv(upvar_id)
         };
 
-        debug!("env_deref ret {}", ret.repr(self.tcx()));
+        debug!("env_deref ret {:?}", ret);
 
         ret
     }
@@ -843,7 +839,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
         let qualif = match expr_ty.sty {
-            ty::ty_vec(_, Some(0)) => qualif,
+            ty::TyArray(_, 0) => qualif,
             _ => check_const::ConstQualif::NOT_CONST
         };
 
@@ -856,7 +852,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty::ReStatic
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
-        debug!("cat_rvalue_node ret {}", ret.repr(self.tcx()));
+        debug!("cat_rvalue_node ret {:?}", ret);
         ret
     }
 
@@ -873,7 +869,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty:expr_ty,
             note: NoteNone
         });
-        debug!("cat_rvalue ret {}", ret.repr(self.tcx()));
+        debug!("cat_rvalue ret {:?}", ret);
         ret
     }
 
@@ -891,7 +887,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty: f_ty,
             note: NoteNone
         });
-        debug!("cat_field ret {}", ret.repr(self.tcx()));
+        debug!("cat_field ret {:?}", ret);
         ret
     }
 
@@ -909,7 +905,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty: f_ty,
             note: NoteNone
         });
-        debug!("cat_tup_field ret {}", ret.repr(self.tcx()));
+        debug!("cat_tup_field ret {:?}", ret);
         ret
     }
 
@@ -926,7 +922,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         let method_ty = self.typer.node_method_ty(method_call);
 
         debug!("cat_deref: method_call={:?} method_ty={:?}",
-               method_call, method_ty.map(|ty| ty.repr(self.tcx())));
+               method_call, method_ty.map(|ty| ty));
 
         let base_cmt = match method_ty {
             Some(method_ty) => {
@@ -944,12 +940,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                               mt.ty,
                                               deref_context,
                                                 /* implicit: */ false);
-                debug!("cat_deref ret {}", ret.repr(self.tcx()));
+                debug!("cat_deref ret {:?}", ret);
                 ret
             }
             None => {
-                debug!("Explicit deref of non-derefable type: {}",
-                       base_cmt_ty.repr(self.tcx()));
+                debug!("Explicit deref of non-derefable type: {:?}",
+                       base_cmt_ty);
                 return Err(());
             }
         }
@@ -992,7 +988,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty: deref_ty,
             note: NoteNone
         });
-        debug!("cat_deref_common ret {}", ret.repr(self.tcx()));
+        debug!("cat_deref_common ret {:?}", ret);
         Ok(ret)
     }
 
@@ -1043,7 +1039,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         let m = base_cmt.mutbl.inherit();
         let ret = interior(elt, base_cmt.clone(), base_cmt.ty,
                            m, context, element_ty);
-        debug!("cat_index ret {}", ret.repr(self.tcx()));
+        debug!("cat_index ret {:?}", ret);
         return Ok(ret);
 
         fn interior<'tcx, N: ast_node>(elt: &N,
@@ -1097,7 +1093,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 base_cmt
             }
         };
-        debug!("deref_vec ret {}", ret.repr(self.tcx()));
+        debug!("deref_vec ret {:?}", ret);
         Ok(ret)
     }
 
@@ -1129,8 +1125,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                           slice_ty: Ty)
                           -> (ast::Mutability, ty::Region) {
             match slice_ty.sty {
-                ty::ty_rptr(r, ref mt) => match mt.ty.sty {
-                    ty::ty_vec(_, None) => (mt.mutbl, *r),
+                ty::TyRef(r, ref mt) => match mt.ty.sty {
+                    ty::TySlice(_) => (mt.mutbl, *r),
                     _ => vec_slice_info(tcx, pat, mt.ty),
                 },
 
@@ -1156,7 +1152,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty: interior_ty,
             note: NoteNone
         });
-        debug!("cat_imm_interior ret={}", ret.repr(self.tcx()));
+        debug!("cat_imm_interior ret={:?}", ret);
         ret
     }
 
@@ -1174,7 +1170,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             ty: downcast_ty,
             note: NoteNone
         });
-        debug!("cat_downcast ret={}", ret.repr(self.tcx()));
+        debug!("cat_downcast ret={:?}", ret);
         ret
     }
 
@@ -1234,9 +1230,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         // step out of sync again. So you'll see below that we always
         // get the type of the *subpattern* and use that.
 
-        debug!("cat_pattern: id={} pat={} cmt={}",
-               pat.id, pprust::pat_to_string(pat),
-               cmt.repr(self.tcx()));
+        debug!("cat_pattern: {:?} cmt={:?}",
+               pat,
+               cmt);
 
         (*op)(self, cmt.clone(), pat);
 
@@ -1385,12 +1381,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum InteriorSafety {
-    InteriorUnsafe,
-    InteriorSafe
-}
-
 #[derive(Clone, Debug)]
 pub enum Aliasability {
     FreelyAliasable(AliasableReason),
@@ -1404,13 +1394,13 @@ pub enum AliasableReason {
     AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
     AliasableOther,
     UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
-    AliasableStatic(InteriorSafety),
-    AliasableStaticMut(InteriorSafety),
+    AliasableStatic,
+    AliasableStaticMut,
 }
 
 impl<'tcx> cmt_<'tcx> {
     pub fn guarantor(&self) -> cmt<'tcx> {
-        //! Returns `self` after stripping away any owned pointer derefs or
+        //! Returns `self` after stripping away any derefs or
         //! interior content. The return value is basically the `cmt` which
         //! determines how long the value in `self` remains live.
 
@@ -1469,16 +1459,10 @@ impl<'tcx> cmt_<'tcx> {
             }
 
             cat_static_item(..) => {
-                let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
-                    InteriorUnsafe
-                } else {
-                    InteriorSafe
-                };
-
                 if self.mutbl.is_mutable() {
-                    FreelyAliasable(AliasableStaticMut(int_safe))
+                    FreelyAliasable(AliasableStaticMut)
                 } else {
-                    FreelyAliasable(AliasableStatic(int_safe))
+                    FreelyAliasable(AliasableStatic)
                 }
             }
 
@@ -1534,7 +1518,7 @@ impl<'tcx> cmt_<'tcx> {
                 let upvar = self.upvar();
                 match upvar.as_ref().map(|i| &i.cat) {
                     Some(&cat_upvar(ref var)) => {
-                        var.user_string(tcx)
+                        var.to_string()
                     }
                     Some(_) => unreachable!(),
                     None => {
@@ -1546,7 +1530,7 @@ impl<'tcx> cmt_<'tcx> {
                                 format!("`Box` content")
                             }
                             UnsafePtr(..) => {
-                                format!("dereference of unsafe pointer")
+                                format!("dereference of raw pointer")
                             }
                             BorrowedPtr(..) => {
                                 format!("borrowed content")
@@ -1574,7 +1558,7 @@ impl<'tcx> cmt_<'tcx> {
                 "pattern-bound indexed content".to_string()
             }
             cat_upvar(ref var) => {
-                var.user_string(tcx)
+                var.to_string()
             }
             cat_downcast(ref cmt, _) => {
                 cmt.descriptive_string(tcx)
@@ -1583,33 +1567,36 @@ impl<'tcx> cmt_<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for cmt_<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("{{{} id:{} m:{:?} ty:{}}}",
-                self.cat.repr(tcx),
-                self.id,
-                self.mutbl,
-                self.ty.repr(tcx))
+impl<'tcx> fmt::Debug for cmt_<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{{{:?} id:{} m:{:?} ty:{:?}}}",
+               self.cat,
+               self.id,
+               self.mutbl,
+               self.ty)
     }
 }
 
-impl<'tcx> Repr<'tcx> for categorization<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for categorization<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            cat_static_item |
-            cat_rvalue(..) |
-            cat_local(..) |
-            cat_upvar(..) => {
-                format!("{:?}", *self)
+            cat_static_item => write!(f, "static"),
+            cat_rvalue(r) => write!(f, "rvalue({:?})", r),
+            cat_local(id) => {
+               let name = ty::tls::with(|tcx| ty::local_var_name_str(tcx, id));
+               write!(f, "local({})", name)
+            }
+            cat_upvar(upvar) => {
+                write!(f, "upvar({:?})", upvar)
             }
             cat_deref(ref cmt, derefs, ptr) => {
-                format!("{}-{}{}->", cmt.cat.repr(tcx), ptr.repr(tcx), derefs)
+                write!(f, "{:?}-{:?}{}->", cmt.cat, ptr, derefs)
             }
             cat_interior(ref cmt, interior) => {
-                format!("{}.{}", cmt.cat.repr(tcx), interior.repr(tcx))
+                write!(f, "{:?}.{:?}", cmt.cat, interior)
             }
             cat_downcast(ref cmt, _) => {
-                format!("{}->(enum)", cmt.cat.repr(tcx))
+                write!(f, "{:?}->(enum)", cmt.cat)
             }
         }
     }
@@ -1628,74 +1615,62 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
     }
 }
 
-impl<'tcx> Repr<'tcx> for PointerKind {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl fmt::Debug for PointerKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Unique => {
-                format!("Box")
-            }
+            Unique => write!(f, "Box"),
             BorrowedPtr(ty::ImmBorrow, ref r) |
             Implicit(ty::ImmBorrow, ref r) => {
-                format!("&{}", r.repr(tcx))
+                write!(f, "&{:?}", r)
             }
             BorrowedPtr(ty::MutBorrow, ref r) |
             Implicit(ty::MutBorrow, ref r) => {
-                format!("&{} mut", r.repr(tcx))
+                write!(f, "&{:?} mut", r)
             }
             BorrowedPtr(ty::UniqueImmBorrow, ref r) |
             Implicit(ty::UniqueImmBorrow, ref r) => {
-                format!("&{} uniq", r.repr(tcx))
-            }
-            UnsafePtr(_) => {
-                format!("*")
+                write!(f, "&{:?} uniq", r)
             }
+            UnsafePtr(_) => write!(f, "*")
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for InteriorKind {
-    fn repr(&self, _tcx: &ty::ctxt) -> String {
+impl fmt::Debug for InteriorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            InteriorField(NamedField(fld)) => {
-                token::get_name(fld).to_string()
-            }
-            InteriorField(PositionalField(i)) => format!("#{}", i),
-            InteriorElement(..) => "[]".to_string(),
+            InteriorField(NamedField(fld)) => write!(f, "{}", fld),
+            InteriorField(PositionalField(i)) => write!(f, "#{}", i),
+            InteriorElement(..) => write!(f, "[]"),
         }
     }
 }
 
 fn element_kind(t: Ty) -> ElementKind {
     match t.sty {
-        ty::ty_rptr(_, ty::mt{ty, ..}) |
-        ty::ty_uniq(ty) => match ty.sty {
-            ty::ty_vec(_, None) => VecElement,
+        ty::TyRef(_, ty::mt{ty, ..}) |
+        ty::TyBox(ty) => match ty.sty {
+            ty::TySlice(_) => VecElement,
             _ => OtherElement
         },
-        ty::ty_vec(..) => VecElement,
+        ty::TyArray(..) | ty::TySlice(_) => VecElement,
         _ => OtherElement
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ClosureKind {
-    fn repr(&self, _: &ty::ctxt) -> String {
-        format!("Upvar({:?})", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for Upvar {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        format!("Upvar({})", self.kind.repr(tcx))
+impl fmt::Debug for Upvar {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}/{:?}", self.id, self.kind)
     }
 }
 
-impl<'tcx> UserString<'tcx> for Upvar {
-    fn user_string(&self, _: &ty::ctxt) -> String {
+impl fmt::Display for Upvar {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let kind = match self.kind {
             ty::FnClosureKind => "Fn",
             ty::FnMutClosureKind => "FnMut",
             ty::FnOnceClosureKind => "FnOnce",
         };
-        format!("captured outer variable in an `{}` closure", kind)
+        write!(f, "captured outer variable in an `{}` closure", kind)
     }
 }
index 27a30f5cf253cf97da67691b72b29ec2863119cc..0cb302d79b866c47c3dd616fc9c2d70e6e86ac03 100644 (file)
@@ -135,12 +135,19 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
     contains_bindings
 }
 
-/// Checks if the pattern contains any `ref` or `ref mut` bindings.
-pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
-    let mut result = false;
+/// Checks if the pattern contains any `ref` or `ref mut` bindings,
+/// and if yes wether its containing mutable ones or just immutables ones.
+pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> Option<ast::Mutability> {
+    let mut result = None;
     pat_bindings(dm, pat, |mode, _, _, _| {
         match mode {
-            ast::BindingMode::BindByRef(_) => { result = true; }
+            ast::BindingMode::BindByRef(m) => {
+                // Pick Mutable as maximum
+                match result {
+                    None | Some(ast::MutImmutable) => result = Some(m),
+                    _ => (),
+                }
+            }
             ast::BindingMode::BindByValue(_) => { }
         }
     });
@@ -148,9 +155,14 @@ pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
 }
 
 /// Checks if the patterns for this arm contain any `ref` or `ref mut`
-/// bindings.
-pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> bool {
-    arm.pats.iter().any(|pat| pat_contains_ref_binding(dm, pat))
+/// bindings, and if yes wether its containing mutable ones or just immutables ones.
+pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> Option<ast::Mutability> {
+    arm.pats.iter()
+            .filter_map(|pat| pat_contains_ref_binding(dm, pat))
+            .max_by(|m| match *m {
+                ast::MutMutable => 1,
+                ast::MutImmutable => 0,
+            })
 }
 
 /// Checks if the pattern contains any patterns that bind something to
@@ -189,3 +201,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
         span: DUMMY_SP,
     })
 }
+
+/// Return variants that are necessary to exist for the pattern to match.
+pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
+    let mut variants = vec![];
+    walk_pat(pat, |p| {
+        match p.node {
+            ast::PatEnum(_, _) |
+            ast::PatIdent(_, _, None) |
+            ast::PatStruct(..) => {
+                match dm.borrow().get(&p.id) {
+                    Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
+                        variants.push(id.node);
+                    }
+                    _ => ()
+                }
+            }
+            _ => ()
+        }
+        true
+    });
+    variants.sort();
+    variants.dedup();
+    variants
+}
index b532dc88df4cb5c939c6935ddd20bd1edbd2fba8..0bbcfa700388c847eb94716a9b0a828bf354ee56 100644 (file)
@@ -15,6 +15,7 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
+use ast_map;
 use middle::def;
 use middle::ty;
 use middle::privacy;
@@ -24,7 +25,6 @@ use util::nodemap::NodeSet;
 use std::collections::HashSet;
 use syntax::abi;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util::is_local;
 use syntax::attr;
 use syntax::visit::Visitor;
@@ -46,7 +46,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
 
     match item.node {
         ast::ItemImpl(_, _, ref generics, _, _, _) |
-        ast::ItemFn(_, _, _, ref generics, _) => {
+        ast::ItemFn(_, _, _, _, ref generics, _) => {
             generics_require_inlining(generics)
         }
         _ => false,
@@ -256,7 +256,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             // but all other rust-only interfaces can be private (they will not
             // participate in linkage after this product is produced)
             if let ast_map::NodeItem(item) = *node {
-                if let ast::ItemFn(_, _, abi, _, _) = item.node {
+                if let ast::ItemFn(_, _, _, abi, _, _) = item.node {
                     if abi != abi::Rust {
                         self.reachable_symbols.insert(search_item);
                     }
@@ -273,7 +273,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
         match *node {
             ast_map::NodeItem(item) => {
                 match item.node {
-                    ast::ItemFn(_, _, _, _, ref search_block) => {
+                    ast::ItemFn(_, _, _, _, _, ref search_block) => {
                         if item_might_be_inlined(&*item) {
                             visit::walk_block(self, &**search_block)
                         }
@@ -354,7 +354,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     // this properly would result in the necessity of computing *type*
     // reachability, which might result in a compile time loss.
     fn mark_destructors_reachable(&mut self) {
-        for (_, destructor_def_id) in &*self.tcx.destructor_for_type.borrow() {
+        for (_, destructor_def_id) in self.tcx.destructor_for_type.borrow().iter() {
             if destructor_def_id.krate == ast::LOCAL_CRATE {
                 self.reachable_symbols.insert(destructor_def_id.node);
             }
index 2c510b5f1d3b5d79d7b313dc67851cc15c0b0fa2..2a033d36a4777968fa568f166be7ac46da2b7c9b 100644 (file)
@@ -16,6 +16,7 @@
 //! Most of the documentation on regions can be found in
 //! `middle/typeck/infer/region_inference.rs`
 
+use ast_map;
 use session::Session;
 use middle::ty::{self, Ty};
 use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
@@ -25,7 +26,6 @@ use syntax::codemap::{self, Span};
 use syntax::{ast, visit};
 use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
 use syntax::ast_util::stmt_id;
-use syntax::ast_map;
 use syntax::ptr::P;
 use syntax::visit::{Visitor, FnKind};
 
index e7a03a9b7e17439ea4a1557ea9e1c026897d88b4..9e5ad7b42f5c5b751328313a92dbc87bec3ef8e3 100644 (file)
@@ -154,7 +154,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
                 b: &'v ast::Block, s: Span, _: ast::NodeId) {
         match fk {
-            visit::FkItemFn(_, generics, _, _, _) => {
+            visit::FkItemFn(_, generics, _, _, _, _) => {
                 self.visit_early_late(subst::FnSpace, generics, |this| {
                     this.walk_fn(fk, fd, b, s)
                 })
@@ -232,7 +232,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     }
 
     fn visit_generics(&mut self, generics: &ast::Generics) {
-        for ty_param in &*generics.ty_params {
+        for ty_param in generics.ty_params.iter() {
             visit::walk_ty_param_bounds_helper(self, &ty_param.bounds);
             match ty_param.default {
                 Some(ref ty) => self.visit_ty(&**ty),
@@ -447,7 +447,7 @@ impl<'a> LifetimeContext<'a> {
                    fb: &'b ast::Block,
                    _span: Span) {
         match fk {
-            visit::FkItemFn(_, generics, _, _, _) => {
+            visit::FkItemFn(_, generics, _, _, _, _) => {
                 visit::walk_fn_decl(self, fd);
                 self.visit_generics(generics);
             }
@@ -773,7 +773,7 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
         let mut collector =
             FreeLifetimeCollector { early_bound: &mut early_bound,
                                     late_bound: &mut late_bound };
-        for ty_param in &*generics.ty_params {
+        for ty_param in generics.ty_params.iter() {
             visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
         }
         for predicate in &generics.where_clause.predicates {
index d75dc861e83304a0702fb699333b7df9c3e3185c..3f00d9ba5e98d149cd9c5d94b7bce402d533a76f 100644 (file)
@@ -23,46 +23,46 @@ use syntax::{attr, visit};
 use syntax::ast;
 use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
 use syntax::ast::{Item, Generics, StructField};
-use syntax::ast_util::is_local;
+use syntax::ast_util::{is_local, local_def};
 use syntax::attr::{Stability, AttrMetaMethods};
 use syntax::visit::{FnKind, Visitor};
 use syntax::feature_gate::emit_feature_err;
-use util::nodemap::{NodeMap, DefIdMap, FnvHashSet, FnvHashMap};
-use util::ppaux::Repr;
+use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 
 use std::mem::replace;
 
 /// A stability index, giving the stability level for items and methods.
-pub struct Index {
-    // Indicates whether this crate has #![feature(staged_api)]
-    staged_api: bool,
-    // stability for crate-local items; unmarked stability == no entry
-    local: NodeMap<Stability>,
-    // cache for extern-crate items; unmarked stability == entry with None
-    extern_cache: DefIdMap<Option<Stability>>
+pub struct Index<'tcx> {
+    /// This is mostly a cache, except the stabilities of local items
+    /// are filled by the annotator.
+    map: DefIdMap<Option<&'tcx Stability>>,
+
+    /// Maps for each crate whether it is part of the staged API.
+    staged_api: FnvHashMap<ast::CrateNum, bool>
 }
 
 // A private tree-walker for producing an Index.
-struct Annotator<'a> {
-    sess: &'a Session,
-    index: &'a mut Index,
-    parent: Option<Stability>,
+struct Annotator<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    index: &'a mut Index<'tcx>,
+    parent: Option<&'tcx Stability>,
     export_map: &'a PublicItems,
 }
 
-impl<'a> Annotator<'a> {
+impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
     // Determine the stability for a node based on its attributes and inherited
     // stability. The stability is recorded in the index and used as the parent.
     fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
                    attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
         F: FnOnce(&mut Annotator),
     {
-        if self.index.staged_api {
+        if self.index.staged_api[&ast::LOCAL_CRATE] {
             debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
-            match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
+            match attr::find_stability(self.tcx.sess.diagnostic(), attrs, item_sp) {
                 Some(stab) => {
                     debug!("annotate: found {:?}", stab);
-                    self.index.local.insert(id, stab.clone());
+                    let stab = self.tcx.intern_stability(stab);
+                    self.index.map.insert(local_def(id), Some(stab));
 
                     // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
                     if stab.level != attr::Stable {
@@ -77,13 +77,14 @@ impl<'a> Annotator<'a> {
                     debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
                            use_parent, self.parent);
                     if use_parent {
-                        if let Some(stab) = self.parent.clone() {
-                            self.index.local.insert(id, stab);
-                        } else if self.index.staged_api && required
+                        if let Some(stab) = self.parent {
+                            self.index.map.insert(local_def(id), Some(stab));
+                        } else if self.index.staged_api[&ast::LOCAL_CRATE] && required
                             && self.export_map.contains(&id)
-                            && !self.sess.opts.test {
-                                self.sess.span_err(item_sp,
-                                                   "This node does not have a stability attribute");
+                            && !self.tcx.sess.opts.test {
+                                self.tcx.sess.span_err(item_sp,
+                                                       "This node does not \
+                                                        have a stability attribute");
                             }
                     }
                     f(self);
@@ -95,7 +96,7 @@ impl<'a> Annotator<'a> {
                 let tag = attr.name();
                 if tag == "unstable" || tag == "stable" || tag == "deprecated" {
                     attr::mark_used(attr);
-                    self.sess.span_err(attr.span(),
+                    self.tcx.sess.span_err(attr.span(),
                                        "stability attributes may not be used outside \
                                         of the standard library");
                 }
@@ -105,7 +106,7 @@ impl<'a> Annotator<'a> {
     }
 }
 
-impl<'a, 'v> Visitor<'v> for Annotator<'a> {
+impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
     fn visit_item(&mut self, i: &Item) {
         // FIXME (#18969): the following is a hack around the fact
         // that we cannot currently annotate the stability of
@@ -168,11 +169,11 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> {
     }
 }
 
-impl Index {
+impl<'tcx> Index<'tcx> {
     /// Construct the stability index for a crate being compiled.
-    pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems) {
+    pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, export_map: &PublicItems) {
         let mut annotator = Annotator {
-            sess: sess,
+            tcx: tcx,
             index: self,
             parent: None,
             export_map: export_map,
@@ -182,22 +183,23 @@ impl Index {
     }
 
     pub fn new(krate: &Crate) -> Index {
-        let mut staged_api = false;
+        let mut is_staged_api = false;
         for attr in &krate.attrs {
             if &attr.name()[..] == "staged_api" {
                 match attr.node.value.node {
                     ast::MetaWord(_) => {
                         attr::mark_used(attr);
-                        staged_api = true;
+                        is_staged_api = true;
                     }
                     _ => (/*pass*/)
                 }
             }
         }
+        let mut staged_api = FnvHashMap();
+        staged_api.insert(ast::LOCAL_CRATE, is_staged_api);
         Index {
             staged_api: staged_api,
-            local: NodeMap(),
-            extern_cache: DefIdMap()
+            map: DefIdMap(),
         }
     }
 }
@@ -232,13 +234,13 @@ struct Checker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Checker<'a, 'tcx> {
-    fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<Stability>) {
+    fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<&Stability>) {
         // Only the cross-crate scenario matters when checking unstable APIs
         let cross_crate = !is_local(id);
         if !cross_crate { return }
 
         match *stab {
-            Some(Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
+            Some(&Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
                 self.used_features.insert(feature.clone(), attr::Unstable);
 
                 if !self.active_features.contains(feature) {
@@ -252,7 +254,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                                       &feature, span, &msg);
                 }
             }
-            Some(Stability { level, ref feature, .. }) => {
+            Some(&Stability { level, ref feature, .. }) => {
                 self.used_features.insert(feature.clone(), level);
 
                 // Stable APIs are always ok to call and deprecated APIs are
@@ -312,7 +314,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
 
 /// Helper for discovering nodes to check for stability
 pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     match item.node {
         ast::ItemExternCrate(_) => {
             // compiler-generated `extern crate` items have a dummy span.
@@ -349,7 +351,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
 
 /// Helper for discovering nodes to check for stability
 pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     let span;
     let id = match e.node {
         ast::ExprMethodCall(i, _, _) => {
@@ -384,7 +386,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
         ast::ExprField(ref base_e, ref field) => {
             span = field.span;
             match ty::expr_ty_adjusted(tcx, base_e).sty {
-                ty::ty_struct(did, _) => {
+                ty::TyStruct(did, _) => {
                     ty::lookup_struct_fields(tcx, did)
                         .iter()
                         .find(|f| f.name == field.node.name)
@@ -401,7 +403,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
         ast::ExprTupField(ref base_e, ref field) => {
             span = field.span;
             match ty::expr_ty_adjusted(tcx, base_e).sty {
-                ty::ty_struct(did, _) => {
+                ty::TyStruct(did, _) => {
                     ty::lookup_struct_fields(tcx, did)
                         .get(field.node)
                         .unwrap_or_else(|| {
@@ -410,7 +412,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                         })
                         .id
                 }
-                ty::ty_tup(..) => return,
+                ty::TyTuple(..) => return,
                 _ => tcx.sess.span_bug(e.span,
                                        "stability::check_expr: unnamed field access on \
                                         something other than a tuple or struct")
@@ -419,7 +421,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
         ast::ExprStruct(_, ref expr_fields, _) => {
             let type_ = ty::expr_ty(tcx, e);
             match type_.sty {
-                ty::ty_struct(did, _) => {
+                ty::TyStruct(did, _) => {
                     let struct_fields = ty::lookup_struct_fields(tcx, did);
                     // check the stability of each field that appears
                     // in the construction expression.
@@ -442,12 +444,12 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                 // we don't look at stability attributes on
                 // struct-like enums (yet...), but it's definitely not
                 // a bug to have construct one.
-                ty::ty_enum(..) => return,
+                ty::TyEnum(..) => return,
                 _ => {
                     tcx.sess.span_bug(e.span,
                                       &format!("stability::check_expr: struct construction \
                                                 of non-struct, type {:?}",
-                                               type_.repr(tcx)));
+                                               type_));
                 }
             }
         }
@@ -458,7 +460,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
 }
 
 pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         Some(def::DefPrimTy(..)) => {}
         Some(def) => {
@@ -470,19 +472,19 @@ pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
 }
 
 pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
-                 cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                 cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
 
     let did = match ty::pat_ty_opt(tcx, pat) {
-        Some(&ty::TyS { sty: ty::ty_struct(did, _), .. }) => did,
+        Some(&ty::TyS { sty: ty::TyStruct(did, _), .. }) => did,
         Some(_) | None => return,
     };
     let struct_fields = ty::lookup_struct_fields(tcx, did);
     match pat.node {
         // Foo(a, b, c)
         ast::PatEnum(_, Some(ref pat_fields)) => {
-            for (field, struct_field) in pat_fields.iter().zip(struct_fields.iter()) {
+            for (field, struct_field) in pat_fields.iter().zip(&struct_fields) {
                 // a .. pattern is fine, but anything positional is
                 // not.
                 if let ast::PatWild(ast::PatWildMulti) = field.node {
@@ -511,7 +513,7 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
 }
 
 fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
-                            cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                            cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     if !is_staged_api(tcx, id) { return  }
     if is_internal(tcx, span) { return }
     let ref stability = lookup(tcx, id);
@@ -528,20 +530,27 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
             if trait_method_id != id => {
                 is_staged_api(tcx, trait_method_id)
             }
-        _ if is_local(id) => {
-            tcx.stability.borrow().staged_api
-        }
         _ => {
-            csearch::is_staged_api(&tcx.sess.cstore, id)
+            *tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
+                || csearch::is_staged_api(&tcx.sess.cstore, id.krate))
         }
     }
 }
 
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
-pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
-    debug!("lookup(id={})",
-           id.repr(tcx));
+pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
+    if let Some(st) = tcx.stability.borrow().map.get(&id) {
+        return *st;
+    }
+
+    let st = lookup_uncached(tcx, id);
+    tcx.stability.borrow_mut().map.insert(id, st);
+    st
+}
+
+fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
+    debug!("lookup(id={:?})", id);
 
     // is this definition the implementation of a trait method?
     match ty::trait_item_of_item(tcx, id) {
@@ -553,25 +562,23 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
     }
 
     let item_stab = if is_local(id) {
-        tcx.stability.borrow().local.get(&id.node).cloned()
+        None // The stability cache is filled partially lazily
     } else {
-        let stab = csearch::get_stability(&tcx.sess.cstore, id);
-        let mut index = tcx.stability.borrow_mut();
-        (*index).extern_cache.insert(id, stab.clone());
-        stab
+        csearch::get_stability(&tcx.sess.cstore, id).map(|st| tcx.intern_stability(st))
     };
 
     item_stab.or_else(|| {
-        if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
-            // FIXME (#18969): for the time being, simply use the
-            // stability of the trait to determine the stability of any
-            // unmarked impls for it. See FIXME above for more details.
-
-            debug!("lookup: trait_id={:?}", trait_id);
-            lookup(tcx, trait_id)
-        } else {
-            None
+        if ty::is_impl(tcx, id) {
+            if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
+                // FIXME (#18969): for the time being, simply use the
+                // stability of the trait to determine the stability of any
+                // unmarked impls for it. See FIXME above for more details.
+
+                debug!("lookup: trait_id={:?}", trait_id);
+                return lookup(tcx, trait_id);
+            }
         }
+        None
     })
 }
 
@@ -587,14 +594,14 @@ pub fn check_unused_or_stable_features(sess: &Session,
 
     let stable_msg = "this feature is stable. attribute no longer needed";
 
-    for &span in sess.features.borrow().declared_stable_lang_features.iter() {
+    for &span in &sess.features.borrow().declared_stable_lang_features {
         sess.add_lint(lint::builtin::STABLE_FEATURES,
                       ast::CRATE_NODE_ID,
                       span,
                       stable_msg.to_string());
     }
 
-    for (used_lib_feature, level) in lib_features_used.iter() {
+    for (used_lib_feature, level) in lib_features_used {
         match remaining_lib_features.remove(used_lib_feature) {
             Some(span) => {
                 if *level == attr::Stable {
@@ -608,7 +615,7 @@ pub fn check_unused_or_stable_features(sess: &Session,
         }
     }
 
-    for (_, &span) in remaining_lib_features.iter() {
+    for &span in remaining_lib_features.values() {
         sess.add_lint(lint::builtin::UNUSED_FEATURES,
                       ast::CRATE_NODE_ID,
                       span,
index 500255db330c5c62df937621f324f8e1b7a9e3c0..c3c29d0ade8dfb0e64b5403f1c902bb48111ec86 100644 (file)
@@ -15,7 +15,6 @@ pub use self::RegionSubsts::*;
 
 use middle::ty::{self, Ty};
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
-use util::ppaux::Repr;
 
 use std::fmt;
 use std::iter::IntoIterator;
@@ -29,7 +28,7 @@ use syntax::codemap::{Span, DUMMY_SP};
 /// identify each in-scope parameter by an *index* and a *parameter
 /// space* (which indices where the parameter is defined; see
 /// `ParamSpace`).
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct Substs<'tcx> {
     pub types: VecPerParamSpace<Ty<'tcx>>,
     pub regions: RegionSubsts,
@@ -38,7 +37,7 @@ pub struct Substs<'tcx> {
 /// Represents the values to use when substituting lifetime parameters.
 /// If the value is `ErasedRegions`, then this subst is occurring during
 /// trans, and all region parameters will be replaced with `ty::ReStatic`.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub enum RegionSubsts {
     ErasedRegions,
     NonerasedRegions(VecPerParamSpace<ty::Region>)
@@ -240,13 +239,11 @@ pub struct SeparateVecsPerParamSpace<T> {
 }
 
 impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "VecPerParamSpace {{"));
-        for space in &ParamSpace::all() {
-            try!(write!(fmt, "{:?}: {:?}, ", *space, self.get_slice(*space)));
-        }
-        try!(write!(fmt, "}}"));
-        Ok(())
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "[{:?};{:?};{:?}]",
+               self.get_slice(TypeSpace),
+               self.get_slice(SelfSpace),
+               self.get_slice(FnSpace))
     }
 }
 
@@ -279,8 +276,8 @@ impl<T> VecPerParamSpace<T> {
         let self_limit = type_limit + s.len();
 
         let mut content = t;
-        content.extend(s.into_iter());
-        content.extend(f.into_iter());
+        content.extend(s);
+        content.extend(f);
 
         VecPerParamSpace {
             type_limit: type_limit,
@@ -448,20 +445,6 @@ impl<T> VecPerParamSpace<T> {
                                        self.self_limit)
     }
 
-    pub fn map_move<U, F>(self, mut pred: F) -> VecPerParamSpace<U> where
-        F: FnMut(T) -> U,
-    {
-        let SeparateVecsPerParamSpace {
-            types: t,
-            selfs: s,
-            fns: f
-        } = self.split();
-
-        VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
-                              s.into_iter().map(|p| pred(p)).collect(),
-                              f.into_iter().map(|p| pred(p)).collect())
-    }
-
     pub fn split(self) -> SeparateVecsPerParamSpace<T> {
         let VecPerParamSpace { type_limit, self_limit, content } = self;
 
@@ -634,10 +617,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
                                 self.tcx().sess.span_bug(
                                     span,
                                     &format!("Type parameter out of range \
-                                              when substituting in region {} (root type={}) \
+                                              when substituting in region {} (root type={:?}) \
                                               (space={:?}, index={})",
-                                             data.name.as_str(),
-                                             self.root_ty.repr(self.tcx()),
+                                             data.name,
+                                             self.root_ty,
                                              data.space,
                                              data.index));
                             }
@@ -661,7 +644,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
         self.ty_stack_depth += 1;
 
         let t1 = match t.sty {
-            ty::ty_param(p) => {
+            ty::TyParam(p) => {
                 self.ty_for_param(p, t)
             }
             _ => {
@@ -689,14 +672,14 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
                 let span = self.span.unwrap_or(DUMMY_SP);
                 self.tcx().sess.span_bug(
                     span,
-                    &format!("Type parameter `{}` ({}/{:?}/{}) out of range \
-                                 when substituting (root type={}) substs={}",
-                            p.repr(self.tcx()),
-                            source_ty.repr(self.tcx()),
+                    &format!("Type parameter `{:?}` ({:?}/{:?}/{}) out of range \
+                                 when substituting (root type={:?}) substs={:?}",
+                            p,
+                            source_ty,
                             p.space,
                             p.idx,
-                            self.root_ty.repr(self.tcx()),
-                            self.substs.repr(self.tcx())));
+                            self.root_ty,
+                            self.substs));
             }
         };
 
@@ -747,14 +730,14 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
     /// is that only in the second case have we passed through a fn binder.
     fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
         debug!("shift_regions(ty={:?}, region_binders_passed={:?}, type_has_escaping_regions={:?})",
-               ty.repr(self.tcx()), self.region_binders_passed, ty::type_has_escaping_regions(ty));
+               ty, self.region_binders_passed, ty::type_has_escaping_regions(ty));
 
         if self.region_binders_passed == 0 || !ty::type_has_escaping_regions(ty) {
             return ty;
         }
 
         let result = ty_fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
-        debug!("shift_regions: shifted result = {:?}", result.repr(self.tcx()));
+        debug!("shift_regions: shifted result = {:?}", result);
 
         result
     }
index 9c47d7f217aac183d663e3bc3b65b86aa740bc22..853d12172af5ef67010e6db28f4f987958d099c0 100644 (file)
@@ -120,7 +120,7 @@ implement `Convert` like so:
 
 ```rust
 impl Convert<uint> for int { ... } // int -> uint
-impl Convert<int> for uint { ... } // uint -> uint
+impl Convert<int> for uint { ... } // uint -> int
 ```
 
 Now imagine there is some code like the following:
index 222da6d7c3e5ef39ca6a6174d7d2b20632557273..a826836b10c62c181accd85e1c82eef74bc5b9a4 100644 (file)
@@ -22,7 +22,6 @@ use middle::ty::{self, ToPolyTraitRef, Ty};
 use middle::infer::{self, InferCtxt};
 use syntax::ast;
 use syntax::codemap::{DUMMY_SP, Span};
-use util::ppaux::Repr;
 
 #[derive(Copy, Clone)]
 struct InferIsLocal(bool);
@@ -34,10 +33,10 @@ pub fn overlapping_impls(infcx: &InferCtxt,
                          -> bool
 {
     debug!("impl_can_satisfy(\
-           impl1_def_id={}, \
-           impl2_def_id={})",
-           impl1_def_id.repr(infcx.tcx),
-           impl2_def_id.repr(infcx.tcx));
+           impl1_def_id={:?}, \
+           impl2_def_id={:?})",
+           impl1_def_id,
+           impl2_def_id);
 
     let param_env = &ty::empty_parameter_environment(infcx.tcx);
     let selcx = &mut SelectionContext::intercrate(infcx, param_env);
@@ -53,9 +52,9 @@ fn overlap(selcx: &mut SelectionContext,
            b_def_id: ast::DefId)
            -> bool
 {
-    debug!("overlap(a_def_id={}, b_def_id={})",
-           a_def_id.repr(selcx.tcx()),
-           b_def_id.repr(selcx.tcx()));
+    debug!("overlap(a_def_id={:?}, b_def_id={:?})",
+           a_def_id,
+           b_def_id);
 
     let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx,
                                                                 a_def_id,
@@ -65,9 +64,9 @@ fn overlap(selcx: &mut SelectionContext,
                                                                 b_def_id,
                                                                 util::fresh_type_vars_for_impl);
 
-    debug!("overlap: a_trait_ref={}", a_trait_ref.repr(selcx.tcx()));
+    debug!("overlap: a_trait_ref={:?}", a_trait_ref);
 
-    debug!("overlap: b_trait_ref={}", b_trait_ref.repr(selcx.tcx()));
+    debug!("overlap: b_trait_ref={:?}", b_trait_ref);
 
     // Does `a <: b` hold? If not, no overlap.
     if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
@@ -81,16 +80,15 @@ fn overlap(selcx: &mut SelectionContext,
     debug!("overlap: subtraitref check succeeded");
 
     // Are any of the obligations unsatisfiable? If so, no overlap.
-    let tcx = selcx.tcx();
     let infcx = selcx.infcx();
     let opt_failing_obligation =
         a_obligations.iter()
-                     .chain(b_obligations.iter())
+                     .chain(&b_obligations)
                      .map(|o| infcx.resolve_type_vars_if_possible(o))
                      .find(|o| !selcx.evaluate_obligation(o));
 
     if let Some(failing_obligation) = opt_failing_obligation {
-        debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(tcx));
+        debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
         return false
     }
 
@@ -99,7 +97,7 @@ fn overlap(selcx: &mut SelectionContext,
 
 pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> bool
 {
-    debug!("trait_ref_is_knowable(trait_ref={})", trait_ref.repr(tcx));
+    debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
 
     // if the orphan rules pass, that means that no ancestor crate can
     // impl this, so it's up to us.
@@ -155,12 +153,12 @@ fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     let Normalized { value: predicates, obligations: normalization_obligations2 } =
         project::normalize(selcx, ObligationCause::dummy(), &predicates);
     let impl_obligations =
-        util::predicates_for_generics(selcx.tcx(), ObligationCause::dummy(), 0, &predicates);
+        util::predicates_for_generics(ObligationCause::dummy(), 0, &predicates);
 
     let impl_obligations: Vec<_> =
         impl_obligations.into_iter()
-        .chain(normalization_obligations1.into_iter())
-        .chain(normalization_obligations2.into_iter())
+        .chain(normalization_obligations1)
+        .chain(normalization_obligations2)
         .collect();
 
     (impl_trait_ref, impl_obligations)
@@ -181,17 +179,17 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
                           impl_def_id: ast::DefId)
                           -> Result<(), OrphanCheckErr<'tcx>>
 {
-    debug!("orphan_check({})", impl_def_id.repr(tcx));
+    debug!("orphan_check({:?})", impl_def_id);
 
     // We only except this routine to be invoked on implementations
     // of a trait, not inherent implementations.
     let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
-    debug!("orphan_check: trait_ref={}", trait_ref.repr(tcx));
+    debug!("orphan_check: trait_ref={:?}", trait_ref);
 
     // If the *trait* is local to the crate, ok.
     if trait_ref.def_id.krate == ast::LOCAL_CRATE {
-        debug!("trait {} is local to current crate",
-               trait_ref.def_id.repr(tcx));
+        debug!("trait {:?} is local to current crate",
+               trait_ref.def_id);
         return Ok(());
     }
 
@@ -203,26 +201,26 @@ fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 infer_is_local: InferIsLocal)
                                 -> Result<(), OrphanCheckErr<'tcx>>
 {
-    debug!("orphan_check_trait_ref(trait_ref={}, infer_is_local={})",
-           trait_ref.repr(tcx), infer_is_local.0);
+    debug!("orphan_check_trait_ref(trait_ref={:?}, infer_is_local={})",
+           trait_ref, infer_is_local.0);
 
     // First, create an ordered iterator over all the type parameters to the trait, with the self
     // type appearing first.
     let input_tys = Some(trait_ref.self_ty());
-    let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace).iter());
+    let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace));
 
     // Find the first input type that either references a type parameter OR
     // some local type.
     for input_ty in input_tys {
         if ty_is_local(tcx, input_ty, infer_is_local) {
-            debug!("orphan_check_trait_ref: ty_is_local `{}`", input_ty.repr(tcx));
+            debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
 
             // First local input type. Check that there are no
             // uncovered type parameters.
             let uncovered_tys = uncovered_tys(tcx, input_ty, infer_is_local);
             for uncovered_ty in uncovered_tys {
                 if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) {
-                    debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
+                    debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
                     return Err(OrphanCheckErr::UncoveredTy(param));
                 }
             }
@@ -235,7 +233,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
         // parameters reachable.
         if !infer_is_local.0 {
             if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) {
-                debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
+                debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
                 return Err(OrphanCheckErr::UncoveredTy(param));
             }
         }
@@ -255,7 +253,7 @@ fn uncovered_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
         vec![]
     } else if fundamental_ty(tcx, ty) {
         ty.walk_shallow()
-          .flat_map(|t| uncovered_tys(tcx, t, infer_is_local).into_iter())
+          .flat_map(|t| uncovered_tys(tcx, t, infer_is_local))
           .collect()
     } else {
         vec![ty]
@@ -265,7 +263,7 @@ fn uncovered_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool {
     match ty.sty {
         // FIXME(#20590) straighten story about projection types
-        ty::ty_projection(..) | ty::ty_param(..) => true,
+        ty::TyProjection(..) | ty::TyParam(..) => true,
         _ => false,
     }
 }
@@ -279,11 +277,11 @@ fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, infer_is_local: InferIs
 fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
 {
     match ty.sty {
-        ty::ty_uniq(..) | ty::ty_rptr(..) =>
+        ty::TyBox(..) | ty::TyRef(..) =>
             true,
-        ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) =>
+        ty::TyEnum(def_id, _) | ty::TyStruct(def_id, _) =>
             ty::has_attr(tcx, def_id, "fundamental"),
-        ty::ty_trait(ref data) =>
+        ty::TyTrait(ref data) =>
             ty::has_attr(tcx, data.principal_def_id(), "fundamental"),
         _ =>
             false
@@ -295,48 +293,49 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  infer_is_local: InferIsLocal)
                                  -> bool
 {
-    debug!("ty_is_local_constructor({})", ty.repr(tcx));
+    debug!("ty_is_local_constructor({:?})", ty);
 
     match ty.sty {
-        ty::ty_bool |
-        ty::ty_char |
-        ty::ty_int(..) |
-        ty::ty_uint(..) |
-        ty::ty_float(..) |
-        ty::ty_str(..) |
-        ty::ty_bare_fn(..) |
-        ty::ty_vec(..) |
-        ty::ty_ptr(..) |
-        ty::ty_rptr(..) |
-        ty::ty_tup(..) |
-        ty::ty_param(..) |
-        ty::ty_projection(..) => {
+        ty::TyBool |
+        ty::TyChar |
+        ty::TyInt(..) |
+        ty::TyUint(..) |
+        ty::TyFloat(..) |
+        ty::TyStr(..) |
+        ty::TyBareFn(..) |
+        ty::TyArray(..) |
+        ty::TySlice(..) |
+        ty::TyRawPtr(..) |
+        ty::TyRef(..) |
+        ty::TyTuple(..) |
+        ty::TyParam(..) |
+        ty::TyProjection(..) => {
             false
         }
 
-        ty::ty_infer(..) => {
+        ty::TyInfer(..) => {
             infer_is_local.0
         }
 
-        ty::ty_enum(def_id, _) |
-        ty::ty_struct(def_id, _) => {
+        ty::TyEnum(def_id, _) |
+        ty::TyStruct(def_id, _) => {
             def_id.krate == ast::LOCAL_CRATE
         }
 
-        ty::ty_uniq(_) => { // Box<T>
+        ty::TyBox(_) => { // Box<T>
             let krate = tcx.lang_items.owned_box().map(|d| d.krate);
             krate == Some(ast::LOCAL_CRATE)
         }
 
-        ty::ty_trait(ref tt) => {
+        ty::TyTrait(ref tt) => {
             tt.principal_def_id().krate == ast::LOCAL_CRATE
         }
 
-        ty::ty_closure(..) |
-        ty::ty_err => {
+        ty::TyClosure(..) |
+        ty::TyError => {
             tcx.sess.bug(
-                &format!("ty_is_local invoked on unexpected type: {}",
-                        ty.repr(tcx)))
+                &format!("ty_is_local invoked on unexpected type: {:?}",
+                        ty))
         }
     }
 }
index 2b82987480d6ea70ad5dbc3ef7fac4153a22000e..8618f5215290769924d31ce6813b1b6171de2b40 100644 (file)
@@ -28,9 +28,9 @@ use middle::infer::InferCtxt;
 use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
 use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
+use std::fmt;
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
-use util::ppaux::{Repr, UserString};
 
 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                            errors: &Vec<FulfillmentError<'tcx>>) {
@@ -60,16 +60,16 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 {
     let predicate =
         infcx.resolve_type_vars_if_possible(&obligation.predicate);
-    // The ty_err created by normalize_to_error can end up being unified
+    // The TyError created by normalize_to_error can end up being unified
     // into all obligations: for example, if our obligation is something
     // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
-    // then $X will be unified with ty_err, but the error still needs to be
+    // then $X will be unified with TyError, but the error still needs to be
     // reported.
     if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
         span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
                 "type mismatch resolving `{}`: {}",
-                predicate.user_string(infcx.tcx),
-                ty::type_err_to_str(infcx.tcx, &error.err));
+                predicate,
+                error.err);
         note_obligation_cause(infcx, obligation);
     }
 }
@@ -79,7 +79,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                      span: Span) -> Option<String> {
     let def_id = trait_ref.def_id;
     let mut report = None;
-    for item in &*ty::get_attrs(infcx.tcx, def_id) {
+    for item in ty::get_attrs(infcx.tcx, def_id).iter() {
         if item.check_name("rustc_on_unimplemented") {
             let err_sp = if item.meta().span == DUMMY_SP {
                 span
@@ -87,16 +87,16 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                 item.meta().span
             };
             let def = ty::lookup_trait_def(infcx.tcx, def_id);
-            let trait_str = def.trait_ref.user_string(infcx.tcx);
+            let trait_str = def.trait_ref.to_string();
             if let Some(ref istring) = item.value_str() {
                 let mut generic_map = def.generics.types.iter_enumerated()
                                          .map(|(param, i, gen)| {
                                                (gen.name.as_str().to_string(),
                                                 trait_ref.substs.types.get(param, i)
-                                                         .user_string(infcx.tcx))
+                                                         .to_string())
                                               }).collect::<HashMap<String, String>>();
                 generic_map.insert("Self".to_string(),
-                                   trait_ref.self_ty().user_string(infcx.tcx));
+                                   trait_ref.self_ty().to_string());
                 let parser = Parser::new(&istring);
                 let mut errored = false;
                 let err: String = parser.filter_map(|p| {
@@ -157,13 +157,13 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
                                           obligation: &Obligation<'tcx, T>)
                                           -> !
-    where T: UserString<'tcx> + TypeFoldable<'tcx>
+    where T: fmt::Display + TypeFoldable<'tcx>
 {
     let predicate =
         infcx.resolve_type_vars_if_possible(&obligation.predicate);
     span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
               "overflow evaluating the requirement `{}`",
-              predicate.user_string(infcx.tcx));
+              predicate);
 
     suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
 
@@ -184,7 +184,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     span_err!(infcx.tcx.sess, obligation.cause.span, E0276,
                             "the requirement `{}` appears on the impl \
                             method but not on the corresponding trait method",
-                            obligation.predicate.user_string(infcx.tcx));;
+                            obligation.predicate);;
                 }
                 _ => {
                     match obligation.predicate {
@@ -197,8 +197,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                 let trait_ref = trait_predicate.to_poly_trait_ref();
                                 span_err!(infcx.tcx.sess, obligation.cause.span, E0277,
                                         "the trait `{}` is not implemented for the type `{}`",
-                                        trait_ref.user_string(infcx.tcx),
-                                        trait_ref.self_ty().user_string(infcx.tcx));
+                                        trait_ref,
+                                        trait_ref.self_ty());
                                 // Check if it has a custom "#[rustc_on_unimplemented]"
                                 // error message, report with that message if it does
                                 let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
@@ -216,8 +216,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                                                &predicate).err().unwrap();
                             span_err!(infcx.tcx.sess, obligation.cause.span, E0278,
                                     "the requirement `{}` is not satisfied (`{}`)",
-                                    predicate.user_string(infcx.tcx),
-                                    ty::type_err_to_str(infcx.tcx, &err));
+                                    predicate,
+                                    err);
                         }
 
                         ty::Predicate::RegionOutlives(ref predicate) => {
@@ -226,8 +226,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                                                       &predicate).err().unwrap();
                             span_err!(infcx.tcx.sess, obligation.cause.span, E0279,
                                     "the requirement `{}` is not satisfied (`{}`)",
-                                    predicate.user_string(infcx.tcx),
-                                    ty::type_err_to_str(infcx.tcx, &err));
+                                    predicate,
+                                    err);
                         }
 
                         ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
@@ -235,7 +235,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                     infcx.resolve_type_vars_if_possible(&obligation.predicate);
                                 span_err!(infcx.tcx.sess, obligation.cause.span, E0280,
                                         "the requirement `{}` is not satisfied",
-                                        predicate.user_string(infcx.tcx));
+                                        predicate);
                         }
                     }
                 }
@@ -249,10 +249,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                 span_err!(infcx.tcx.sess, obligation.cause.span, E0281,
                         "type mismatch: the type `{}` implements the trait `{}`, \
                         but the trait `{}` is required ({})",
-                        expected_trait_ref.self_ty().user_string(infcx.tcx),
-                        expected_trait_ref.user_string(infcx.tcx),
-                        actual_trait_ref.user_string(infcx.tcx),
-                        ty::type_err_to_str(infcx.tcx, e));
+                        expected_trait_ref.self_ty(),
+                        expected_trait_ref,
+                        actual_trait_ref,
+                        e);
                     note_obligation_cause(infcx, obligation);
             }
         }
@@ -282,7 +282,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         infcx.tcx.sess.span_note(
                             obligation.cause.span,
                             &format!("method `{}` has no receiver",
-                                    method.name.user_string(infcx.tcx)));
+                                    method.name));
                     }
 
                     ObjectSafetyViolation::Method(method,
@@ -291,7 +291,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             obligation.cause.span,
                             &format!("method `{}` references the `Self` type \
                                     in its arguments or return type",
-                                    method.name.user_string(infcx.tcx)));
+                                    method.name));
                     }
 
                     ObjectSafetyViolation::Method(method,
@@ -299,7 +299,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         infcx.tcx.sess.span_note(
                             obligation.cause.span,
                             &format!("method `{}` has generic type parameters",
-                                    method.name.user_string(infcx.tcx)));
+                                    method.name));
                     }
                 }
             }
@@ -316,9 +316,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
     let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
 
-    debug!("maybe_report_ambiguity(predicate={}, obligation={})",
-           predicate.repr(infcx.tcx),
-           obligation.repr(infcx.tcx));
+    debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
+           predicate,
+           obligation);
 
     match predicate {
         ty::Predicate::Trait(ref data) => {
@@ -349,11 +349,11 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         span_err!(infcx.tcx.sess, obligation.cause.span, E0282,
                                 "unable to infer enough type information about `{}`; \
                                  type annotations or generic parameter binding required",
-                                self_ty.user_string(infcx.tcx));
+                                self_ty);
                     } else {
                         span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
                                 "type annotations required: cannot resolve `{}`",
-                                predicate.user_string(infcx.tcx));;
+                                predicate);;
                         note_obligation_cause(infcx, obligation);
                     }
                 }
@@ -365,8 +365,8 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         "coherence failed to report ambiguity: \
                          cannot locate the impl of the trait `{}` for \
                          the type `{}`",
-                        trait_ref.user_string(infcx.tcx),
-                        self_ty.user_string(infcx.tcx)));
+                        trait_ref,
+                        self_ty));
             }
         }
 
@@ -374,7 +374,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.user_string(infcx.tcx));;
+                        predicate);;
                 note_obligation_cause(infcx, obligation);
             }
         }
@@ -383,7 +383,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
 fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
                                       obligation: &Obligation<'tcx, T>)
-    where T: UserString<'tcx>
+    where T: fmt::Display
 {
     note_obligation_cause_code(infcx,
                                &obligation.predicate,
@@ -395,7 +395,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
                                            predicate: &T,
                                            cause_span: Span,
                                            cause_code: &ObligationCauseCode<'tcx>)
-    where T: UserString<'tcx>
+    where T: fmt::Display
 {
     let tcx = infcx.tcx;
     match *cause_code {
@@ -463,7 +463,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
             let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
             span_note!(tcx.sess, cause_span,
                        "required because it appears within the type `{}`",
-                       parent_trait_ref.0.self_ty().user_string(infcx.tcx));
+                       parent_trait_ref.0.self_ty());
             let parent_predicate = parent_trait_ref.as_predicate();
             note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
@@ -471,8 +471,8 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
             let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
             span_note!(tcx.sess, cause_span,
                        "required because of the requirements on the impl of `{}` for `{}`",
-                       parent_trait_ref.user_string(infcx.tcx),
-                       parent_trait_ref.0.self_ty().user_string(infcx.tcx));
+                       parent_trait_ref,
+                       parent_trait_ref.0.self_ty());
             let parent_predicate = parent_trait_ref.as_predicate();
             note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
@@ -480,7 +480,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
             span_note!(tcx.sess, cause_span,
                       "the requirement `{}` appears on the impl method \
                       but not on the corresponding trait method",
-                      predicate.user_string(infcx.tcx));
+                      predicate);
         }
     }
 }
index 5938c6df92a66ecb1264051b0c4500d4d9b67f3f..593a71a30fe2a11ae5dd86609b4df3e2b088d4d7 100644 (file)
 
 use middle::infer::InferCtxt;
 use middle::ty::{self, RegionEscape, Ty};
+
 use std::collections::HashSet;
-use std::default::Default;
+use std::fmt;
 use syntax::ast;
 use util::common::ErrorReported;
-use util::ppaux::Repr;
 use util::nodemap::NodeMap;
 
 use super::CodeAmbiguity;
@@ -28,6 +28,10 @@ use super::select::SelectionContext;
 use super::Unimplemented;
 use super::util::predicate_for_builtin_bound;
 
+pub struct FulfilledPredicates<'tcx> {
+    set: HashSet<ty::Predicate<'tcx>>
+}
+
 /// The fulfillment context is used to drive trait resolution.  It
 /// consists of a list of obligations that must be (eventually)
 /// satisfied. The job is to track which are satisfied, which yielded
@@ -44,7 +48,7 @@ pub struct FulfillmentContext<'tcx> {
     // than the `SelectionCache`: it avoids duplicate errors and
     // permits recursive obligations, which are often generated from
     // traits like `Send` et al.
-    duplicate_set: HashSet<ty::Predicate<'tcx>>,
+    duplicate_set: FulfilledPredicates<'tcx>,
 
     // A list of all obligations that have been registered with this
     // fulfillment context.
@@ -80,6 +84,8 @@ pub struct FulfillmentContext<'tcx> {
     // obligations (otherwise, it's easy to fail to walk to a
     // particular node-id).
     region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
+
+    errors_will_be_reported: bool,
 }
 
 #[derive(Clone)]
@@ -90,12 +96,30 @@ pub struct RegionObligation<'tcx> {
 }
 
 impl<'tcx> FulfillmentContext<'tcx> {
-    pub fn new() -> FulfillmentContext<'tcx> {
+    /// Creates a new fulfillment context.
+    ///
+    /// `errors_will_be_reported` indicates whether ALL errors that
+    /// are generated by this fulfillment context will be reported to
+    /// the end user. This is used to inform caching, because it
+    /// allows us to conclude that traits that resolve successfully
+    /// will in fact always resolve successfully (in particular, it
+    /// guarantees that if some dependent obligation encounters a
+    /// problem, compilation will be aborted).  If you're not sure of
+    /// the right value here, pass `false`, as that is the more
+    /// conservative option.
+    ///
+    /// FIXME -- a better option would be to hold back on modifying
+    /// the global cache until we know that all dependent obligations
+    /// are also satisfied. In that case, we could actually remove
+    /// this boolean flag, and we'd also avoid the problem of squelching
+    /// duplicate errors that occur across fns.
+    pub fn new(errors_will_be_reported: bool) -> FulfillmentContext<'tcx> {
         FulfillmentContext {
-            duplicate_set: HashSet::new(),
+            duplicate_set: FulfilledPredicates::new(),
             predicates: Vec::new(),
             attempted_mark: 0,
             region_obligations: NodeMap(),
+            errors_will_be_reported: errors_will_be_reported,
         }
     }
 
@@ -113,8 +137,8 @@ impl<'tcx> FulfillmentContext<'tcx> {
                                          cause: ObligationCause<'tcx>)
                                          -> Ty<'tcx>
     {
-        debug!("normalize_associated_type(projection_ty={})",
-               projection_ty.repr(infcx.tcx));
+        debug!("normalize_associated_type(projection_ty={:?})",
+               projection_ty);
 
         assert!(!projection_ty.has_escaping_regions());
 
@@ -127,7 +151,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
             self.register_predicate_obligation(infcx, obligation);
         }
 
-        debug!("normalize_associated_type: result={}", normalized.value.repr(infcx.tcx));
+        debug!("normalize_associated_type: result={:?}", normalized.value);
 
         normalized.value
     }
@@ -147,12 +171,11 @@ impl<'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn register_region_obligation<'a>(&mut self,
-                                          infcx: &InferCtxt<'a,'tcx>,
                                           t_a: Ty<'tcx>,
                                           r_b: ty::Region,
                                           cause: ObligationCause<'tcx>)
     {
-        register_region_obligation(infcx.tcx, t_a, r_b, cause, &mut self.region_obligations);
+        register_region_obligation(t_a, r_b, cause, &mut self.region_obligations);
     }
 
     pub fn register_predicate_obligation<'a>(&mut self,
@@ -165,12 +188,12 @@ impl<'tcx> FulfillmentContext<'tcx> {
 
         assert!(!obligation.has_escaping_regions());
 
-        if !self.duplicate_set.insert(obligation.predicate.clone()) {
-            debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx));
+        if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
+            debug!("register_predicate({:?}) -- already seen, skip", obligation);
             return;
         }
 
-        debug!("register_predicate({})", obligation.repr(infcx.tcx));
+        debug!("register_predicate({:?})", obligation);
         self.predicates.push(obligation);
     }
 
@@ -231,6 +254,28 @@ impl<'tcx> FulfillmentContext<'tcx> {
         &self.predicates
     }
 
+    fn is_duplicate_or_add(&mut self, tcx: &ty::ctxt<'tcx>,
+                           predicate: &ty::Predicate<'tcx>)
+                           -> bool {
+        // This is a kind of dirty hack to allow us to avoid "rederiving"
+        // things that we have already proven in other methods.
+        //
+        // The idea is that any predicate that doesn't involve type
+        // parameters and which only involves the 'static region (and
+        // no other regions) is universally solvable, since impls are global.
+        //
+        // This is particularly important since even if we have a
+        // cache hit in the selection context, we still wind up
+        // evaluating the 'nested obligations'.  This cache lets us
+        // skip those.
+
+        if self.errors_will_be_reported && predicate.is_global() {
+            tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
+        } else {
+            self.duplicate_set.is_duplicate_or_add(predicate)
+        }
+    }
+
     /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
     /// only attempts to select obligations that haven't been seen before.
     fn select<'a>(&mut self,
@@ -320,7 +365,6 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
      * type inference.
      */
 
-    let tcx = selcx.tcx();
     match obligation.predicate {
         ty::Predicate::Trait(ref data) => {
             let trait_obligation = obligation.with(data.clone());
@@ -329,13 +373,13 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                     false
                 }
                 Ok(Some(s)) => {
-                    s.map_move_nested(|p| new_obligations.push(p));
+                    new_obligations.append(&mut s.nested_obligations());
                     true
                 }
                 Err(selection_err) => {
-                    debug!("predicate: {} error: {}",
-                           obligation.repr(tcx),
-                           selection_err.repr(tcx));
+                    debug!("predicate: {:?} error: {:?}",
+                           obligation,
+                           selection_err);
                     errors.push(
                         FulfillmentError::new(
                             obligation.clone(),
@@ -384,7 +428,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                         CodeSelectionError(Unimplemented)));
             } else {
                 let ty::OutlivesPredicate(t_a, r_b) = binder.0;
-                register_region_obligation(tcx, t_a, r_b,
+                register_region_obligation(t_a, r_b,
                                            obligation.cause.clone(),
                                            region_obligations);
             }
@@ -394,12 +438,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         ty::Predicate::Projection(ref data) => {
             let project_obligation = obligation.with(data.clone());
             let result = project::poly_project_and_unify_type(selcx, &project_obligation);
-            debug!("process_predicate: poly_project_and_unify_type({}) returned {}",
-                   project_obligation.repr(tcx),
-                   result.repr(tcx));
+            debug!("process_predicate: poly_project_and_unify_type({:?}) returned {:?}",
+                   project_obligation,
+                   result);
             match result {
                 Ok(Some(obligations)) => {
-                    new_obligations.extend(obligations.into_iter());
+                    new_obligations.extend(obligations);
                     true
                 }
                 Ok(None) => {
@@ -417,16 +461,15 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     }
 }
 
-impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("RegionObligation(sub_region={}, sup_type={})",
-                self.sub_region.repr(tcx),
-                self.sup_type.repr(tcx))
+impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "RegionObligation(sub_region={:?}, sup_type={:?})",
+               self.sub_region,
+               self.sup_type)
     }
 }
 
-fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                    t_a: Ty<'tcx>,
+fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
                                     r_b: ty::Region,
                                     cause: ObligationCause<'tcx>,
                                     region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
@@ -435,10 +478,28 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                sub_region: r_b,
                                                cause: cause };
 
-    debug!("register_region_obligation({})",
-           region_obligation.repr(tcx));
+    debug!("register_region_obligation({:?})",
+           region_obligation);
 
     region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![])
         .push(region_obligation);
 
 }
+
+impl<'tcx> FulfilledPredicates<'tcx> {
+    pub fn new() -> FulfilledPredicates<'tcx> {
+        FulfilledPredicates {
+            set: HashSet::new()
+        }
+    }
+
+    pub fn is_duplicate(&self, p: &ty::Predicate<'tcx>) -> bool {
+        self.set.contains(p)
+    }
+
+    fn is_duplicate_or_add(&mut self, p: &ty::Predicate<'tcx>) -> bool {
+        !self.set.insert(p.clone())
+    }
+}
+
+
index fe61bb5e4ea6f7b0841bf978abd26ba4e6904ccf..e3c122e2f1f59319f6dc3291c0510af5f8a50222 100644 (file)
@@ -20,11 +20,9 @@ use middle::subst;
 use middle::ty::{self, HasProjectionTypes, Ty};
 use middle::ty_fold::TypeFoldable;
 use middle::infer::{self, fixup_err_to_string, InferCtxt};
-use std::slice::Iter;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
-use util::ppaux::Repr;
 
 pub use self::error_reporting::report_fulfillment_errors;
 pub use self::error_reporting::report_overflow_error;
@@ -33,7 +31,7 @@ pub use self::error_reporting::suggest_new_overflow_limit;
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
 pub use self::coherence::OrphanCheckErr;
-pub use self::fulfill::{FulfillmentContext, RegionObligation};
+pub use self::fulfill::{FulfillmentContext, FulfilledPredicates, RegionObligation};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::normalize;
 pub use self::project::Normalized;
@@ -146,9 +144,9 @@ pub struct DerivedObligationCause<'tcx> {
     parent_code: Rc<ObligationCauseCode<'tcx>>
 }
 
-pub type Obligations<'tcx, O> = subst::VecPerParamSpace<Obligation<'tcx, O>>;
-pub type PredicateObligations<'tcx> = subst::VecPerParamSpace<PredicateObligation<'tcx>>;
-pub type TraitObligations<'tcx> = subst::VecPerParamSpace<TraitObligation<'tcx>>;
+pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
+pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
+pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
 
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 
@@ -220,7 +218,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
 /// ### The type parameter `N`
 ///
 /// See explanation on `VtableImplData`.
-#[derive(Debug,Clone)]
+#[derive(Clone)]
 pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
@@ -246,7 +244,7 @@ pub enum Vtable<'tcx, N> {
     /// Vtable automatically generated for a closure. The def ID is the ID
     /// of the closure expression. This is a `VtableImpl` in spirit, but the
     /// impl is generated by the compiler and does not appear in the source.
-    VtableClosure(ast::DefId, subst::Substs<'tcx>),
+    VtableClosure(VtableClosureData<'tcx, N>),
 
     /// Same as above, but for a fn pointer type with the given signature.
     VtableFnPointer(ty::Ty<'tcx>),
@@ -266,18 +264,27 @@ pub enum Vtable<'tcx, N> {
 pub struct VtableImplData<'tcx, N> {
     pub impl_def_id: ast::DefId,
     pub substs: subst::Substs<'tcx>,
-    pub nested: subst::VecPerParamSpace<N>
+    pub nested: Vec<N>
+}
+
+#[derive(Clone, PartialEq, Eq)]
+pub struct VtableClosureData<'tcx, N> {
+    pub closure_def_id: ast::DefId,
+    pub substs: subst::Substs<'tcx>,
+    /// Nested obligations. This can be non-empty if the closure
+    /// signature contains associated types.
+    pub nested: Vec<N>
 }
 
-#[derive(Debug,Clone)]
+#[derive(Clone)]
 pub struct VtableDefaultImplData<N> {
     pub trait_def_id: ast::DefId,
     pub nested: Vec<N>
 }
 
-#[derive(Debug,Clone)]
+#[derive(Clone)]
 pub struct VtableBuiltinData<N> {
-    pub nested: subst::VecPerParamSpace<N>
+    pub nested: Vec<N>
 }
 
 /// A vtable for some object-safe trait `Foo` automatically derived
@@ -292,12 +299,11 @@ pub struct VtableObjectData<'tcx> {
 }
 
 /// Creates predicate obligations from the generic bounds.
-pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                     cause: ObligationCause<'tcx>,
+pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                      generic_bounds: &ty::InstantiatedPredicates<'tcx>)
                                      -> PredicateObligations<'tcx>
 {
-    util::predicates_for_generics(tcx, cause, 0, generic_bounds)
+    util::predicates_for_generics(cause, 0, generic_bounds)
 }
 
 /// Determines whether the type `ty` is known to meet `bound` and
@@ -305,18 +311,18 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
 /// `bound` or is not known to meet bound (note that this is
 /// conservative towards *no impl*, which is the opposite of the
 /// `evaluate` methods).
-pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                                       typer: &ty::ClosureTyper<'tcx>,
-                                       ty: Ty<'tcx>,
-                                       bound: ty::BuiltinBound,
-                                       span: Span)
-                                       -> SelectionResult<'tcx, ()>
+pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                                 typer: &ty::ClosureTyper<'tcx>,
+                                                 ty: Ty<'tcx>,
+                                                 bound: ty::BuiltinBound,
+                                                 span: Span)
+                                                 -> bool
 {
-    debug!("type_known_to_meet_builtin_bound(ty={}, bound={:?})",
-           ty.repr(infcx.tcx),
+    debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})",
+           ty,
            bound);
 
-    let mut fulfill_cx = FulfillmentContext::new();
+    let mut fulfill_cx = FulfillmentContext::new(false);
 
     // We can use a dummy node-id here because we won't pay any mind
     // to region obligations that arise (there shouldn't really be any
@@ -328,61 +334,18 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     // Note: we only assume something is `Copy` if we can
     // *definitively* show that it implements `Copy`. Otherwise,
     // assume it is move; linear is always ok.
-    let result = match fulfill_cx.select_all_or_error(infcx, typer) {
-        Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
-        Err(errors) => {
-            // If there were any hard errors, propagate an arbitrary
-            // one of those. If no hard errors at all, report
-            // ambiguity.
-            let sel_error =
-                errors.iter()
-                      .filter_map(|err| {
-                          match err.code {
-                              CodeAmbiguity => None,
-                              CodeSelectionError(ref e) => Some(e.clone()),
-                              CodeProjectionError(_) => {
-                                  infcx.tcx.sess.span_bug(
-                                      span,
-                                      "projection error while selecting?")
-                              }
-                          }
-                      })
-                      .next();
-            match sel_error {
-                None => { Ok(None) }
-                Some(e) => { Err(e) }
-            }
-        }
-    };
-
-    debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} result={:?}",
-           ty.repr(infcx.tcx),
-           bound,
-           result);
-
-    result
-}
-
-pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                                                 typer: &ty::ClosureTyper<'tcx>,
-                                                 ty: Ty<'tcx>,
-                                                 bound: ty::BuiltinBound,
-                                                 span: Span)
-                                                 -> bool
-{
-    match evaluate_builtin_bound(infcx, typer, ty, bound, span) {
-        Ok(Some(())) => {
-            // definitely impl'd
+    match fulfill_cx.select_all_or_error(infcx, typer) {
+        Ok(()) => {
+            debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
+                   ty,
+                   bound);
             true
         }
-        Ok(None) => {
-            // ambiguous: if coherence check was successful, shouldn't
-            // happen, but we might have reported an error and been
-            // soldering on, so just treat this like not implemented
-            false
-        }
-        Err(_) => {
-            // errors: not implemented.
+        Err(e) => {
+            debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}",
+                   ty,
+                   bound,
+                   e);
             false
         }
     }
@@ -412,12 +375,30 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
     let span = cause.span;
     let body_id = cause.body_id;
 
-    debug!("normalize_param_env_or_error(unnormalized_env={})",
-           unnormalized_env.repr(tcx));
+    debug!("normalize_param_env_or_error(unnormalized_env={:?})",
+           unnormalized_env);
+
+    let predicates: Vec<_> =
+        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.clone())
+        .filter(|p| !p.is_global()) // (*)
+        .collect();
+
+    // (*) Any predicate like `i32: Trait<u32>` or whatever doesn't
+    // need to be in the *environment* to be proven, so screen those
+    // out. This is important for the soundness of inter-fn
+    // caching. Note though that we should probably check that these
+    // predicates hold at the point where the environment is
+    // constructed, but I am not currently doing so out of laziness.
+    // -nmatsakis
+
+    debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
+           predicates);
+
+    let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
 
     let infcx = infer::new_infer_ctxt(tcx);
-    let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
-                                           &unnormalized_env.caller_bounds) {
+    let predicates = match fully_normalize(&infcx, &elaborated_env, cause,
+                                           &elaborated_env.caller_bounds) {
         Ok(predicates) => predicates,
         Err(errors) => {
             report_fulfillment_errors(&infcx, &errors);
@@ -439,14 +420,11 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
             // all things considered.
             let err_msg = fixup_err_to_string(fixup_err);
             tcx.sess.span_err(span, &err_msg);
-            return unnormalized_env; // an unnormalized env is better than nothing
+            return elaborated_env; // an unnormalized env is better than nothing
         }
     };
 
-    debug!("normalize_param_env_or_error: predicates={}",
-           predicates.repr(tcx));
-
-    unnormalized_env.with_caller_bounds(predicates)
+    elaborated_env.with_caller_bounds(predicates)
 }
 
 pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
@@ -454,25 +432,23 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                   cause: ObligationCause<'tcx>,
                                   value: &T)
                                   -> Result<T, Vec<FulfillmentError<'tcx>>>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
-    let tcx = closure_typer.tcx();
-
-    debug!("normalize_param_env(value={})", value.repr(tcx));
+    debug!("normalize_param_env(value={:?})", value);
 
     let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
-    let mut fulfill_cx = FulfillmentContext::new();
+    let mut fulfill_cx = FulfillmentContext::new(false);
     let Normalized { value: normalized_value, obligations } =
         project::normalize(selcx, cause, value);
-    debug!("normalize_param_env: normalized_value={} obligations={}",
-           normalized_value.repr(tcx),
-           obligations.repr(tcx));
+    debug!("normalize_param_env: normalized_value={:?} obligations={:?}",
+           normalized_value,
+           obligations);
     for obligation in obligations {
         fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
     }
     try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
     let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
-    debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
+    debug!("normalize_param_env: resolved_value={:?}", resolved_value);
     Ok(resolved_value)
 }
 
@@ -525,114 +501,39 @@ impl<'tcx> ObligationCause<'tcx> {
 }
 
 impl<'tcx, N> Vtable<'tcx, N> {
-    pub fn iter_nested(&self) -> Iter<N> {
-        match *self {
-            VtableImpl(ref i) => i.iter_nested(),
-            VtableParam(ref n) => n.iter(),
-            VtableBuiltin(ref i) => i.iter_nested(),
-            VtableObject(_) |
-            VtableDefaultImpl(..) | VtableFnPointer(..) |
-            VtableClosure(..) => (&[]).iter(),
-        }
-    }
-
-    pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where
-        F: FnMut(&N) -> M,
-    {
-        match *self {
-            VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
-            VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),
-            VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
-            VtableClosure(d, ref s) => VtableClosure(d, s.clone()),
-            VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
-            VtableObject(ref p) => VtableObject(p.clone()),
-            VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
-        }
-    }
-
-    pub fn map_move_nested<M, F>(self, op: F) -> Vtable<'tcx, M> where
-        F: FnMut(N) -> M,
-    {
+    pub fn nested_obligations(self) -> Vec<N> {
         match self {
-            VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
-            VtableFnPointer(sig) => VtableFnPointer(sig),
-            VtableClosure(d, s) => VtableClosure(d, s),
-            VtableDefaultImpl(t) => VtableDefaultImpl(t.map_move_nested(op)),
-            VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
-            VtableObject(p) => VtableObject(p),
-            VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
-        }
-    }
-}
-
-impl<'tcx, N> VtableImplData<'tcx, N> {
-    pub fn iter_nested(&self) -> Iter<N> {
-        self.nested.iter()
-    }
-
-    pub fn map_nested<M, F>(&self, op: F) -> VtableImplData<'tcx, M> where
-        F: FnMut(&N) -> M,
-    {
-        VtableImplData {
-            impl_def_id: self.impl_def_id,
-            substs: self.substs.clone(),
-            nested: self.nested.map(op)
-        }
-    }
-
-    pub fn map_move_nested<M, F>(self, op: F) -> VtableImplData<'tcx, M> where
-        F: FnMut(N) -> M,
-    {
-        let VtableImplData { impl_def_id, substs, nested } = self;
-        VtableImplData {
-            impl_def_id: impl_def_id,
-            substs: substs,
-            nested: nested.map_move(op)
-        }
-    }
-}
-
-impl<N> VtableDefaultImplData<N> {
-    pub fn iter_nested(&self) -> Iter<N> {
-        self.nested.iter()
-    }
-
-    pub fn map_nested<M, F>(&self, op: F) -> VtableDefaultImplData<M> where
-        F: FnMut(&N) -> M,
-    {
-        VtableDefaultImplData {
-            trait_def_id: self.trait_def_id,
-            nested: self.nested.iter().map(op).collect()
+            VtableImpl(i) => i.nested,
+            VtableParam(n) => n,
+            VtableBuiltin(i) => i.nested,
+            VtableDefaultImpl(d) => d.nested,
+            VtableClosure(c) => c.nested,
+            VtableObject(_) | VtableFnPointer(..) => vec![]
         }
     }
 
-    pub fn map_move_nested<M, F>(self, op: F) -> VtableDefaultImplData<M> where
-        F: FnMut(N) -> M,
-    {
-        let VtableDefaultImplData { trait_def_id, nested } = self;
-        VtableDefaultImplData {
-            trait_def_id: trait_def_id,
-            nested: nested.into_iter().map(op).collect()
-        }
-    }
-}
-
-impl<N> VtableBuiltinData<N> {
-    pub fn iter_nested(&self) -> Iter<N> {
-        self.nested.iter()
-    }
-
-    pub fn map_nested<M, F>(&self, op: F) -> VtableBuiltinData<M> where F: FnMut(&N) -> M {
-        VtableBuiltinData {
-            nested: self.nested.map(op)
-        }
-    }
-
-    pub fn map_move_nested<M, F>(self, op: F) -> VtableBuiltinData<M> where
-        F: FnMut(N) -> M,
-    {
-        VtableBuiltinData {
-            nested: self.nested.map_move(op)
+    pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
+        match self {
+            VtableImpl(i) => VtableImpl(VtableImplData {
+                impl_def_id: i.impl_def_id,
+                substs: i.substs,
+                nested: i.nested.into_iter().map(f).collect()
+            }),
+            VtableParam(n) => VtableParam(n.into_iter().map(f).collect()),
+            VtableBuiltin(i) => VtableBuiltin(VtableBuiltinData {
+                nested: i.nested.into_iter().map(f).collect()
+            }),
+            VtableObject(o) => VtableObject(o),
+            VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData {
+                trait_def_id: d.trait_def_id,
+                nested: d.nested.into_iter().map(f).collect()
+            }),
+            VtableFnPointer(f) => VtableFnPointer(f),
+            VtableClosure(c) => VtableClosure(VtableClosureData {
+                closure_def_id: c.closure_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect()
+            })
         }
     }
 }
index ac3c9dfbb463b3a1d0fba2d88e6aaed6431d8cbc..afb30716c36697b50955d1f5fcb4ec0f4c0fa07c 100644 (file)
@@ -25,8 +25,8 @@ use middle::traits;
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use std::rc::Rc;
 use syntax::ast;
-use util::ppaux::Repr;
 
+#[derive(Debug)]
 pub enum ObjectSafetyViolation<'tcx> {
     /// Self : Sized declared on the trait
     SizedSelf,
@@ -70,7 +70,7 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
         result
     });
 
-    debug!("is_object_safe({}) = {}", trait_def_id.repr(tcx), result);
+    debug!("is_object_safe({:?}) = {}", trait_def_id, result);
 
     result
 }
@@ -80,7 +80,7 @@ pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       -> Vec<ObjectSafetyViolation<'tcx>>
 {
     traits::supertrait_def_ids(tcx, trait_def_id)
-        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id).into_iter())
+        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
         .collect()
 }
 
@@ -111,9 +111,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
         violations.push(ObjectSafetyViolation::SupertraitSelf);
     }
 
-    debug!("object_safety_violations_for_trait(trait_def_id={}) = {}",
-           trait_def_id.repr(tcx),
-           violations.repr(tcx));
+    debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+           trait_def_id,
+           violations);
 
     violations
 }
@@ -308,7 +308,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
     let mut error = false;
     ty::maybe_walk_ty(ty, |ty| {
         match ty.sty {
-            ty::ty_param(ref param_ty) => {
+            ty::TyParam(ref param_ty) => {
                 if param_ty.space == SelfSpace {
                     error = true;
                 }
@@ -316,7 +316,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
                 false // no contained types to walk
             }
 
-            ty::ty_projection(ref data) => {
+            ty::TyProjection(ref data) => {
                 // This is a projected type `<Foo as SomeTrait>::X`.
 
                 // Compute supertraits of current trait lazily.
@@ -352,22 +352,9 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
     error
 }
 
-impl<'tcx> Repr<'tcx> for ObjectSafetyViolation<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            ObjectSafetyViolation::SizedSelf =>
-                format!("SizedSelf"),
-            ObjectSafetyViolation::SupertraitSelf =>
-                format!("SupertraitSelf"),
-            ObjectSafetyViolation::Method(ref m, code) =>
-                format!("Method({},{:?})", m.repr(tcx), code),
-        }
-    }
-}
-
 fn is_self<'tcx>(ty: Ty<'tcx>) -> bool {
     match ty.sty {
-        ty::ty_param(ref data) => data.space == subst::SelfSpace,
+        ty::TyParam(ref data) => data.space == subst::SelfSpace,
         _ => false,
     }
 }
index f6bde80e29875ce2b6df67793adcaaca9ef08a64..3ac58dafa4a7a25807825eb90ad3e5784cd772d5 100644 (file)
@@ -17,18 +17,19 @@ use super::ObligationCause;
 use super::PredicateObligation;
 use super::SelectionContext;
 use super::SelectionError;
+use super::VtableClosureData;
 use super::VtableImplData;
 use super::util;
 
 use middle::infer;
-use middle::subst::{Subst, Substs};
+use middle::subst::Subst;
 use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape,
                  HasProjectionTypes, ToPolyTraitRef, Ty};
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
-use syntax::ast;
 use syntax::parse::token;
 use util::common::FN_OUTPUT_NAME;
-use util::ppaux::Repr;
+
+use std::fmt;
 
 pub type PolyProjectionObligation<'tcx> =
     Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
@@ -40,6 +41,7 @@ pub type ProjectionTyObligation<'tcx> =
     Obligation<'tcx, ty::ProjectionTy<'tcx>>;
 
 /// When attempting to resolve `<T as TraitRef>::Name` ...
+#[derive(Debug)]
 pub enum ProjectionTyError<'tcx> {
     /// ...we found multiple sources of information and couldn't resolve the ambiguity.
     TooManyCandidates,
@@ -53,11 +55,11 @@ pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::type_err<'tcx>
 }
 
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq, Debug)]
 enum ProjectionTyCandidate<'tcx> {
     ParamEnv(ty::PolyProjectionPredicate<'tcx>),
     Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
-    Closure(ast::DefId, Substs<'tcx>),
+    Closure(VtableClosureData<'tcx, PredicateObligation<'tcx>>),
     FnPointer(Ty<'tcx>),
 }
 
@@ -76,8 +78,8 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
     obligation: &PolyProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
-    debug!("poly_project_and_unify_type(obligation={})",
-           obligation.repr(selcx.tcx()));
+    debug!("poly_project_and_unify_type(obligation={:?})",
+           obligation);
 
     let infcx = selcx.infcx();
     infcx.commit_if_ok(|snapshot| {
@@ -109,8 +111,8 @@ fn project_and_unify_type<'cx,'tcx>(
     obligation: &ProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
-    debug!("project_and_unify_type(obligation={})",
-           obligation.repr(selcx.tcx()));
+    debug!("project_and_unify_type(obligation={:?})",
+           obligation);
 
     let Normalized { value: normalized_ty, obligations } =
         match opt_normalize_projection_type(selcx,
@@ -124,9 +126,9 @@ fn project_and_unify_type<'cx,'tcx>(
             }
         };
 
-    debug!("project_and_unify_type: normalized_ty={} obligations={}",
-           normalized_ty.repr(selcx.tcx()),
-           obligations.repr(selcx.tcx()));
+    debug!("project_and_unify_type: normalized_ty={:?} obligations={:?}",
+           normalized_ty,
+           obligations);
 
     let infcx = selcx.infcx();
     let origin = infer::RelateOutputImplTypes(obligation.cause.span);
@@ -138,8 +140,8 @@ fn project_and_unify_type<'cx,'tcx>(
 
 fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext<'cx,'tcx>,
                                                     obligation: &ProjectionObligation<'tcx>) {
-    debug!("consider_unification_despite_ambiguity(obligation={})",
-           obligation.repr(selcx.tcx()));
+    debug!("consider_unification_despite_ambiguity(obligation={:?})",
+           obligation);
 
     let def_id = obligation.predicate.projection_ty.trait_ref.def_id;
     match selcx.tcx().lang_items.fn_trait_kind(def_id) {
@@ -153,7 +155,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
     debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}",
            self_ty.sty);
     match self_ty.sty {
-        ty::ty_closure(closure_def_id, substs) => {
+        ty::TyClosure(closure_def_id, substs) => {
             let closure_typer = selcx.closure_typer();
             let closure_type = closure_typer.closure_type(closure_def_id, substs);
             let ty::Binder((_, ret_type)) =
@@ -162,13 +164,18 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
                                                         self_ty,
                                                         &closure_type.sig,
                                                         util::TupleArgumentsFlag::No);
+            // We don't have to normalize the return type here - this is only
+            // reached for TyClosure: Fn inputs where the closure kind is
+            // still unknown, which should only occur in typeck where the
+            // closure type is already normalized.
             let (ret_type, _) =
                 infcx.replace_late_bound_regions_with_fresh_var(
                     obligation.cause.span,
                     infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name),
                     &ty::Binder(ret_type));
+
             debug!("consider_unification_despite_ambiguity: ret_type={:?}",
-                   ret_type.repr(selcx.tcx()));
+                   ret_type);
             let origin = infer::RelateOutputImplTypes(obligation.cause.span);
             let obligation_ty = obligation.predicate.ty;
             match infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type) {
@@ -188,7 +195,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
                                cause: ObligationCause<'tcx>,
                                value: &T)
                                -> Normalized<'tcx, T>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
     normalize_with_depth(selcx, cause, 0, value)
 }
@@ -199,10 +206,11 @@ pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tc
                                           depth: usize,
                                           value: &T)
                                           -> Normalized<'tcx, T>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
     let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
     let result = normalizer.fold(value);
+
     Normalized {
         value: result,
         obligations: normalizer.obligations,
@@ -230,7 +238,7 @@ impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
         }
     }
 
-    fn fold<T:TypeFoldable<'tcx> + HasProjectionTypes + Clone>(&mut self, value: &T) -> T {
+    fn fold<T:TypeFoldable<'tcx> + HasProjectionTypes>(&mut self, value: &T) -> T {
         let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
 
         if !value.has_projection_types() {
@@ -260,7 +268,7 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
 
         let ty = ty_fold::super_fold_ty(self, ty);
         match ty.sty {
-            ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*)
+            ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
@@ -279,7 +287,7 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
                                               data.clone(),
                                               self.cause.clone(),
                                               self.depth);
-                self.obligations.extend(obligations.into_iter());
+                self.obligations.extend(obligations);
                 ty
             }
 
@@ -348,9 +356,9 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
     -> Option<NormalizedTy<'tcx>>
 {
     debug!("normalize_projection_type(\
-           projection_ty={}, \
+           projection_ty={:?}, \
            depth={})",
-           projection_ty.repr(selcx.tcx()),
+           projection_ty,
            depth);
 
     let obligation = Obligation::with_depth(cause.clone(), depth, projection_ty.clone());
@@ -361,21 +369,20 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
             // an impl, where-clause etc) and hence we must
             // re-normalize it
 
-            debug!("normalize_projection_type: projected_ty={} depth={} obligations={}",
-                   projected_ty.repr(selcx.tcx()),
+            debug!("normalize_projection_type: projected_ty={:?} depth={} obligations={:?}",
+                   projected_ty,
                    depth,
-                   obligations.repr(selcx.tcx()));
+                   obligations);
 
             if ty::type_has_projection(projected_ty) {
-                let tcx = selcx.tcx();
                 let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
                 let normalized_ty = normalizer.fold(&projected_ty);
 
-                debug!("normalize_projection_type: normalized_ty={} depth={}",
-                       normalized_ty.repr(tcx),
+                debug!("normalize_projection_type: normalized_ty={:?} depth={}",
+                       normalized_ty,
                        depth);
 
-                obligations.extend(normalizer.obligations.into_iter());
+                obligations.extend(normalizer.obligations);
                 Some(Normalized {
                     value: normalized_ty,
                     obligations: obligations,
@@ -388,15 +395,19 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
             }
         }
         Ok(ProjectedTy::NoProgress(projected_ty)) => {
+            debug!("normalize_projection_type: projected_ty={:?} no progress",
+                   projected_ty);
             Some(Normalized {
                 value: projected_ty,
                 obligations: vec!()
             })
         }
         Err(ProjectionTyError::TooManyCandidates) => {
+            debug!("normalize_projection_type: too many candidates");
             None
         }
         Err(ProjectionTyError::TraitSelectionError(_)) => {
+            debug!("normalize_projection_type: ERROR");
             // if we got an error processing the `T as Trait` part,
             // just return `ty::err` but add the obligation `T :
             // Trait`, which when processed will cause the error to be
@@ -407,11 +418,11 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
     }
 }
 
-/// in various error cases, we just set ty_err and return an obligation
+/// in various error cases, we just set TyError and return an obligation
 /// that, when fulfilled, will lead to an error.
 ///
-/// FIXME: the ty_err created here can enter the obligation we create,
-/// leading to error messages involving ty_err.
+/// FIXME: the TyError created here can enter the obligation we create,
+/// leading to error messages involving TyError.
 fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                                projection_ty: ty::ProjectionTy<'tcx>,
                                cause: ObligationCause<'tcx>,
@@ -439,8 +450,8 @@ fn project_type<'cx,'tcx>(
     obligation: &ProjectionTyObligation<'tcx>)
     -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>>
 {
-    debug!("project(obligation={})",
-           obligation.repr(selcx.tcx()));
+    debug!("project(obligation={:?})",
+           obligation);
 
     let recursion_limit = selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
@@ -451,7 +462,7 @@ fn project_type<'cx,'tcx>(
     let obligation_trait_ref =
         selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
 
-    debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx()));
+    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
 
     if obligation_trait_ref.references_error() {
         return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!()));
@@ -530,7 +541,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
 {
-    let env_predicates = selcx.param_env().caller_bounds.clone();
+    let env_predicates = selcx.param_env().caller_bounds.iter().cloned();
     assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
                                         candidate_set, env_predicates);
 }
@@ -553,8 +564,8 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
 {
     // Check whether the self-type is itself a projection.
     let trait_ref = match obligation_trait_ref.self_ty().sty {
-        ty::ty_projection(ref data) => data.trait_ref.clone(),
-        ty::ty_infer(ty::TyVar(_)) => {
+        ty::TyProjection(ref data) => data.trait_ref.clone(),
+        ty::TyInfer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
             candidate_set.ambiguous = true;
@@ -566,22 +577,25 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
     // If so, extract what we know from the trait and try to come up with a good answer.
     let trait_predicates = ty::lookup_predicates(selcx.tcx(), trait_ref.def_id);
     let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
+    let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
     assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
-                                        candidate_set, bounds.predicates.into_vec());
+                                        candidate_set, bounds)
 }
 
-fn assemble_candidates_from_predicates<'cx,'tcx>(
+fn assemble_candidates_from_predicates<'cx,'tcx,I>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-    env_predicates: Vec<ty::Predicate<'tcx>>)
+    env_predicates: I)
+    where I: Iterator<Item=ty::Predicate<'tcx>>
 {
-    debug!("assemble_candidates_from_predicates(obligation={}, env_predicates={})",
-           obligation.repr(selcx.tcx()),
-           env_predicates.repr(selcx.tcx()));
+    debug!("assemble_candidates_from_predicates(obligation={:?})",
+           obligation);
     let infcx = selcx.infcx();
-    for predicate in elaborate_predicates(selcx.tcx(), env_predicates) {
+    for predicate in env_predicates {
+        debug!("assemble_candidates_from_predicates: predicate={:?}",
+               predicate);
         match predicate {
             ty::Predicate::Projection(ref data) => {
                 let same_name = data.item_name() == obligation.predicate.item_name;
@@ -598,10 +612,9 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
                                               obligation_poly_trait_ref).is_ok()
                 });
 
-                debug!("assemble_candidates_from_predicates: candidate {} is_match {} same_name {}",
-                       data.repr(selcx.tcx()),
-                       is_match,
-                       same_name);
+                debug!("assemble_candidates_from_predicates: candidate={:?} \
+                                                             is_match={} same_name={}",
+                       data, is_match, same_name);
 
                 if is_match {
                     candidate_set.vec.push(
@@ -620,22 +633,22 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
     object_ty: Ty<'tcx>)
 {
-    let infcx = selcx.infcx();
-    debug!("assemble_candidates_from_object_type(object_ty={})",
-           object_ty.repr(infcx.tcx));
+    debug!("assemble_candidates_from_object_type(object_ty={:?})",
+           object_ty);
     let data = match object_ty.sty {
-        ty::ty_trait(ref data) => data,
+        ty::TyTrait(ref data) => data,
         _ => {
             selcx.tcx().sess.span_bug(
                 obligation.cause.span,
-                &format!("assemble_candidates_from_object_type called with non-object: {}",
-                         object_ty.repr(selcx.tcx())));
+                &format!("assemble_candidates_from_object_type called with non-object: {:?}",
+                         object_ty));
         }
     };
     let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
     let env_predicates = projection_bounds.iter()
                                           .map(|p| p.as_predicate())
                                           .collect();
+    let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
     assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
                                         candidate_set, env_predicates)
 }
@@ -658,16 +671,16 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             return Ok(());
         }
         Err(e) => {
-            debug!("assemble_candidates_from_impls: selection error {}",
-                   e.repr(selcx.tcx()));
+            debug!("assemble_candidates_from_impls: selection error {:?}",
+                   e);
             return Err(e);
         }
     };
 
     match vtable {
         super::VtableImpl(data) => {
-            debug!("assemble_candidates_from_impls: impl candidate {}",
-                   data.repr(selcx.tcx()));
+            debug!("assemble_candidates_from_impls: impl candidate {:?}",
+                   data);
 
             candidate_set.vec.push(
                 ProjectionTyCandidate::Impl(data));
@@ -677,9 +690,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
                 selcx, obligation, obligation_trait_ref, candidate_set,
                 data.object_ty);
         }
-        super::VtableClosure(closure_def_id, substs) => {
+        super::VtableClosure(data) => {
             candidate_set.vec.push(
-                ProjectionTyCandidate::Closure(closure_def_id, substs));
+                ProjectionTyCandidate::Closure(data));
         }
         super::VtableFnPointer(fn_type) => {
             candidate_set.vec.push(
@@ -717,8 +730,8 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             // These traits have no associated types.
             selcx.tcx().sess.span_bug(
                 obligation.cause.span,
-                &format!("Cannot project an associated type from `{}`",
-                         vtable.repr(selcx.tcx())));
+                &format!("Cannot project an associated type from `{:?}`",
+                         vtable));
         }
     }
 
@@ -731,11 +744,9 @@ fn confirm_candidate<'cx,'tcx>(
     candidate: ProjectionTyCandidate<'tcx>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
 {
-    let infcx = selcx.infcx();
-
-    debug!("confirm_candidate(candidate={}, obligation={})",
-           candidate.repr(infcx.tcx),
-           obligation.repr(infcx.tcx));
+    debug!("confirm_candidate(candidate={:?}, obligation={:?})",
+           candidate,
+           obligation);
 
     match candidate {
         ProjectionTyCandidate::ParamEnv(poly_projection) => {
@@ -746,8 +757,8 @@ fn confirm_candidate<'cx,'tcx>(
             confirm_impl_candidate(selcx, obligation, impl_vtable)
         }
 
-        ProjectionTyCandidate::Closure(def_id, substs) => {
-            confirm_closure_candidate(selcx, obligation, def_id, &substs)
+        ProjectionTyCandidate::Closure(closure_vtable) => {
+            confirm_closure_candidate(selcx, obligation, closure_vtable)
         }
 
         ProjectionTyCandidate::FnPointer(fn_type) => {
@@ -770,13 +781,24 @@ fn confirm_fn_pointer_candidate<'cx,'tcx>(
 fn confirm_closure_candidate<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    closure_def_id: ast::DefId,
-    substs: &Substs<'tcx>)
+    vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
 {
     let closure_typer = selcx.closure_typer();
-    let closure_type = closure_typer.closure_type(closure_def_id, substs);
-    confirm_callable_candidate(selcx, obligation, &closure_type.sig, util::TupleArgumentsFlag::No)
+    let closure_type = closure_typer.closure_type(vtable.closure_def_id, &vtable.substs);
+    let Normalized {
+        value: closure_type,
+        mut obligations
+    } = normalize_with_depth(selcx,
+                             obligation.cause.clone(),
+                             obligation.recursion_depth+1,
+                             &closure_type);
+    let (ty, mut cc_obligations) = confirm_callable_candidate(selcx,
+                                                              obligation,
+                                                              &closure_type.sig,
+                                                              util::TupleArgumentsFlag::No);
+    obligations.append(&mut cc_obligations);
+    (ty, obligations)
 }
 
 fn confirm_callable_candidate<'cx,'tcx>(
@@ -788,9 +810,9 @@ fn confirm_callable_candidate<'cx,'tcx>(
 {
     let tcx = selcx.tcx();
 
-    debug!("confirm_closure_candidate({},{})",
-           obligation.repr(tcx),
-           fn_sig.repr(tcx));
+    debug!("confirm_callable_candidate({:?},{:?})",
+           obligation,
+           fn_sig);
 
     // the `Output` associated type is declared on `FnOnce`
     let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap();
@@ -840,10 +862,10 @@ fn confirm_param_env_candidate<'cx,'tcx>(
         Err(e) => {
             selcx.tcx().sess.span_bug(
                 obligation.cause.span,
-                &format!("Failed to unify `{}` and `{}` in projection: {}",
-                         obligation.repr(selcx.tcx()),
-                         projection.repr(selcx.tcx()),
-                         ty::type_err_to_str(selcx.tcx(), &e)));
+                &format!("Failed to unify `{:?}` and `{:?}` in projection: {}",
+                         obligation,
+                         projection,
+                         e));
         }
     }
 
@@ -857,63 +879,41 @@ fn confirm_impl_candidate<'cx,'tcx>(
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
 {
     // there don't seem to be nicer accessors to these:
-    let impl_items_map = selcx.tcx().impl_items.borrow();
     let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
 
-    let impl_items = impl_items_map.get(&impl_vtable.impl_def_id).unwrap();
-    let mut impl_ty = None;
-    for impl_item in impl_items {
-        let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() {
-            ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
-            ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => { continue; }
-        };
-
-        if assoc_type.name != obligation.predicate.item_name {
-            continue;
-        }
-
-        let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
-        impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
-        break;
-    }
-
-    match impl_ty {
-        Some(ty) => (ty, impl_vtable.nested.into_vec()),
-        None => {
-            // This means that the impl is missing a
-            // definition for the associated type. This error
-            // ought to be reported by the type checker method
-            // `check_impl_items_against_trait`, so here we
-            // just return ty_err.
-            (selcx.tcx().types.err, vec!())
+    // Look for the associated type in the impl
+    for impl_item in &selcx.tcx().impl_items.borrow()[&impl_vtable.impl_def_id] {
+        if let ty::TypeTraitItem(ref assoc_ty) = impl_or_trait_items_map[&impl_item.def_id()] {
+            if assoc_ty.name == obligation.predicate.item_name {
+                return (assoc_ty.ty.unwrap().subst(selcx.tcx(), &impl_vtable.substs),
+                        impl_vtable.nested);
+            }
         }
     }
-}
 
-impl<'tcx> Repr<'tcx> for ProjectionTyError<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            ProjectionTyError::TooManyCandidates =>
-                format!("NoCandidate"),
-            ProjectionTyError::TraitSelectionError(ref e) =>
-                format!("TraitSelectionError({})", e.repr(tcx)),
+    // It is not in the impl - get the default from the trait.
+    let trait_ref = obligation.predicate.trait_ref;
+    for trait_item in ty::trait_items(selcx.tcx(), trait_ref.def_id).iter() {
+        if let &ty::TypeTraitItem(ref assoc_ty) = trait_item {
+            if assoc_ty.name == obligation.predicate.item_name {
+                if let Some(ty) = assoc_ty.ty {
+                    return (ty.subst(selcx.tcx(), trait_ref.substs),
+                            impl_vtable.nested);
+                } else {
+                    // This means that the impl is missing a
+                    // definition for the associated type. This error
+                    // ought to be reported by the type checker method
+                    // `check_impl_items_against_trait`, so here we
+                    // just return TyError.
+                    return (selcx.tcx().types.err, vec!());
+                }
+            }
         }
     }
-}
 
-impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            ProjectionTyCandidate::ParamEnv(ref data) =>
-                format!("ParamEnv({})", data.repr(tcx)),
-            ProjectionTyCandidate::Impl(ref data) =>
-                format!("Impl({})", data.repr(tcx)),
-            ProjectionTyCandidate::Closure(ref a, ref b) =>
-                format!("Closure(({},{}))", a.repr(tcx), b.repr(tcx)),
-            ProjectionTyCandidate::FnPointer(a) =>
-                format!("FnPointer(({}))", a.repr(tcx)),
-        }
-    }
+    selcx.tcx().sess.span_bug(obligation.cause.span,
+                              &format!("No associated type for {:?}",
+                                       trait_ref));
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
@@ -925,10 +925,10 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
     }
 }
 
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Normalized<'tcx, T> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Normalized({},{})",
-                self.value.repr(tcx),
-                self.obligations.repr(tcx))
+impl<'tcx, T:fmt::Debug> fmt::Debug for Normalized<'tcx, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Normalized({:?},{:?})",
+               self.value,
+               self.obligations)
     }
 }
index 8011d296263151b23785e570e3e75a02482b0a11..e05eb7148244c84c4ac5864c9c679b359ea1418f 100644 (file)
@@ -31,24 +31,26 @@ use super::Selection;
 use super::SelectionResult;
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
             VtableFnPointer, VtableObject, VtableDefaultImpl};
-use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData};
+use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
+            VtableClosureData, VtableDefaultImplData};
 use super::object_safety;
 use super::util;
 
 use middle::fast_reject;
-use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
+use middle::subst::{Subst, Substs, TypeSpace};
 use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
 use middle::ty_fold::TypeFoldable;
 use middle::ty_match;
 use middle::ty_relate::TypeRelation;
+
 use std::cell::RefCell;
+use std::fmt;
 use std::rc::Rc;
 use syntax::{abi, ast};
 use util::common::ErrorReported;
 use util::nodemap::FnvHashMap;
-use util::ppaux::Repr;
 
 pub struct SelectionContext<'cx, 'tcx:'cx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -297,7 +299,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// type environment by performing unification.
     pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
                   -> SelectionResult<'tcx, Selection<'tcx>> {
-        debug!("select({})", obligation.repr(self.tcx()));
+        debug!("select({:?})", obligation);
         assert!(!obligation.predicate.has_escaping_regions());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
@@ -350,12 +352,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // lifetimes can appear inside the self-type.
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let (closure_def_id, substs) = match self_ty.sty {
-            ty::ty_closure(id, ref substs) => (id, substs.clone()),
+            ty::TyClosure(id, ref substs) => (id, substs.clone()),
             _ => { return; }
         };
         assert!(!substs.has_escaping_regions());
 
-        let closure_trait_ref = self.closure_trait_ref(obligation, closure_def_id, substs);
+        // It is OK to call the unnormalized variant here - this is only
+        // reached for TyClosure: Fn inputs where the closure kind is
+        // still unknown, which should only occur in typeck where the
+        // closure type is already normalized.
+        let closure_trait_ref = self.closure_trait_ref_unnormalized(obligation,
+                                                                    closure_def_id,
+                                                                    substs);
+
         match self.confirm_poly_trait_refs(obligation.cause.clone(),
                                            obligation.predicate.to_poly_trait_ref(),
                                            closure_trait_ref) {
@@ -379,8 +388,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                obligation: &PredicateObligation<'tcx>)
                                -> bool
     {
-        debug!("evaluate_obligation({})",
-               obligation.repr(self.tcx()));
+        debug!("evaluate_obligation({:?})",
+               obligation);
 
         self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
             .may_apply()
@@ -432,8 +441,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                           obligation: &PredicateObligation<'tcx>)
                                            -> EvaluationResult<'tcx>
     {
-        debug!("evaluate_predicate_recursively({})",
-               obligation.repr(self.tcx()));
+        debug!("evaluate_predicate_recursively({:?})",
+               obligation);
+
+        // Check the cache from the tcx of predicates that we know
+        // have been proven elsewhere. This cache only contains
+        // predicates that are global in scope and hence unaffected by
+        // the current environment.
+        if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
+            return EvaluatedToOk;
+        }
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
@@ -483,8 +500,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                            obligation: &TraitObligation<'tcx>)
                                            -> EvaluationResult<'tcx>
     {
-        debug!("evaluate_obligation_recursively({})",
-               obligation.repr(self.tcx()));
+        debug!("evaluate_obligation_recursively({:?})",
+               obligation);
 
         let stack = self.push_stack(previous_stack, obligation);
 
@@ -531,8 +548,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                   |prev| self.match_fresh_trait_refs(&stack.fresh_trait_ref,
                                                      &prev.fresh_trait_ref)))
         {
-            debug!("evaluate_stack({}) --> unbound argument, recursion -->  ambiguous",
-                   stack.fresh_trait_ref.repr(self.tcx()));
+            debug!("evaluate_stack({:?}) --> unbound argument, recursion -->  ambiguous",
+                   stack.fresh_trait_ref);
             return EvaluatedToAmbig;
         }
 
@@ -560,8 +577,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .skip(1) // skip top-most frame
             .any(|prev| stack.fresh_trait_ref == prev.fresh_trait_ref)
         {
-            debug!("evaluate_stack({}) --> recursive",
-                   stack.fresh_trait_ref.repr(self.tcx()));
+            debug!("evaluate_stack({:?}) --> recursive",
+                   stack.fresh_trait_ref);
             return EvaluatedToOk;
         }
 
@@ -579,9 +596,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                          obligation: &TraitObligation<'tcx>)
                          -> bool
     {
-        debug!("evaluate_impl(impl_def_id={}, obligation={})",
-               impl_def_id.repr(self.tcx()),
-               obligation.repr(self.tcx()));
+        debug!("evaluate_impl(impl_def_id={:?}, obligation={:?})",
+               impl_def_id,
+               obligation);
 
         self.infcx.probe(|snapshot| {
             match self.match_impl(impl_def_id, obligation, snapshot) {
@@ -627,16 +644,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // with fresh skolemized types starting from index 0.
         let cache_fresh_trait_pred =
             self.infcx.freshen(stack.obligation.predicate.clone());
-        debug!("candidate_from_obligation(cache_fresh_trait_pred={}, obligation={})",
-               cache_fresh_trait_pred.repr(self.tcx()),
-               stack.repr(self.tcx()));
+        debug!("candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
+               cache_fresh_trait_pred,
+               stack);
         assert!(!stack.obligation.predicate.has_escaping_regions());
 
         match self.check_candidate_cache(&cache_fresh_trait_pred) {
             Some(c) => {
-                debug!("CACHE HIT: cache_fresh_trait_pred={}, candidate={}",
-                       cache_fresh_trait_pred.repr(self.tcx()),
-                       c.repr(self.tcx()));
+                debug!("CACHE HIT: cache_fresh_trait_pred={:?}, candidate={:?}",
+                       cache_fresh_trait_pred,
+                       c);
                 return c;
             }
             None => { }
@@ -646,8 +663,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let candidate = self.candidate_from_obligation_no_cache(stack);
 
         if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
-            debug!("CACHE MISS: cache_fresh_trait_pred={}, candidate={}",
-                   cache_fresh_trait_pred.repr(self.tcx()), candidate.repr(self.tcx()));
+            debug!("CACHE MISS: cache_fresh_trait_pred={:?}, candidate={:?}",
+                   cache_fresh_trait_pred, candidate);
             self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone());
         }
 
@@ -676,10 +693,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let mut candidates = candidate_set.vec;
 
-        debug!("assembled {} candidates for {}: {}",
+        debug!("assembled {} candidates for {:?}: {:?}",
                candidates.len(),
-               stack.repr(self.tcx()),
-               candidates.repr(self.tcx()));
+               stack,
+               candidates);
 
         // At this point, we know that each of the entries in the
         // candidate set is *individually* applicable. Now we have to
@@ -719,12 +736,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     .any(|j| self.candidate_should_be_dropped_in_favor_of(&candidates[i],
                                                                           &candidates[j]));
                 if is_dup {
-                    debug!("Dropping candidate #{}/{}: {}",
-                           i, candidates.len(), candidates[i].repr(self.tcx()));
+                    debug!("Dropping candidate #{}/{}: {:?}",
+                           i, candidates.len(), candidates[i]);
                     candidates.swap_remove(i);
                 } else {
-                    debug!("Retaining candidate #{}/{}: {}",
-                           i, candidates.len(), candidates[i].repr(self.tcx()));
+                    debug!("Retaining candidate #{}/{}: {:?}",
+                           i, candidates.len(), candidates[i]);
                     i += 1;
                 }
             }
@@ -890,8 +907,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
             Some(ty::BoundCopy) => {
-                debug!("obligation self ty is {}",
-                       obligation.predicate.0.self_ty().repr(self.tcx()));
+                debug!("obligation self ty is {:?}",
+                       obligation.predicate.0.self_ty());
 
                 // User-defined copy impls are permitted, but only for
                 // structs and enums.
@@ -941,17 +958,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let poly_trait_predicate =
             self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
 
-        debug!("assemble_candidates_for_projected_tys({},{})",
-               obligation.repr(self.tcx()),
-               poly_trait_predicate.repr(self.tcx()));
+        debug!("assemble_candidates_for_projected_tys({:?},{:?})",
+               obligation,
+               poly_trait_predicate);
 
         // FIXME(#20297) -- just examining the self-type is very simplistic
 
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
         let trait_def_id = match poly_trait_predicate.0.trait_ref.self_ty().sty {
-            ty::ty_projection(ref data) => data.trait_ref.def_id,
-            ty::ty_infer(ty::TyVar(_)) => {
+            ty::TyProjection(ref data) => data.trait_ref.def_id,
+            ty::TyInfer(ty::TyVar(_)) => {
                 // If the self-type is an inference variable, then it MAY wind up
                 // being a projected type, so induce an ambiguity.
                 //
@@ -965,8 +982,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => { return; }
         };
 
-        debug!("assemble_candidates_for_projected_tys: trait_def_id={}",
-               trait_def_id.repr(self.tcx()));
+        debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}",
+               trait_def_id);
 
         let result = self.infcx.probe(|snapshot| {
             self.match_projection_obligation_against_bounds_from_trait(obligation,
@@ -989,29 +1006,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let (skol_trait_predicate, skol_map) =
             self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
         debug!("match_projection_obligation_against_bounds_from_trait: \
-                skol_trait_predicate={} skol_map={}",
-               skol_trait_predicate.repr(self.tcx()),
-               skol_map.repr(self.tcx()));
+                skol_trait_predicate={:?} skol_map={:?}",
+               skol_trait_predicate,
+               skol_map);
 
         let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
-            ty::ty_projection(ref data) => &data.trait_ref,
+            ty::TyProjection(ref data) => &data.trait_ref,
             _ => {
                 self.tcx().sess.span_bug(
                     obligation.cause.span,
                     &format!("match_projection_obligation_against_bounds_from_trait() called \
-                              but self-ty not a projection: {}",
-                             skol_trait_predicate.trait_ref.self_ty().repr(self.tcx())));
+                              but self-ty not a projection: {:?}",
+                             skol_trait_predicate.trait_ref.self_ty()));
             }
         };
         debug!("match_projection_obligation_against_bounds_from_trait: \
-                projection_trait_ref={}",
-               projection_trait_ref.repr(self.tcx()));
+                projection_trait_ref={:?}",
+               projection_trait_ref);
 
         let trait_predicates = ty::lookup_predicates(self.tcx(), projection_trait_ref.def_id);
         let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
         debug!("match_projection_obligation_against_bounds_from_trait: \
-                bounds={}",
-               bounds.repr(self.tcx()));
+                bounds={:?}",
+               bounds);
 
         let matching_bound =
             util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec())
@@ -1025,8 +1042,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                               snapshot)));
 
         debug!("match_projection_obligation_against_bounds_from_trait: \
-                matching_bound={}",
-               matching_bound.repr(self.tcx()));
+                matching_bound={:?}",
+               matching_bound);
         match matching_bound {
             None => false,
             Some(bound) => {
@@ -1072,17 +1089,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                                   candidates: &mut SelectionCandidateSet<'tcx>)
                                                   -> Result<(),SelectionError<'tcx>>
     {
-        debug!("assemble_candidates_from_caller_bounds({})",
-               stack.obligation.repr(self.tcx()));
-
-        let caller_trait_refs: Vec<_> =
-            self.param_env().caller_bounds.iter()
-            .filter_map(|o| o.to_opt_poly_trait_ref())
-            .collect();
+        debug!("assemble_candidates_from_caller_bounds({:?})",
+               stack.obligation);
 
         let all_bounds =
-            util::transitive_bounds(
-                self.tcx(), &caller_trait_refs[..]);
+            self.param_env().caller_bounds
+                            .iter()
+                            .filter_map(|o| o.to_opt_poly_trait_ref());
 
         let matching_bounds =
             all_bounds.filter(
@@ -1134,8 +1147,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // type/region parameters
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let (closure_def_id, substs) = match self_ty.sty {
-            ty::ty_closure(id, ref substs) => (id, substs.clone()),
-            ty::ty_infer(ty::TyVar(_)) => {
+            ty::TyClosure(id, substs) => (id, substs),
+            ty::TyInfer(ty::TyVar(_)) => {
                 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
                 return Ok(());
@@ -1143,16 +1156,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => { return Ok(()); }
         };
 
-        debug!("assemble_unboxed_candidates: self_ty={} kind={:?} obligation={}",
-               self_ty.repr(self.tcx()),
+        debug!("assemble_unboxed_candidates: self_ty={:?} kind={:?} obligation={:?}",
+               self_ty,
                kind,
-               obligation.repr(self.tcx()));
+               obligation);
 
         match self.closure_typer.closure_kind(closure_def_id) {
             Some(closure_kind) => {
                 debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
                 if closure_kind.extends(kind) {
-                    candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone()));
+                    candidates.vec.push(ClosureCandidate(closure_def_id,
+                                                         substs.clone()));
                 }
             }
             None => {
@@ -1178,13 +1192,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // ok to skip binder because what we are inspecting doesn't involve bound regions
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         match self_ty.sty {
-            ty::ty_infer(ty::TyVar(_)) => {
+            ty::TyInfer(ty::TyVar(_)) => {
                 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
 
             // provide an impl, but only for suitable `fn` pointers
-            ty::ty_bare_fn(_, &ty::BareFnTy {
+            ty::TyBareFn(_, &ty::BareFnTy {
                 unsafety: ast::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -1208,7 +1222,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                       candidates: &mut SelectionCandidateSet<'tcx>)
                                       -> Result<(), SelectionError<'tcx>>
     {
-        debug!("assemble_candidates_from_impls(obligation={})", obligation.repr(self.tcx()));
+        debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
 
         let def = ty::lookup_trait_def(self.tcx(), obligation.predicate.def_id());
 
@@ -1234,13 +1248,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         // OK to skip binder here because the tests we do below do not involve bound regions
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        debug!("assemble_candidates_from_default_impls(self_ty={})", self_ty.repr(self.tcx()));
+        debug!("assemble_candidates_from_default_impls(self_ty={:?})", self_ty);
 
         let def_id = obligation.predicate.def_id();
 
         if ty::trait_has_default_impl(self.tcx(), def_id) {
             match self_ty.sty {
-                ty::ty_trait(..) => {
+                ty::TyTrait(..) => {
                     // For object types, we don't know what the closed
                     // over types are. For most traits, this means we
                     // conservatively say nothing; a candidate may be
@@ -1254,8 +1268,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         candidates.vec.push(DefaultImplObjectCandidate(def_id));
                     }
                 }
-                ty::ty_param(..) |
-                ty::ty_projection(..) => {
+                ty::TyParam(..) |
+                ty::TyProjection(..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -1270,7 +1284,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // for an example of a test case that exercises
                     // this path.
                 }
-                ty::ty_infer(ty::TyVar(_)) => {
+                ty::TyInfer(ty::TyVar(_)) => {
                     // the defaulted impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
@@ -1303,8 +1317,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                           obligation: &TraitObligation<'tcx>,
                                           candidates: &mut SelectionCandidateSet<'tcx>)
     {
-        debug!("assemble_candidates_from_object_ty(self_ty={})",
-               self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()).repr(self.tcx()));
+        debug!("assemble_candidates_from_object_ty(self_ty={:?})",
+               self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()));
 
         // Object-safety candidates are only applicable to object-safe
         // traits. Including this check is useful because it helps
@@ -1324,7 +1338,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let (self_ty, _) =
                 self.infcx().skolemize_late_bound_regions(&bound_self_ty, snapshot);
             let poly_trait_ref = match self_ty.sty {
-                ty::ty_trait(ref data) => {
+                ty::TyTrait(ref data) => {
                     match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
                         Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
                             if data.bounds.builtin_bounds.contains(&bound) {
@@ -1339,7 +1353,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                     data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
                 }
-                ty::ty_infer(ty::TyVar(_)) => {
+                ty::TyInfer(ty::TyVar(_)) => {
                     debug!("assemble_candidates_from_object_ty: ambiguous");
                     candidates.ambiguous = true; // could wind up being an object type
                     return Ok(());
@@ -1349,8 +1363,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             };
 
-            debug!("assemble_candidates_from_object_ty: poly_trait_ref={}",
-                   poly_trait_ref.repr(self.tcx()));
+            debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}",
+                   poly_trait_ref);
 
             // see whether the object trait can be upcast to the trait we are looking for
             let upcast_trait_refs = self.upcast(poly_trait_ref, obligation);
@@ -1393,12 +1407,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let source = self.infcx.shallow_resolve(self_ty);
         let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
 
-        debug!("assemble_candidates_for_unsizing(source={}, target={})",
-               source.repr(self.tcx()), target.repr(self.tcx()));
+        debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})",
+               source, target);
 
         let may_apply = match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
+            (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
                 // Upcasts permit two things:
                 //
                 // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
@@ -1415,23 +1429,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // T -> Trait.
-            (_, &ty::ty_trait(_)) => true,
+            (_, &ty::TyTrait(_)) => true,
 
             // Ambiguous handling is below T -> Trait, because inference
             // variables can still implement Unsize<Trait> and nested
             // obligations will have the final say (likely deferred).
-            (&ty::ty_infer(ty::TyVar(_)), _) |
-            (_, &ty::ty_infer(ty::TyVar(_))) => {
+            (&ty::TyInfer(ty::TyVar(_)), _) |
+            (_, &ty::TyInfer(ty::TyVar(_))) => {
                 debug!("assemble_candidates_for_unsizing: ambiguous");
                 candidates.ambiguous = true;
                 false
             }
 
             // [T; n] -> [T].
-            (&ty::ty_vec(_, Some(_)), &ty::ty_vec(_, None)) => true,
+            (&ty::TyArray(_, _), &ty::TySlice(_)) => true,
 
             // Struct<T> -> Struct<U>.
-            (&ty::ty_struct(def_id_a, _), &ty::ty_struct(def_id_b, _)) => {
+            (&ty::TyStruct(def_id_a, _), &ty::TyStruct(def_id_b, _)) => {
                 def_id_a == def_id_b
             }
 
@@ -1460,7 +1474,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             candidate: &SelectionCandidate<'tcx>)
                             -> EvaluationResult<'tcx>
     {
-        debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx()));
+        debug!("winnow_candidate: candidate={:?}", candidate);
         let result = self.infcx.probe(|_| {
             let candidate = (*candidate).clone();
             match self.confirm_candidate(stack.obligation, candidate) {
@@ -1479,7 +1493,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             selection: Selection<'tcx>)
                             -> EvaluationResult<'tcx>
     {
-        self.evaluate_predicates_recursively(stack, selection.iter_nested())
+        self.evaluate_predicates_recursively(stack,
+                                             selection.nested_obligations().iter())
     }
 
     /// Returns true if `candidate_i` should be dropped in favor of
@@ -1551,8 +1566,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         match self.builtin_bound(bound, stack.obligation) {
             Ok(If(..)) => {
-                debug!("builtin_bound: bound={}",
-                       bound.repr(self.tcx()));
+                debug!("builtin_bound: bound={:?}",
+                       bound);
                 candidates.vec.push(BuiltinCandidate(bound));
                 Ok(())
             }
@@ -1577,19 +1592,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
         return match self_ty.sty {
-            ty::ty_infer(ty::IntVar(_)) |
-            ty::ty_infer(ty::FloatVar(_)) |
-            ty::ty_uint(_) |
-            ty::ty_int(_) |
-            ty::ty_bool |
-            ty::ty_float(_) |
-            ty::ty_bare_fn(..) |
-            ty::ty_char => {
+            ty::TyInfer(ty::IntVar(_)) |
+            ty::TyInfer(ty::FloatVar(_)) |
+            ty::TyUint(_) |
+            ty::TyInt(_) |
+            ty::TyBool |
+            ty::TyFloat(_) |
+            ty::TyBareFn(..) |
+            ty::TyChar => {
                 // safe for everything
                 ok_if(Vec::new())
             }
 
-            ty::ty_uniq(_) => {  // Box<T>
+            ty::TyBox(_) => {  // Box<T>
                 match bound {
                     ty::BoundCopy => Err(Unimplemented),
 
@@ -1601,7 +1616,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::ty_ptr(..) => {     // *const T, *mut T
+            ty::TyRawPtr(..) => {     // *const T, *mut T
                 match bound {
                     ty::BoundCopy | ty::BoundSized => ok_if(Vec::new()),
 
@@ -1611,7 +1626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::ty_trait(ref data) => {
+            ty::TyTrait(ref data) => {
                 match bound {
                     ty::BoundSized => Err(Unimplemented),
                     ty::BoundCopy => {
@@ -1639,7 +1654,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => {
+            ty::TyRef(_, ty::mt { ty: _, mutbl }) => {
                 // &mut T or &T
                 match bound {
                     ty::BoundCopy => {
@@ -1660,35 +1675,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::ty_vec(element_ty, ref len) => {
-                // [T, ..n] and [T]
+            ty::TyArray(element_ty, _) => {
+                // [T; n]
                 match bound {
-                    ty::BoundCopy => {
-                        match *len {
-                            // [T, ..n] is copy iff T is copy
-                            Some(_) => ok_if(vec![element_ty]),
-
-                            // [T] is unsized and hence affine
-                            None => Err(Unimplemented),
-                        }
-                    }
-
-                    ty::BoundSized => {
-                        if len.is_some() {
-                            ok_if(Vec::new())
-                        } else {
-                            Err(Unimplemented)
-                        }
-                    }
-
+                    ty::BoundCopy => ok_if(vec![element_ty]),
+                    ty::BoundSized => ok_if(Vec::new()),
                     ty::BoundSync | ty::BoundSend => {
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
 
-            ty::ty_str => {
-                // Equivalent to [u8]
+            ty::TyStr | ty::TySlice(_) => {
                 match bound {
                     ty::BoundSync | ty::BoundSend => {
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
@@ -1699,9 +1697,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-            ty::ty_tup(ref tys) => ok_if(tys.clone()),
+            ty::TyTuple(ref tys) => ok_if(tys.clone()),
 
-            ty::ty_closure(def_id, substs) => {
+            ty::TyClosure(def_id, 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
@@ -1736,7 +1734,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::ty_struct(def_id, substs) => {
+            ty::TyStruct(def_id, substs) => {
                 let types: Vec<Ty> =
                     ty::struct_fields(self.tcx(), def_id, substs).iter()
                                                                  .map(|f| f.mt.ty)
@@ -1744,17 +1742,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 nominal(bound, types)
             }
 
-            ty::ty_enum(def_id, substs) => {
+            ty::TyEnum(def_id, substs) => {
                 let types: Vec<Ty> =
                     ty::substd_enum_variants(self.tcx(), def_id, substs)
                     .iter()
-                    .flat_map(|variant| variant.args.iter())
+                    .flat_map(|variant| &variant.args)
                     .cloned()
                     .collect();
                 nominal(bound, types)
             }
 
-            ty::ty_projection(_) | ty::ty_param(_) => {
+            ty::TyProjection(_) | ty::TyParam(_) => {
                 // Note: A type parameter is only considered to meet a
                 // particular bound if there is a where clause telling
                 // us that it does, and that case is handled by
@@ -1762,7 +1760,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(ParameterBuiltin)
             }
 
-            ty::ty_infer(ty::TyVar(_)) => {
+            ty::TyInfer(ty::TyVar(_)) => {
                 // Unbound type variable. Might or might not have
                 // applicable impls and so forth, depending on what
                 // those type variables wind up being bound to.
@@ -1770,15 +1768,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(AmbiguousBuiltin)
             }
 
-            ty::ty_err => ok_if(Vec::new()),
+            ty::TyError => ok_if(Vec::new()),
 
-            ty::ty_infer(ty::FreshTy(_))
-            | ty::ty_infer(ty::FreshIntTy(_))
-            | ty::ty_infer(ty::FreshFloatTy(_)) => {
+            ty::TyInfer(ty::FreshTy(_))
+            | ty::TyInfer(ty::FreshIntTy(_))
+            | ty::TyInfer(ty::FreshFloatTy(_)) => {
                 self.tcx().sess.bug(
                     &format!(
-                        "asked to assemble builtin bounds of unexpected type: {}",
-                        self_ty.repr(self.tcx())));
+                        "asked to assemble builtin bounds of unexpected type: {:?}",
+                        self_ty));
             }
         };
 
@@ -1818,51 +1816,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// ```
     fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
         match t.sty {
-            ty::ty_uint(_) |
-            ty::ty_int(_) |
-            ty::ty_bool |
-            ty::ty_float(_) |
-            ty::ty_bare_fn(..) |
-            ty::ty_str |
-            ty::ty_err |
-            ty::ty_infer(ty::IntVar(_)) |
-            ty::ty_infer(ty::FloatVar(_)) |
-            ty::ty_char => {
+            ty::TyUint(_) |
+            ty::TyInt(_) |
+            ty::TyBool |
+            ty::TyFloat(_) |
+            ty::TyBareFn(..) |
+            ty::TyStr |
+            ty::TyError |
+            ty::TyInfer(ty::IntVar(_)) |
+            ty::TyInfer(ty::FloatVar(_)) |
+            ty::TyChar => {
                 Some(Vec::new())
             }
 
-            ty::ty_trait(..) |
-            ty::ty_param(..) |
-            ty::ty_projection(..) |
-            ty::ty_infer(ty::TyVar(_)) |
-            ty::ty_infer(ty::FreshTy(_)) |
-            ty::ty_infer(ty::FreshIntTy(_)) |
-            ty::ty_infer(ty::FreshFloatTy(_)) => {
+            ty::TyTrait(..) |
+            ty::TyParam(..) |
+            ty::TyProjection(..) |
+            ty::TyInfer(ty::TyVar(_)) |
+            ty::TyInfer(ty::FreshTy(_)) |
+            ty::TyInfer(ty::FreshIntTy(_)) |
+            ty::TyInfer(ty::FreshFloatTy(_)) => {
                 self.tcx().sess.bug(
                     &format!(
-                        "asked to assemble constituent types of unexpected type: {}",
-                        t.repr(self.tcx())));
+                        "asked to assemble constituent types of unexpected type: {:?}",
+                        t));
             }
 
-            ty::ty_uniq(referent_ty) => {  // Box<T>
+            ty::TyBox(referent_ty) => {  // Box<T>
                 Some(vec![referent_ty])
             }
 
-            ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
-            ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
+            ty::TyRawPtr(ty::mt { ty: element_ty, ..}) |
+            ty::TyRef(_, ty::mt { ty: element_ty, ..}) => {
                 Some(vec![element_ty])
             },
 
-            ty::ty_vec(element_ty, _) => {
+            ty::TyArray(element_ty, _) | ty::TySlice(element_ty) => {
                 Some(vec![element_ty])
             }
 
-            ty::ty_tup(ref tys) => {
+            ty::TyTuple(ref tys) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
                 Some(tys.clone())
             }
 
-            ty::ty_closure(def_id, substs) => {
+            ty::TyClosure(def_id, substs) => {
                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
                 match self.closure_typer.closure_upvars(def_id, substs) {
@@ -1876,22 +1874,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // for `PhantomData<T>`, we pass `T`
-            ty::ty_struct(def_id, substs)
+            ty::TyStruct(def_id, substs)
                 if Some(def_id) == self.tcx().lang_items.phantom_data() =>
             {
                 Some(substs.types.get_slice(TypeSpace).to_vec())
             }
 
-            ty::ty_struct(def_id, substs) => {
+            ty::TyStruct(def_id, substs) => {
                 Some(ty::struct_fields(self.tcx(), def_id, substs).iter()
                      .map(|f| f.mt.ty)
                      .collect())
             }
 
-            ty::ty_enum(def_id, substs) => {
+            ty::TyEnum(def_id, substs) => {
                 Some(ty::substd_enum_variants(self.tcx(), def_id, substs)
                      .iter()
-                     .flat_map(|variant| variant.args.iter())
+                     .flat_map(|variant| &variant.args)
                      .map(|&ty| ty)
                      .collect())
             }
@@ -1958,7 +1956,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Flatten those vectors (couldn't do it above due `collect`)
         match obligations {
-            Ok(obligations) => obligations.into_iter().flat_map(|o| o.into_iter()).collect(),
+            Ok(obligations) => obligations.into_iter().flat_map(|o| o).collect(),
             Err(ErrorReported) => Vec::new(),
         }
     }
@@ -1975,9 +1973,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                          candidate: SelectionCandidate<'tcx>)
                          -> Result<Selection<'tcx>,SelectionError<'tcx>>
     {
-        debug!("confirm_candidate({}, {})",
-               obligation.repr(self.tcx()),
-               candidate.repr(self.tcx()));
+        debug!("confirm_candidate({:?}, {:?})",
+               obligation,
+               candidate);
 
         match candidate {
             BuiltinCandidate(builtin_bound) => {
@@ -1987,7 +1985,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             PhantomFnCandidate |
             ErrorCandidate => {
-                Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() }))
+                Ok(VtableBuiltin(VtableBuiltinData { nested: vec![] }))
             }
 
             ParamCandidate(param) => {
@@ -2012,8 +2010,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ClosureCandidate(closure_def_id, substs) => {
-                try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
-                Ok(VtableClosure(closure_def_id, substs))
+                let vtable_closure =
+                    try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
+                Ok(VtableClosure(vtable_closure))
             }
 
             BuiltinObjectCandidate => {
@@ -2066,9 +2065,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                param: ty::PolyTraitRef<'tcx>)
                                -> Vec<PredicateObligation<'tcx>>
     {
-        debug!("confirm_param_candidate({},{})",
-               obligation.repr(self.tcx()),
-               param.repr(self.tcx()));
+        debug!("confirm_param_candidate({:?},{:?})",
+               obligation,
+               param);
 
         // During evaluation, we already checked that this
         // where-clause trait-ref could be unified with the obligation
@@ -2078,9 +2077,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             Ok(obligations) => obligations,
             Err(()) => {
                 self.tcx().sess.bug(
-                    &format!("Where clause `{}` was applicable to `{}` but now is not",
-                             param.repr(self.tcx()),
-                             obligation.repr(self.tcx())));
+                    &format!("Where clause `{:?}` was applicable to `{:?}` but now is not",
+                             param,
+                             obligation));
             }
         }
     }
@@ -2091,16 +2090,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                  -> Result<VtableBuiltinData<PredicateObligation<'tcx>>,
                                            SelectionError<'tcx>>
     {
-        debug!("confirm_builtin_candidate({})",
-               obligation.repr(self.tcx()));
+        debug!("confirm_builtin_candidate({:?})",
+               obligation);
 
         match try!(self.builtin_bound(bound, obligation)) {
             If(nested) => Ok(self.vtable_builtin_data(obligation, bound, nested)),
             AmbiguousBuiltin | ParameterBuiltin => {
                 self.tcx().sess.span_bug(
                     obligation.cause.span,
-                    &format!("builtin bound for {} was ambig",
-                            obligation.repr(self.tcx())));
+                    &format!("builtin bound for {:?} was ambig",
+                            obligation));
             }
         }
     }
@@ -2120,10 +2119,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let obligations = self.collect_predicates_for_types(obligation, trait_def, nested);
 
-        let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
-
-        debug!("vtable_builtin_data: obligations={}",
-               obligations.repr(self.tcx()));
+        debug!("vtable_builtin_data: obligations={:?}",
+               obligations);
 
         VtableBuiltinData { nested: obligations }
     }
@@ -2138,9 +2135,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                       trait_def_id: ast::DefId)
                                       -> VtableDefaultImplData<PredicateObligation<'tcx>>
     {
-        debug!("confirm_default_impl_candidate({}, {})",
-               obligation.repr(self.tcx()),
-               trait_def_id.repr(self.tcx()));
+        debug!("confirm_default_impl_candidate({:?}, {:?})",
+               obligation,
+               trait_def_id);
 
         // binder is moved below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
@@ -2149,8 +2146,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             None => {
                 self.tcx().sess.bug(
                     &format!(
-                        "asked to confirm default implementation for ambiguous type: {}",
-                        self_ty.repr(self.tcx())));
+                        "asked to confirm default implementation for ambiguous type: {:?}",
+                        self_ty));
             }
         }
     }
@@ -2160,16 +2157,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                              trait_def_id: ast::DefId)
                                              -> VtableDefaultImplData<PredicateObligation<'tcx>>
     {
-        debug!("confirm_default_impl_object_candidate({}, {})",
-               obligation.repr(self.tcx()),
-               trait_def_id.repr(self.tcx()));
+        debug!("confirm_default_impl_object_candidate({:?}, {:?})",
+               obligation,
+               trait_def_id);
 
         assert!(ty::has_attr(self.tcx(), trait_def_id, "rustc_reflect_like"));
 
         // OK to skip binder, it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
         match self_ty.sty {
-            ty::ty_trait(ref data) => {
+            ty::TyTrait(ref data) => {
                 // OK to skip the binder, it is reintroduced below
                 let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace);
                 let assoc_types = data.bounds.projection_bounds
@@ -2188,8 +2185,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => {
                 self.tcx().sess.bug(
                     &format!(
-                        "asked to confirm default object implementation for non-object type: {}",
-                        self_ty.repr(self.tcx())));
+                        "asked to confirm default object implementation for non-object type: {:?}",
+                        self_ty));
             }
         }
     }
@@ -2201,13 +2198,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                            nested: ty::Binder<Vec<Ty<'tcx>>>)
                            -> VtableDefaultImplData<PredicateObligation<'tcx>>
     {
-        debug!("vtable_default_impl_data: nested={}", nested.repr(self.tcx()));
+        debug!("vtable_default_impl_data: nested={:?}", nested);
 
         let mut obligations = self.collect_predicates_for_types(obligation,
                                                                 trait_def_id,
                                                                 nested);
 
-        let trait_obligations: Result<VecPerParamSpace<_>,()> = self.infcx.commit_if_ok(|snapshot| {
+        let trait_obligations: Result<Vec<_>,()> = self.infcx.commit_if_ok(|snapshot| {
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let (trait_ref, skol_map) =
                 self.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot);
@@ -2219,9 +2216,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                               snapshot))
         });
 
-        obligations.extend(trait_obligations.unwrap().into_iter()); // no Errors in that code above
+        // no Errors in that code above
+        obligations.append(&mut trait_obligations.unwrap());
 
-        debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx()));
+        debug!("vtable_default_impl_data: obligations={:?}", obligations);
 
         VtableDefaultImplData {
             trait_def_id: trait_def_id,
@@ -2235,9 +2233,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                               -> Result<VtableImplData<'tcx, PredicateObligation<'tcx>>,
                                         SelectionError<'tcx>>
     {
-        debug!("confirm_impl_candidate({},{})",
-               obligation.repr(self.tcx()),
-               impl_def_id.repr(self.tcx()));
+        debug!("confirm_impl_candidate({:?},{:?})",
+               obligation,
+               impl_def_id);
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
@@ -2245,7 +2243,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let (substs, skol_map) =
                 self.rematch_impl(impl_def_id, obligation,
                                   snapshot);
-            debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
+            debug!("confirm_impl_candidate substs={:?}", substs);
             Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
                                 obligation.recursion_depth + 1, skol_map, snapshot))
         })
@@ -2253,18 +2251,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn vtable_impl(&mut self,
                    impl_def_id: ast::DefId,
-                   substs: Normalized<'tcx, Substs<'tcx>>,
+                   mut substs: Normalized<'tcx, Substs<'tcx>>,
                    cause: ObligationCause<'tcx>,
                    recursion_depth: usize,
                    skol_map: infer::SkolemizationMap,
                    snapshot: &infer::CombinedSnapshot)
                    -> VtableImplData<'tcx, PredicateObligation<'tcx>>
     {
-        debug!("vtable_impl(impl_def_id={}, substs={}, recursion_depth={}, skol_map={})",
-               impl_def_id.repr(self.tcx()),
-               substs.repr(self.tcx()),
+        debug!("vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, skol_map={:?})",
+               impl_def_id,
+               substs,
                recursion_depth,
-               skol_map.repr(self.tcx()));
+               skol_map);
 
         let mut impl_obligations =
             self.impl_or_trait_obligations(cause,
@@ -2274,11 +2272,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                            skol_map,
                                            snapshot);
 
-        debug!("vtable_impl: impl_def_id={} impl_obligations={}",
-               impl_def_id.repr(self.tcx()),
-               impl_obligations.repr(self.tcx()));
+        debug!("vtable_impl: impl_def_id={:?} impl_obligations={:?}",
+               impl_def_id,
+               impl_obligations);
 
-        impl_obligations.extend(TypeSpace, substs.obligations.into_iter());
+        impl_obligations.append(&mut substs.obligations);
 
         VtableImplData { impl_def_id: impl_def_id,
                          substs: substs.value,
@@ -2289,8 +2287,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 obligation: &TraitObligation<'tcx>)
                                 -> VtableObjectData<'tcx>
     {
-        debug!("confirm_object_candidate({})",
-               obligation.repr(self.tcx()));
+        debug!("confirm_object_candidate({:?})",
+               obligation);
 
         // FIXME skipping binder here seems wrong -- we should
         // probably flatten the binder from the obligation and the
@@ -2298,7 +2296,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // case that results. -nmatsakis
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.sty {
-            ty::ty_trait(ref data) => {
+            ty::TyTrait(ref data) => {
                 data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
             }
             _ => {
@@ -2331,8 +2329,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     obligation: &TraitObligation<'tcx>)
                                     -> Result<ty::Ty<'tcx>,SelectionError<'tcx>>
     {
-        debug!("confirm_fn_pointer_candidate({})",
-               obligation.repr(self.tcx()));
+        debug!("confirm_fn_pointer_candidate({:?})",
+               obligation);
 
         // ok to skip binder; it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
@@ -2355,24 +2353,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                  obligation: &TraitObligation<'tcx>,
                                  closure_def_id: ast::DefId,
                                  substs: &Substs<'tcx>)
-                                 -> Result<(),SelectionError<'tcx>>
+                                 -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
+                                           SelectionError<'tcx>>
     {
-        debug!("confirm_closure_candidate({},{},{})",
-               obligation.repr(self.tcx()),
-               closure_def_id.repr(self.tcx()),
-               substs.repr(self.tcx()));
+        debug!("confirm_closure_candidate({:?},{:?},{:?})",
+               obligation,
+               closure_def_id,
+               substs);
 
-        let trait_ref = self.closure_trait_ref(obligation,
-                                               closure_def_id,
-                                               substs);
+        let Normalized {
+            value: trait_ref,
+            obligations
+        } = self.closure_trait_ref(obligation, closure_def_id, substs);
 
-        debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={})",
-               closure_def_id.repr(self.tcx()),
-               trait_ref.repr(self.tcx()));
+        debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
+               closure_def_id,
+               trait_ref,
+               obligations);
 
-        self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                     obligation.predicate.to_poly_trait_ref(),
-                                     trait_ref)
+        try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
+                                          obligation.predicate.to_poly_trait_ref(),
+                                          trait_ref));
+
+        Ok(VtableClosureData {
+            closure_def_id: closure_def_id,
+            substs: substs.clone(),
+            nested: obligations
+        })
     }
 
     /// In the case of closure types and fn pointers,
@@ -2430,18 +2437,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::no_late_bound_regions(tcx, &obligation.self_ty()).unwrap());
         let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
 
-        debug!("confirm_builtin_unsize_candidate(source={}, target={})",
-               source.repr(tcx), target.repr(tcx));
+        debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})",
+               source, target);
 
         let mut nested = vec![];
         match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
+            (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
                 // See assemble_candidates_for_unsizing for more info.
                 let bounds = ty::ExistentialBounds {
                     region_bound: data_b.bounds.region_bound,
                     builtin_bounds: data_b.bounds.builtin_bounds,
                     projection_bounds: data_a.bounds.projection_bounds.clone(),
+                    region_bound_will_change: data_b.bounds.region_bound_will_change,
                 };
 
                 let new_trait = ty::mk_trait(tcx, data_a.principal.clone(), bounds);
@@ -2462,7 +2470,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // T -> Trait.
-            (_, &ty::ty_trait(ref data)) => {
+            (_, &ty::TyTrait(ref data)) => {
                 let object_did = data.principal_def_id();
                 if !object_safety::is_object_safe(tcx, object_did) {
                     return Err(TraitNotObjectSafe(object_did));
@@ -2509,7 +2517,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // [T; n] -> [T].
-            (&ty::ty_vec(a, Some(_)), &ty::ty_vec(b, None)) => {
+            (&ty::TyArray(a, _), &ty::TySlice(b)) => {
                 let origin = infer::Misc(obligation.cause.span);
                 if self.infcx.sub_types(false, origin, a, b).is_err() {
                     return Err(Unimplemented);
@@ -2517,46 +2525,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // Struct<T> -> Struct<U>.
-            (&ty::ty_struct(def_id, substs_a), &ty::ty_struct(_, substs_b)) => {
+            (&ty::TyStruct(def_id, substs_a), &ty::TyStruct(_, substs_b)) => {
                 let fields = ty::lookup_struct_fields(tcx, def_id).iter().map(|f| {
                     ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
                 }).collect::<Vec<_>>();
 
-                // FIXME(#25351) The last field of the structure has to exist and be a
-                // type parameter (for now, to avoid tracking edge cases).
-                let i = if let Some(&ty::ty_param(p)) = fields.last().map(|ty| &ty.sty) {
-                    assert!(p.space == TypeSpace);
-                    p.idx as usize
+                // The last field of the structure has to exist and contain type parameters.
+                let field = if let Some(&field) = fields.last() {
+                    field
                 } else {
                     return Err(Unimplemented);
                 };
+                let mut ty_params = vec![];
+                ty::walk_ty(field, |ty| {
+                    if let ty::TyParam(p) = ty.sty {
+                        assert!(p.space == TypeSpace);
+                        let idx = p.idx as usize;
+                        if !ty_params.contains(&idx) {
+                            ty_params.push(idx);
+                        }
+                    }
+                });
+                if ty_params.is_empty() {
+                    return Err(Unimplemented);
+                }
 
-                // Replace the type parameter chosen for unsizing with
-                // ty_err and ensure it does not affect any other fields.
+                // Replace type parameters used in unsizing with
+                // TyError and ensure they do not affect any other fields.
                 // This could be checked after type collection for any struct
                 // with a potentially unsized trailing field.
                 let mut new_substs = substs_a.clone();
-                new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
+                for &i in &ty_params {
+                    new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
+                }
                 for &ty in fields.init() {
                     if ty::type_is_error(ty.subst(tcx, &new_substs)) {
                         return Err(Unimplemented);
                     }
                 }
 
-                // Extract T and U from Struct<T> and Struct<U>.
-                let inner_source = *substs_a.types.get(TypeSpace, i);
-                let inner_target = *substs_b.types.get(TypeSpace, i);
+                // Extract Field<T> and Field<U> from Struct<T> and Struct<U>.
+                let inner_source = field.subst(tcx, substs_a);
+                let inner_target = field.subst(tcx, substs_b);
 
-                // Check that all the source structure with the unsized
-                // type parameter is a subtype of the target.
-                new_substs.types.get_mut_slice(TypeSpace)[i] = inner_target;
+                // Check that the source structure with the target's
+                // type parameters is a subtype of the target.
+                for &i in &ty_params {
+                    let param_b = *substs_b.types.get(TypeSpace, i);
+                    new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
+                }
                 let new_struct = ty::mk_struct(tcx, def_id, tcx.mk_substs(new_substs));
                 let origin = infer::Misc(obligation.cause.span);
                 if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
                     return Err(Unimplemented);
                 }
 
-                // Construct the nested T: Unsize<U> predicate.
+                // Construct the nested Field<T>: Unsize<Field<U>> predicate.
                 nested.push(util::predicate_for_trait_def(tcx,
                     obligation.cause.clone(),
                     obligation.predicate.def_id(),
@@ -2568,9 +2592,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => unreachable!()
         };
 
-        Ok(VtableBuiltinData {
-            nested: VecPerParamSpace::new(nested, vec![], vec![])
-        })
+        Ok(VtableBuiltinData { nested: nested })
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -2593,9 +2615,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             Ok((substs, skol_map)) => (substs, skol_map),
             Err(()) => {
                 self.tcx().sess.bug(
-                    &format!("Impl {} was matchable against {} but now is not",
-                            impl_def_id.repr(self.tcx()),
-                            obligation.repr(self.tcx())));
+                    &format!("Impl {:?} was matchable against {:?} but now is not",
+                            impl_def_id,
+                            obligation));
             }
         }
     }
@@ -2634,30 +2656,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                           obligation.recursion_depth + 1,
                                           &impl_trait_ref);
 
-        debug!("match_impl(impl_def_id={}, obligation={}, \
-               impl_trait_ref={}, skol_obligation_trait_ref={})",
-               impl_def_id.repr(self.tcx()),
-               obligation.repr(self.tcx()),
-               impl_trait_ref.repr(self.tcx()),
-               skol_obligation_trait_ref.repr(self.tcx()));
+        debug!("match_impl(impl_def_id={:?}, obligation={:?}, \
+               impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
+               impl_def_id,
+               obligation,
+               impl_trait_ref,
+               skol_obligation_trait_ref);
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
         if let Err(e) = self.infcx.sub_trait_refs(false,
                                                   origin,
                                                   impl_trait_ref.value.clone(),
                                                   skol_obligation_trait_ref) {
-            debug!("match_impl: failed sub_trait_refs due to `{}`",
-                   ty::type_err_to_str(self.tcx(), &e));
+            debug!("match_impl: failed sub_trait_refs due to `{}`", e);
             return Err(());
         }
 
         if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
-            debug!("match_impl: failed leak check due to `{}`",
-                   ty::type_err_to_str(self.tcx(), &e));
+            debug!("match_impl: failed leak check due to `{}`", e);
             return Err(());
         }
 
-        debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
+        debug!("match_impl: success impl_substs={:?}", impl_substs);
         Ok((Normalized {
             value: impl_substs,
             obligations: impl_trait_ref.obligations
@@ -2674,7 +2694,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // simplified, do not match.
 
         obligation.predicate.0.input_types().iter()
-            .zip(impl_trait_ref.input_types().iter())
+            .zip(impl_trait_ref.input_types())
             .any(|(&obligation_ty, &impl_ty)| {
                 let simplified_obligation_ty =
                     fast_reject::simplify_type(self.tcx(), obligation_ty, true);
@@ -2708,9 +2728,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             poly_trait_ref: ty::PolyTraitRef<'tcx>)
                             -> Result<(),()>
     {
-        debug!("match_poly_trait_ref: obligation={} poly_trait_ref={}",
-               obligation.repr(self.tcx()),
-               poly_trait_ref.repr(self.tcx()));
+        debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
+               obligation,
+               poly_trait_ref);
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
         match self.infcx.sub_poly_trait_refs(false,
@@ -2749,15 +2769,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let impl_self_ty = ty::lookup_item_type(self.tcx(), impl_def_id).ty;
         let impl_self_ty = impl_self_ty.subst(self.tcx(), &impl_substs);
 
-        debug!("match_impl_self_types(obligation_self_ty={}, impl_self_ty={})",
-               obligation_self_ty.repr(self.tcx()),
-               impl_self_ty.repr(self.tcx()));
+        debug!("match_impl_self_types(obligation_self_ty={:?}, impl_self_ty={:?})",
+               obligation_self_ty,
+               impl_self_ty);
 
         match self.match_self_types(obligation_cause,
                                     impl_self_ty,
                                     obligation_self_ty) {
             Ok(()) => {
-                debug!("Matched impl_substs={}", impl_substs.repr(self.tcx()));
+                debug!("Matched impl_substs={:?}", impl_substs);
                 Ok(impl_substs)
             }
             Err(()) => {
@@ -2817,11 +2837,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    fn closure_trait_ref(&self,
-                         obligation: &TraitObligation<'tcx>,
-                         closure_def_id: ast::DefId,
-                         substs: &Substs<'tcx>)
-                         -> ty::PolyTraitRef<'tcx>
+    fn closure_trait_ref_unnormalized(&mut self,
+                                      obligation: &TraitObligation<'tcx>,
+                                      closure_def_id: ast::DefId,
+                                      substs: &Substs<'tcx>)
+                                      -> ty::PolyTraitRef<'tcx>
     {
         let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
         let ty::Binder((trait_ref, _)) =
@@ -2830,7 +2850,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                                     obligation.predicate.0.self_ty(), // (1)
                                                     &closure_type.sig,
                                                     util::TupleArgumentsFlag::No);
-
         // (1) Feels icky to skip the binder here, but OTOH we know
         // that the self-type is an unboxed closure type and hence is
         // in fact unparameterized (or at least does not reference any
@@ -2840,6 +2859,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         ty::Binder(trait_ref)
     }
 
+    fn closure_trait_ref(&mut self,
+                         obligation: &TraitObligation<'tcx>,
+                         closure_def_id: ast::DefId,
+                         substs: &Substs<'tcx>)
+                         -> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
+    {
+        let trait_ref = self.closure_trait_ref_unnormalized(
+            obligation, closure_def_id, substs);
+
+        // A closure signature can contain associated types which
+        // must be normalized.
+        normalize_with_depth(self,
+                             obligation.cause.clone(),
+                             obligation.recursion_depth+1,
+                             &trait_ref)
+    }
+
     /// Returns the obligations that are implied by instantiating an
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
@@ -2851,20 +2887,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                  substs: &Substs<'tcx>, // for impl or trait
                                  skol_map: infer::SkolemizationMap,
                                  snapshot: &infer::CombinedSnapshot)
-                                 -> VecPerParamSpace<PredicateObligation<'tcx>>
+                                 -> Vec<PredicateObligation<'tcx>>
     {
-        debug!("impl_or_trait_obligations(def_id={})", def_id.repr(self.tcx()));
+        debug!("impl_or_trait_obligations(def_id={:?})", def_id);
 
         let predicates = ty::lookup_predicates(self.tcx(), def_id);
         let predicates = predicates.instantiate(self.tcx(), substs);
         let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates);
-        let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
+        let mut predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
         let mut obligations =
-            util::predicates_for_generics(self.tcx(),
-                                          cause,
+            util::predicates_for_generics(cause,
                                           recursion_depth,
                                           &predicates.value);
-        obligations.extend(TypeSpace, predicates.obligations.into_iter());
+        obligations.append(&mut predicates.obligations);
         obligations
     }
 
@@ -2904,9 +2939,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn upcast(&mut self, obj_trait_ref: ty::PolyTraitRef<'tcx>, obligation: &TraitObligation<'tcx>)
               -> Vec<ty::PolyTraitRef<'tcx>>
     {
-        debug!("upcast(obj_trait_ref={}, obligation={})",
-               obj_trait_ref.repr(self.tcx()),
-               obligation.repr(self.tcx()));
+        debug!("upcast(obj_trait_ref={:?}, obligation={:?})",
+               obj_trait_ref,
+               obligation);
 
         let obligation_def_id = obligation.predicate.def_id();
         let mut upcast_trait_refs = util::upcast(self.tcx(), obj_trait_ref, obligation_def_id);
@@ -2922,33 +2957,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             self.infcx.probe(|_| self.match_poly_trait_ref(obligation, upcast_trait_ref)).is_ok()
         });
 
-        debug!("upcast: upcast_trait_refs={}", upcast_trait_refs.repr(self.tcx()));
+        debug!("upcast: upcast_trait_refs={:?}", upcast_trait_refs);
         upcast_trait_refs
     }
 }
 
-impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            PhantomFnCandidate => format!("PhantomFnCandidate"),
-            ErrorCandidate => format!("ErrorCandidate"),
-            BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
-            BuiltinObjectCandidate => format!("BuiltinObjectCandidate"),
-            BuiltinUnsizeCandidate => format!("BuiltinUnsizeCandidate"),
-            ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
-            ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
-            DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
-            DefaultImplObjectCandidate(t) => format!("DefaultImplObjectCandidate({:?})", t),
-            ProjectionCandidate => format!("ProjectionCandidate"),
-            FnPointerCandidate => format!("FnPointerCandidate"),
-            ObjectCandidate => format!("ObjectCandidate"),
-            ClosureCandidate(c, ref s) => {
-                format!("ClosureCandidate({:?},{})", c, s.repr(tcx))
-            }
-        }
-    }
-}
-
 impl<'tcx> SelectionCache<'tcx> {
     pub fn new() -> SelectionCache<'tcx> {
         SelectionCache {
@@ -2996,10 +3009,9 @@ impl<'o,'tcx> Iterator for TraitObligationStackList<'o,'tcx>{
     }
 }
 
-impl<'o,'tcx> Repr<'tcx> for TraitObligationStack<'o,'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("TraitObligationStack({})",
-                self.obligation.repr(tcx))
+impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TraitObligationStack({:?})", self.obligation)
     }
 }
 
index f30f8560b9fe1627185e3a318c4993e1c0477a2f..54bcd9d7e66abc792ed9ea848779661b45d32895 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::subst::{Substs, VecPerParamSpace};
+use middle::subst::Substs;
 use middle::infer::InferCtxt;
 use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef};
 use std::fmt;
@@ -16,7 +16,6 @@ use syntax::ast;
 use syntax::codemap::Span;
 use util::common::ErrorReported;
 use util::nodemap::FnvHashSet;
-use util::ppaux::Repr;
 
 use super::{Obligation, ObligationCause, PredicateObligation,
             VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData};
@@ -125,8 +124,8 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
                               .map(|p| p.subst_supertrait(self.tcx, &data.to_poly_trait_ref()))
                               .collect();
 
-                debug!("super_predicates: data={} predicates={}",
-                       data.repr(self.tcx), predicates.repr(self.tcx));
+                debug!("super_predicates: data={:?} predicates={:?}",
+                       data, predicates);
 
                 // Only keep those bounds that we haven't already
                 // seen.  This is necessary to prevent infinite
@@ -135,7 +134,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
                 // Sized { }`.
                 predicates.retain(|r| self.visited.insert(r));
 
-                self.stack.extend(predicates.into_iter());
+                self.stack.extend(predicates);
             }
             ty::Predicate::Equate(..) => {
                 // Currently, we do not "elaborate" predicates like
@@ -302,33 +301,20 @@ pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     infcx.fresh_substs_for_generics(span, &impl_generics)
 }
 
-impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableImpl({:?})", self.impl_def_id)
-    }
-}
-
-impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableObject(...)")
-    }
-}
-
 /// See `super::obligations_for_generics`
-pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                     cause: ObligationCause<'tcx>,
+pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                      recursion_depth: usize,
                                      generic_bounds: &ty::InstantiatedPredicates<'tcx>)
-                                     -> VecPerParamSpace<PredicateObligation<'tcx>>
+                                     -> Vec<PredicateObligation<'tcx>>
 {
-    debug!("predicates_for_generics(generic_bounds={})",
-           generic_bounds.repr(tcx));
+    debug!("predicates_for_generics(generic_bounds={:?})",
+           generic_bounds);
 
-    generic_bounds.predicates.map(|predicate| {
+    generic_bounds.predicates.iter().map(|predicate| {
         Obligation { cause: cause.clone(),
                      recursion_depth: recursion_depth,
                      predicate: predicate.clone() }
-    })
+    }).collect()
 }
 
 pub fn trait_ref_for_builtin_bound<'tcx>(
@@ -431,7 +417,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
 
         let trait_items = ty::trait_items(tcx, bound_ref.def_id());
-        for trait_item in &**trait_items {
+        for trait_item in trait_items.iter() {
             match *trait_item {
                 ty::MethodTraitItem(_) => method_count += 1,
                 _ => {}
@@ -480,111 +466,84 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
     ty::Binder((trait_ref, sig.0.output.unwrap_or(ty::mk_nil(tcx))))
 }
 
-impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Obligation(predicate={},depth={})",
-                self.predicate.repr(tcx),
-                self.recursion_depth)
+impl<'tcx,O:fmt::Debug> fmt::Debug for super::Obligation<'tcx, O> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Obligation(predicate={:?},depth={})",
+               self.predicate,
+               self.recursion_depth)
     }
 }
 
-impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx, N:fmt::Debug> fmt::Debug for super::Vtable<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             super::VtableImpl(ref v) =>
-                v.repr(tcx),
+                write!(f, "{:?}", v),
 
             super::VtableDefaultImpl(ref t) =>
-                t.repr(tcx),
+                write!(f, "{:?}", t),
 
-            super::VtableClosure(ref d, ref s) =>
-                format!("VtableClosure({},{})",
-                        d.repr(tcx),
-                        s.repr(tcx)),
+            super::VtableClosure(ref d) =>
+                write!(f, "{:?}", d),
 
             super::VtableFnPointer(ref d) =>
-                format!("VtableFnPointer({})",
-                        d.repr(tcx)),
+                write!(f, "VtableFnPointer({:?})", d),
 
             super::VtableObject(ref d) =>
-                format!("VtableObject({})",
-                        d.repr(tcx)),
+                write!(f, "VtableObject({:?})", d),
 
             super::VtableParam(ref n) =>
-                format!("VtableParam({})",
-                        n.repr(tcx)),
+                write!(f, "VtableParam({:?})", n),
 
             super::VtableBuiltin(ref d) =>
-                d.repr(tcx)
+                write!(f, "{:?}", d)
         }
     }
 }
 
-impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableImplData<'tcx, N> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("VtableImpl(impl_def_id={}, substs={}, nested={})",
-                self.impl_def_id.repr(tcx),
-                self.substs.repr(tcx),
-                self.nested.repr(tcx))
-    }
-}
-
-impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("VtableBuiltin(nested={})",
-                self.nested.repr(tcx))
+impl<'tcx, N:fmt::Debug> fmt::Debug for super::VtableImplData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableImpl(impl_def_id={:?}, substs={:?}, nested={:?})",
+               self.impl_def_id,
+               self.substs,
+               self.nested)
     }
 }
 
-impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData<N> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("VtableDefaultImplData(trait_def_id={}, nested={})",
-                self.trait_def_id.repr(tcx),
-                self.nested.repr(tcx))
+impl<'tcx, N:fmt::Debug> fmt::Debug for super::VtableClosureData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableClosure(closure_def_id={:?}, substs={:?}, nested={:?})",
+               self.closure_def_id,
+               self.substs,
+               self.nested)
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("VtableObject(object_ty={})",
-                self.object_ty.repr(tcx))
+impl<'tcx, N:fmt::Debug> fmt::Debug for super::VtableBuiltinData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableBuiltin(nested={:?})", self.nested)
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            super::Unimplemented =>
-                format!("Unimplemented"),
-
-            super::OutputTypeParameterMismatch(ref a, ref b, ref c) =>
-                format!("OutputTypeParameterMismatch({},{},{})",
-                        a.repr(tcx),
-                        b.repr(tcx),
-                        c.repr(tcx)),
-
-            super::TraitNotObjectSafe(ref tr) =>
-                format!("TraitNotObjectSafe({})",
-                        tr.repr(tcx))
-        }
+impl<'tcx, N:fmt::Debug> fmt::Debug for super::VtableDefaultImplData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableDefaultImplData(trait_def_id={:?}, nested={:?})",
+               self.trait_def_id,
+               self.nested)
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::FulfillmentError<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("FulfillmentError({},{})",
-                self.obligation.repr(tcx),
-                self.code.repr(tcx))
+impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableObject(object_ty={:?})", self.object_ty)
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            super::CodeSelectionError(ref o) => o.repr(tcx),
-            super::CodeProjectionError(ref o) => o.repr(tcx),
-            super::CodeAmbiguity => format!("Ambiguity")
-        }
+impl<'tcx> fmt::Debug for super::FulfillmentError<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "FulfillmentError({:?},{:?})",
+               self.obligation,
+               self.code)
     }
 }
 
@@ -598,14 +557,8 @@ impl<'tcx> fmt::Debug for super::FulfillmentErrorCode<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        self.err.repr(tcx)
-    }
-}
-
 impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "MismatchedProjectionTypes(..)")
+        write!(f, "MismatchedProjectionTypes({:?})", self.err)
     }
 }
index e988423ac5774bbb177bcdc820a210826a81bf3e..dcf360571085436f69c188afee306c47a6b3c2e2 100644 (file)
@@ -12,7 +12,6 @@
 
 pub use self::terr_vstore_kind::*;
 pub use self::type_err::*;
-pub use self::BuiltinBound::*;
 pub use self::InferTy::*;
 pub use self::InferRegion::*;
 pub use self::ImplOrTraitItemId::*;
@@ -21,7 +20,6 @@ pub use self::Variance::*;
 pub use self::AutoAdjustment::*;
 pub use self::Representability::*;
 pub use self::AutoRef::*;
-pub use self::ExprKind::*;
 pub use self::DtorKind::*;
 pub use self::ExplicitSelfCategory::*;
 pub use self::FnOutput::*;
@@ -30,23 +28,30 @@ pub use self::ImplOrTraitItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::ImplOrTraitItem::*;
 pub use self::BoundRegion::*;
-pub use self::sty::*;
+pub use self::TypeVariants::*;
 pub use self::IntVarValue::*;
-pub use self::vtable_origin::*;
 pub use self::MethodOrigin::*;
 pub use self::CopyImplementationError::*;
 
+pub use self::BuiltinBound::Send as BoundSend;
+pub use self::BuiltinBound::Sized as BoundSized;
+pub use self::BuiltinBound::Copy as BoundCopy;
+pub use self::BuiltinBound::Sync as BoundSync;
+
+use ast_map::{self, LinkedPath};
 use back::svh::Svh;
 use session::Session;
 use lint;
 use metadata::csearch;
 use middle;
+use middle::cast;
 use middle::check_const;
-use middle::const_eval;
+use middle::const_eval::{self, ConstVal};
 use middle::def::{self, DefMap, ExportMap};
 use middle::dependency_format;
 use middle::fast_reject;
 use middle::free_region::FreeRegionMap;
+use middle::infer::error_reporting::note_and_explain_region;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::mem_categorization as mc;
 use middle::region;
@@ -60,9 +65,6 @@ use middle::traits;
 use middle::ty;
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
 use middle::ty_walk::{self, TypeWalker};
-use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
-use util::ppaux::ty_to_string;
-use util::ppaux::{Repr, UserString};
 use util::common::{memoized, ErrorReported};
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
 use util::nodemap::FnvHashMap;
@@ -78,20 +80,19 @@ use std::mem;
 use std::ops;
 use std::rc::Rc;
 use std::vec::IntoIter;
-use collections::enum_set::{EnumSet, CLike};
+use collections::enum_set::{self, EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
 use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
-use syntax::ast_util::{self, is_local, lit_is_str, local_def};
+use syntax::ast_util::{self, is_local, local_def};
 use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 use syntax::codemap::Span;
 use syntax::parse::token::{self, InternedString, special_idents};
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::ast;
-use syntax::ast_map::{self, LinkedPath};
 
 pub type Disr = u64;
 
@@ -101,11 +102,10 @@ 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<'tcx> {
+pub struct CrateAnalysis {
     pub export_map: ExportMap,
     pub exported_items: middle::privacy::ExportedItems,
     pub public_items: middle::privacy::PublicItems,
-    pub ty_cx: ty::ctxt<'tcx>,
     pub reachable: NodeSet,
     pub name: String,
     pub glob_map: Option<GlobMap>,
@@ -132,11 +132,11 @@ impl ImplOrTraitItemContainer {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub enum ImplOrTraitItem<'tcx> {
     ConstTraitItem(Rc<AssociatedConst<'tcx>>),
     MethodTraitItem(Rc<Method<'tcx>>),
-    TypeTraitItem(Rc<AssociatedType>),
+    TypeTraitItem(Rc<AssociatedType<'tcx>>),
 }
 
 impl<'tcx> ImplOrTraitItem<'tcx> {
@@ -267,8 +267,9 @@ pub struct AssociatedConst<'tcx> {
 }
 
 #[derive(Clone, Copy, Debug)]
-pub struct AssociatedType {
+pub struct AssociatedType<'tcx> {
     pub name: ast::Name,
+    pub ty: Option<Ty<'tcx>>,
     pub vis: ast::Visibility,
     pub def_id: ast::DefId,
     pub container: ImplOrTraitItemContainer,
@@ -288,22 +289,13 @@ pub struct field_ty {
     pub origin: ast::DefId,  // The DefId of the struct in which the field is declared.
 }
 
-// Contains information needed to resolve types and (in the future) look up
-// the types of AST nodes.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct creader_cache_key {
-    pub cnum: CrateNum,
-    pub pos: usize,
-    pub len: usize
-}
-
 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
 pub struct ItemVariances {
     pub types: VecPerParamSpace<Variance>,
     pub regions: VecPerParamSpace<Variance>,
 }
 
-#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug, Copy)]
+#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
 pub enum Variance {
     Covariant,      // T<A> <: T<B> iff A <: B -- e.g., function return type
     Invariant,      // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@@ -311,7 +303,7 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone)]
 pub enum AutoAdjustment<'tcx> {
     AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
     AdjustUnsafeFnPointer,  // go from a safe fn pointer to an unsafe fn pointer
@@ -380,7 +372,7 @@ pub enum AutoAdjustment<'tcx> {
 ///     unsize: Some(Box<[i32]>),
 /// }
 /// ```
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone)]
 pub struct AutoDerefRef<'tcx> {
     /// Step 1. Apply a number of dereferences, producing an lvalue.
     pub autoderefs: usize,
@@ -410,13 +402,7 @@ pub enum CustomCoerceUnsized {
     Struct(usize)
 }
 
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Debug)]
-pub struct param_index {
-    pub space: subst::ParamSpace,
-    pub index: usize
-}
-
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub enum MethodOrigin<'tcx> {
     // fully statically resolved method
     MethodStatic(ast::DefId),
@@ -434,7 +420,7 @@ pub enum MethodOrigin<'tcx> {
 
 // details for a method invoked with a receiver whose type is a type parameter
 // with a bounded trait.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct MethodParam<'tcx> {
     // the precise trait reference that occurs as a bound -- this may
     // be a supertrait of what the user actually typed. Note that it
@@ -455,7 +441,7 @@ pub struct MethodParam<'tcx> {
 }
 
 // details for a method invoked with a receiver whose type is an object
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct MethodObject<'tcx> {
     // the (super)trait containing the method to be invoked
     pub trait_ref: TraitRef<'tcx>,
@@ -518,50 +504,15 @@ impl MethodCall {
 // of the method to be invoked
 pub type MethodMap<'tcx> = RefCell<FnvHashMap<MethodCall, MethodCallee<'tcx>>>;
 
-pub type vtable_param_res<'tcx> = Vec<vtable_origin<'tcx>>;
-
-// Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res<'tcx> = VecPerParamSpace<vtable_param_res<'tcx>>;
-
-#[derive(Clone)]
-pub enum vtable_origin<'tcx> {
-    /*
-      Statically known vtable. def_id gives the impl item
-      from whence comes the vtable, and tys are the type substs.
-      vtable_res is the vtable itself.
-     */
-    vtable_static(ast::DefId, subst::Substs<'tcx>, vtable_res<'tcx>),
-
-    /*
-      Dynamic vtable, comes from a parameter that has a bound on it:
-      fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
-      vtable_param origin
-
-      The first argument is the param index (identifying T in the example),
-      and the second is the bound number (identifying baz)
-     */
-    vtable_param(param_index, usize),
-
-    /*
-      Vtable automatically generated for a closure. The def ID is the
-      ID of the closure expression.
-     */
-    vtable_closure(ast::DefId),
-
-    /*
-      Asked to determine the vtable for ty_err. This is the value used
-      for the vtables of `Self` in a virtual call like `foo.bar()`
-      where `foo` is of object type. The same value is also used when
-      type errors occur.
-     */
-    vtable_error,
+// Contains information needed to resolve types and (in the future) look up
+// the types of AST nodes.
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct creader_cache_key {
+    pub cnum: CrateNum,
+    pub pos: usize,
+    pub len: usize
 }
 
-
-// For every explicit cast into an object type, maps from the cast
-// expr to the associated trait ref.
-pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;
-
 /// A restriction that certain types must be the same size. The use of
 /// `transmute` gives rise to these restrictions. These generally
 /// cannot be checked until trans; therefore, each call to `transmute`
@@ -600,9 +551,10 @@ pub struct CtxtArenas<'tcx> {
     substs: TypedArena<Substs<'tcx>>,
     bare_fn: TypedArena<BareFnTy<'tcx>>,
     region: TypedArena<Region>,
+    stability: TypedArena<attr::Stability>,
 
     // references
-    trait_defs: TypedArena<TraitDef<'tcx>>
+    trait_defs: TypedArena<TraitDef<'tcx>>,
 }
 
 impl<'tcx> CtxtArenas<'tcx> {
@@ -612,6 +564,7 @@ impl<'tcx> CtxtArenas<'tcx> {
             substs: TypedArena::new(),
             bare_fn: TypedArena::new(),
             region: TypedArena::new(),
+            stability: TypedArena::new(),
 
             trait_defs: TypedArena::new()
         }
@@ -653,6 +606,7 @@ pub struct ctxt<'tcx> {
     substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
     bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
     region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
+    stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
 
     /// Common types, pre-interned for your convenience.
     pub types: CommonTypes<'tcx>,
@@ -691,9 +645,7 @@ pub struct ctxt<'tcx> {
     /// A cache for the trait_items() routine
     pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
 
-    pub impl_trait_cache: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
-
-    pub impl_trait_refs: RefCell<NodeMap<TraitRef<'tcx>>>,
+    pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
     pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
@@ -708,15 +660,10 @@ pub struct ctxt<'tcx> {
     /// additional acyclicity requirements).
     pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
 
-    /// Maps from node-id of a trait object cast (like `foo as
-    /// Box<Trait>`) to the trait reference.
-    pub object_cast_map: ObjectCastMap<'tcx>,
-
     pub map: ast_map::Map<'tcx>,
     pub freevars: RefCell<FreevarMap>,
     pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
     pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
-    pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
     pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
     pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
     pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
@@ -774,10 +721,10 @@ pub struct ctxt<'tcx> {
     /// Borrows
     pub upvar_capture_map: RefCell<UpvarCaptureMap>,
 
-    /// These two caches are used by const_eval when decoding external statics
-    /// and variants that are found.
+    /// These caches are used by const_eval when decoding external constants.
     pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
     pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
+    pub extern_const_fns: RefCell<DefIdMap<ast::NodeId>>,
 
     pub method_map: MethodMap<'tcx>,
 
@@ -800,33 +747,30 @@ pub struct ctxt<'tcx> {
     pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>,
 
     /// Maps any item's def-id to its stability index.
-    pub stability: RefCell<stability::Index>,
-
-    /// Maps def IDs to true if and only if they're associated types.
-    pub associated_types: RefCell<DefIdMap<bool>>,
+    pub stability: RefCell<stability::Index<'tcx>>,
 
     /// Caches the results of trait selection. This cache is used
     /// for things that do not have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
 
+    /// A set of predicates that have been fulfilled *somewhere*.
+    /// This is used to avoid duplicate work. Predicates are only
+    /// added to this set when they mention only "global" names
+    /// (i.e., no type or lifetime parameters).
+    pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
+
     /// Caches the representation hints for struct definitions.
     pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
 
-    /// Caches whether types are known to impl Copy. Note that type
-    /// parameters are never placed into this cache, because their
-    /// results are dependent on the parameter environment.
-    pub type_impls_copy_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
-
-    /// Caches whether types are known to impl Sized. Note that type
-    /// parameters are never placed into this cache, because their
-    /// results are dependent on the parameter environment.
-    pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
-
     /// Maps Expr NodeId's to their constant qualification.
     pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>,
+
+    /// Maps a cast expression to its kind. This is keyed on the
+    /// *from* expression of the cast, not the cast itself.
+    pub cast_kinds: RefCell<NodeMap<cast::CastKind>>,
 }
 
 impl<'tcx> ctxt<'tcx> {
@@ -842,6 +786,16 @@ impl<'tcx> ctxt<'tcx> {
         interned
     }
 
+    pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
+        if let Some(st) = self.stability_interner.borrow().get(&stab) {
+            return st;
+        }
+
+        let interned = self.arenas.stability.alloc(stab);
+        self.stability_interner.borrow_mut().insert(interned, interned);
+        interned
+    }
+
     pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
         self.free_region_maps.borrow_mut()
                              .insert(id, map);
@@ -850,6 +804,201 @@ impl<'tcx> ctxt<'tcx> {
     pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
         self.free_region_maps.borrow()[&id].clone()
     }
+
+    pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
+        value.lift_to_tcx(self)
+    }
+}
+
+/// A trait implemented for all X<'a> types which can be safely and
+/// efficiently converted to X<'tcx> as long as they are part of the
+/// provided ty::ctxt<'tcx>.
+/// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
+/// by looking them up in their respective interners.
+/// None is returned if the value or one of the components is not part
+/// of the provided context.
+/// For Ty, None can be returned if either the type interner doesn't
+/// contain the TypeVariants key or if the address of the interned
+/// pointer differs. The latter case is possible if a primitive type,
+/// e.g. `()` or `u8`, was interned in a different context.
+pub trait Lift<'tcx> {
+    type Lifted;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
+}
+
+impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
+    type Lifted = (A::Lifted, B::Lifted);
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b)))
+    }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
+    type Lifted = Vec<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
+        let mut result = Vec::with_capacity(self.len());
+        for x in self {
+            if let Some(value) = tcx.lift(x) {
+                result.push(value);
+            } else {
+                return None;
+            }
+        }
+        Some(result)
+    }
+}
+
+impl<'tcx> Lift<'tcx> for Region {
+    type Lifted = Self;
+    fn lift_to_tcx(&self, _: &ctxt<'tcx>) -> Option<Region> {
+        Some(*self)
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
+    type Lifted = Ty<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> {
+        if let Some(&ty) = tcx.interner.borrow().get(&self.sty) {
+            if *self as *const _ == ty as *const _ {
+                return Some(ty);
+            }
+        }
+        None
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
+    type Lifted = &'tcx Substs<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> {
+        if let Some(&substs) = tcx.substs_interner.borrow().get(*self) {
+            if *self as *const _ == substs as *const _ {
+                return Some(substs);
+            }
+        }
+        None
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
+    type Lifted = TraitRef<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitRef<'tcx>> {
+        tcx.lift(&self.substs).map(|substs| TraitRef {
+            def_id: self.def_id,
+            substs: substs
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for TraitPredicate<'a> {
+    type Lifted = TraitPredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitPredicate<'tcx>> {
+        tcx.lift(&self.trait_ref).map(|trait_ref| TraitPredicate {
+            trait_ref: trait_ref
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for EquatePredicate<'a> {
+    type Lifted = EquatePredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<EquatePredicate<'tcx>> {
+        tcx.lift(&(self.0, self.1)).map(|(a, b)| EquatePredicate(a, b))
+    }
+}
+
+impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for OutlivesPredicate<A, B> {
+    type Lifted = OutlivesPredicate<A::Lifted, B::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&(self.0, self.1)).map(|(a, b)| OutlivesPredicate(a, b))
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ProjectionPredicate<'a> {
+    type Lifted = ProjectionPredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<ProjectionPredicate<'tcx>> {
+        tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| {
+            ProjectionPredicate {
+                projection_ty: ProjectionTy {
+                    trait_ref: trait_ref,
+                    item_name: self.projection_ty.item_name
+                },
+                ty: ty
+            }
+        })
+    }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Binder<T> {
+    type Lifted = Binder<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.0).map(|x| Binder(x))
+    }
+}
+
+pub mod tls {
+    use ast_map;
+    use middle::ty;
+    use session::Session;
+
+    use std::fmt;
+    use syntax::ast;
+    use syntax::codemap;
+
+    /// Marker type used for the scoped TLS slot.
+    /// The type context cannot be used directly because the scoped TLS
+    /// in libstd doesn't allow types generic over lifetimes.
+    struct ThreadLocalTyCx;
+
+    scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
+
+    fn def_id_debug(def_id: ast::DefId, f: &mut fmt::Formatter) -> fmt::Result {
+        // 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
+        with(|tcx| {
+            if def_id.krate == ast::LOCAL_CRATE {
+                match tcx.map.find(def_id.node) {
+                    Some(ast_map::NodeItem(..)) |
+                    Some(ast_map::NodeForeignItem(..)) |
+                    Some(ast_map::NodeImplItem(..)) |
+                    Some(ast_map::NodeTraitItem(..)) |
+                    Some(ast_map::NodeVariant(..)) |
+                    Some(ast_map::NodeStructCtor(..)) => {
+                        return write!(f, "{}", ty::item_path_str(tcx, def_id));
+                    }
+                    _ => {}
+                }
+            }
+            Ok(())
+        })
+    }
+
+    fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
+        with(|tcx| {
+            write!(f, "{}", tcx.sess.codemap().span_to_string(span))
+        })
+    }
+
+    pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
+                                                           -> (Session, R) {
+        let result = ast::DEF_ID_DEBUG.with(|def_id_dbg| {
+            codemap::SPAN_DEBUG.with(|span_dbg| {
+                let original_def_id_debug = def_id_dbg.get();
+                def_id_dbg.set(def_id_debug);
+                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));
+                def_id_dbg.set(original_def_id_debug);
+                span_dbg.set(original_span_debug);
+                result
+            })
+        });
+        (tcx.sess, result)
+    }
+
+    pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
+        TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
+    }
 }
 
 // Flags that we track on types. These flags are propagated upwards
@@ -858,17 +1007,43 @@ impl<'tcx> ctxt<'tcx> {
 // recursing over the type itself.
 bitflags! {
     flags TypeFlags: u32 {
-        const HAS_PARAMS        = 1 << 0,
-        const HAS_SELF          = 1 << 1,
-        const HAS_TY_INFER      = 1 << 2,
-        const HAS_RE_INFER      = 1 << 3,
-        const HAS_RE_LATE_BOUND = 1 << 4,
-        const HAS_REGIONS       = 1 << 5,
-        const HAS_TY_ERR        = 1 << 6,
-        const HAS_PROJECTION    = 1 << 7,
-        const NEEDS_SUBST       = TypeFlags::HAS_PARAMS.bits |
+        const HAS_PARAMS         = 1 << 0,
+        const HAS_SELF           = 1 << 1,
+        const HAS_TY_INFER       = 1 << 2,
+        const HAS_RE_INFER       = 1 << 3,
+        const HAS_RE_EARLY_BOUND = 1 << 4,
+        const HAS_FREE_REGIONS   = 1 << 5,
+        const HAS_TY_ERR         = 1 << 6,
+        const HAS_PROJECTION     = 1 << 7,
+        const HAS_TY_CLOSURE     = 1 << 8,
+
+        // true if there are "names" of types and regions and so forth
+        // that are local to a particular fn
+        const HAS_LOCAL_NAMES   = 1 << 9,
+
+        const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
+                                   TypeFlags::HAS_SELF.bits |
+                                   TypeFlags::HAS_RE_EARLY_BOUND.bits,
+
+        // Flags representing the nominal content of a type,
+        // computed by FlagsComputation. If you add a new nominal
+        // flag, it should be added here too.
+        const NOMINAL_FLAGS     = TypeFlags::HAS_PARAMS.bits |
                                   TypeFlags::HAS_SELF.bits |
-                                  TypeFlags::HAS_REGIONS.bits,
+                                  TypeFlags::HAS_TY_INFER.bits |
+                                  TypeFlags::HAS_RE_INFER.bits |
+                                  TypeFlags::HAS_RE_EARLY_BOUND.bits |
+                                  TypeFlags::HAS_FREE_REGIONS.bits |
+                                  TypeFlags::HAS_TY_ERR.bits |
+                                  TypeFlags::HAS_PROJECTION.bits |
+                                  TypeFlags::HAS_TY_CLOSURE.bits |
+                                  TypeFlags::HAS_LOCAL_NAMES.bits,
+
+        // Caches for type_is_sized, type_moves_by_default
+        const SIZEDNESS_CACHED  = 1 << 16,
+        const IS_SIZED          = 1 << 17,
+        const MOVENESS_CACHED   = 1 << 18,
+        const MOVES_BY_DEFAULT  = 1 << 19,
     }
 }
 
@@ -876,6 +1051,7 @@ macro_rules! sty_debug_print {
     ($ctxt: expr, $($variant: ident),*) => {{
         // curious inner module to allow variant names to be used as
         // variable names.
+        #[allow(non_snake_case)]
         mod inner {
             use middle::ty;
             #[derive(Copy, Clone)]
@@ -894,15 +1070,15 @@ macro_rules! sty_debug_print {
                 $(let mut $variant = total;)*
 
 
-                for (_, t) in &*tcx.interner.borrow() {
+                for (_, t) in tcx.interner.borrow().iter() {
                     let variant = match t.sty {
-                        ty::ty_bool | ty::ty_char | ty::ty_int(..) | ty::ty_uint(..) |
-                            ty::ty_float(..) | ty::ty_str => continue,
-                        ty::ty_err => /* unimportant */ continue,
+                        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
+                            ty::TyFloat(..) | ty::TyStr => continue,
+                        ty::TyError => /* unimportant */ continue,
                         $(ty::$variant(..) => &mut $variant,)*
                     };
-                    let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
-                    let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
+                    let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
+                    let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
 
                     variant.total += 1;
                     total.total += 1;
@@ -937,19 +1113,19 @@ impl<'tcx> ctxt<'tcx> {
     pub fn print_debug_stats(&self) {
         sty_debug_print!(
             self,
-            ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
-            ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection);
+            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
+            TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
         println!("Region interner: #{}", self.region_interner.borrow().len());
+        println!("Stability interner: #{}", self.stability_interner.borrow().len());
     }
 }
 
-#[derive(Debug)]
 pub struct TyS<'tcx> {
-    pub sty: sty<'tcx>,
-    pub flags: TypeFlags,
+    pub sty: TypeVariants<'tcx>,
+    pub flags: Cell<TypeFlags>,
 
     // the maximal depth of any bound regions appearing in this type.
     region_depth: u32,
@@ -998,30 +1174,38 @@ impl<'tcx> Hash for InternedTy<'tcx> {
     }
 }
 
-impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
-    fn borrow<'a>(&'a self) -> &'a sty<'tcx> {
+impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
+    fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
         &self.ty.sty
     }
 }
 
 pub fn type_has_params(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_PARAMS)
+    ty.flags.get().intersects(TypeFlags::HAS_PARAMS)
 }
 pub fn type_has_self(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_SELF)
+    ty.flags.get().intersects(TypeFlags::HAS_SELF)
 }
 pub fn type_has_ty_infer(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_TY_INFER)
+    ty.flags.get().intersects(TypeFlags::HAS_TY_INFER)
 }
 pub fn type_needs_infer(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
+    ty.flags.get().intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
+}
+pub fn type_is_global(ty: Ty) -> bool {
+    !ty.flags.get().intersects(TypeFlags::HAS_LOCAL_NAMES)
 }
 pub fn type_has_projection(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_PROJECTION)
+    ty.flags.get().intersects(TypeFlags::HAS_PROJECTION)
+}
+pub fn type_has_ty_closure(ty: Ty) -> bool {
+    ty.flags.get().intersects(TypeFlags::HAS_TY_CLOSURE)
 }
 
-pub fn type_has_late_bound_regions(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_RE_LATE_BOUND)
+pub fn type_has_erasable_regions(ty: Ty) -> bool {
+    ty.flags.get().intersects(TypeFlags::HAS_RE_EARLY_BOUND |
+                              TypeFlags::HAS_RE_INFER |
+                              TypeFlags::HAS_FREE_REGIONS)
 }
 
 /// An "escaping region" is a bound region whose binder is not part of `t`.
@@ -1061,7 +1245,7 @@ pub struct BareFnTy<'tcx> {
     pub sig: PolyFnSig<'tcx>,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct ClosureTy<'tcx> {
     pub unsafety: ast::Unsafety,
     pub abi: abi::Abi,
@@ -1132,7 +1316,7 @@ impl<'tcx> PolyFnSig<'tcx> {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct ParamTy {
     pub space: subst::ParamSpace,
     pub idx: u32,
@@ -1186,7 +1370,7 @@ pub struct DebruijnIndex {
 }
 
 /// Representation of regions:
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Copy)]
 pub enum Region {
     // Region bound in a type or fn declaration which will be
     // substituted 'early' -- that is, at the same time when type
@@ -1234,7 +1418,7 @@ pub struct EarlyBoundRegion {
 /// Upvars do not get their own node-id. Instead, we use the pair of
 /// the original var id (that is, the root variable that is referenced
 /// by the upvar) and the id of the closure expression.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct UpvarId {
     pub var_id: ast::NodeId,
     pub closure_expr_id: ast::NodeId,
@@ -1299,7 +1483,7 @@ pub enum UpvarCapture {
     ByRef(UpvarBorrow),
 }
 
-#[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Copy)]
 pub struct UpvarBorrow {
     /// The kind of borrow: by-ref upvars have access to shared
     /// immutable borrows, which are not part of the normal language
@@ -1313,6 +1497,15 @@ pub struct UpvarBorrow {
 pub type UpvarCaptureMap = FnvHashMap<UpvarId, UpvarCapture>;
 
 impl Region {
+    pub fn is_global(&self) -> bool {
+        // does this represent a region that can be named in a global
+        // way? used in fulfillment caching.
+        match *self {
+            ty::ReStatic | ty::ReEmpty => true,
+            _ => false,
+        }
+    }
+
     pub fn is_bound(&self) -> bool {
         match *self {
             ty::ReEarlyBound(..) => true,
@@ -1330,7 +1523,7 @@ impl Region {
 }
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug, Copy)]
+         RustcEncodable, RustcDecodable, Copy)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
 pub struct FreeRegion {
@@ -1339,7 +1532,7 @@ pub struct FreeRegion {
 }
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug, Copy)]
+         RustcEncodable, RustcDecodable, Copy, Debug)]
 pub enum BoundRegion {
     /// An anonymous region parameter for a given fn (&T)
     BrAnon(u32),
@@ -1361,53 +1554,102 @@ pub enum BoundRegion {
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum sty<'tcx> {
-    ty_bool,
-    ty_char,
-    ty_int(ast::IntTy),
-    ty_uint(ast::UintTy),
-    ty_float(ast::FloatTy),
-    /// Substs here, possibly against intuition, *may* contain `ty_param`s.
+pub enum TypeVariants<'tcx> {
+    /// The primitive boolean type. Written as `bool`.
+    TyBool,
+
+    /// The primitive character type; holds a Unicode scalar value
+    /// (a non-surrogate code point).  Written as `char`.
+    TyChar,
+
+    /// A primitive signed integer type. For example, `i32`.
+    TyInt(ast::IntTy),
+
+    /// A primitive unsigned integer type. For example, `u32`.
+    TyUint(ast::UintTy),
+
+    /// A primitive floating-point type. For example, `f64`.
+    TyFloat(ast::FloatTy),
+
+    /// An enumerated type, defined with `enum`.
+    ///
+    /// Substs here, possibly against intuition, *may* contain `TyParam`s.
     /// That is, even after substitution it is possible that there are type
-    /// variables. This happens when the `ty_enum` corresponds to an enum
-    /// definition and not a concrete use of it. To get the correct `ty_enum`
+    /// 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 `ast::Ty` and look it up in
-    /// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
+    /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as
     /// well.
-    ty_enum(DefId, &'tcx Substs<'tcx>),
-    ty_uniq(Ty<'tcx>),
-    ty_str,
-    ty_vec(Ty<'tcx>, Option<usize>), // Second field is length.
-    ty_ptr(mt<'tcx>),
-    ty_rptr(&'tcx Region, mt<'tcx>),
+    TyEnum(DefId, &'tcx Substs<'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.
-    ty_bare_fn(Option<DefId>, &'tcx BareFnTy<'tcx>),
+    /// A structure type, defined with `struct`.
+    ///
+    /// See warning about substitutions for enumerated types.
+    TyStruct(DefId, &'tcx Substs<'tcx>),
 
-    ty_trait(Box<TyTrait<'tcx>>),
-    ty_struct(DefId, &'tcx Substs<'tcx>),
+    /// `Box<T>`; this is nominally a struct in the documentation, but is
+    /// special-cased internally. For example, it is possible to implicitly
+    /// move the contents of a box out of that box, and methods of any type
+    /// can have type `Box<Self>`.
+    TyBox(Ty<'tcx>),
 
-    ty_closure(DefId, &'tcx Substs<'tcx>),
+    /// The pointee of a string slice. Written as `str`.
+    TyStr,
 
-    ty_tup(Vec<Ty<'tcx>>),
+    /// An array with the given length. Written as `[T; n]`.
+    TyArray(Ty<'tcx>, usize),
 
-    ty_projection(ProjectionTy<'tcx>),
-    ty_param(ParamTy), // type parameter
+    /// The pointee of an array slice.  Written as `[T]`.
+    TySlice(Ty<'tcx>),
 
-    ty_infer(InferTy), // something used only during inference/typeck
-    ty_err, // Also only used during inference/typeck, to represent
-            // the type of an erroneous expression (helps cut down
-            // on non-useful type error messages)
+    /// A raw pointer. Written as `*mut T` or `*const T`
+    TyRawPtr(mt<'tcx>),
+
+    /// A reference; a pointer with an associated lifetime. Written as
+    /// `&a mut T` or `&'a T`.
+    TyRef(&'tcx Region, mt<'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.
+    ///
+    /// FIXME: Conflating function pointers and the type of a
+    /// function is probably a terrible idea; a function pointer is a
+    /// value with a specific type, but a function can be polymorphic
+    /// or dynamically dispatched.
+    TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>),
+
+    /// A trait, defined with `trait`.
+    TyTrait(Box<TraitTy<'tcx>>),
+
+    /// The anonymous type of a closure. Used to represent the type of
+    /// `|a| a`.
+    TyClosure(DefId, &'tcx Substs<'tcx>),
+
+    /// A tuple type.  For example, `(i32, bool)`.
+    TyTuple(Vec<Ty<'tcx>>),
+
+    /// The projection of an associated type.  For example,
+    /// `<T as Trait<..>>::N`.
+    TyProjection(ProjectionTy<'tcx>),
+
+    /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
+    TyParam(ParamTy),
+
+    /// A type variable used during type-checking.
+    TyInfer(InferTy),
+
+    /// A placeholder for a type which could not be computed; this is
+    /// propagated to avoid useless error messages.
+    TyError,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct TyTrait<'tcx> {
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TraitTy<'tcx> {
     pub principal: ty::PolyTraitRef<'tcx>,
     pub bounds: ExistentialBounds<'tcx>,
 }
 
-impl<'tcx> TyTrait<'tcx> {
+impl<'tcx> TraitTy<'tcx> {
     pub fn principal_def_id(&self) -> ast::DefId {
         self.principal.0.def_id
     }
@@ -1472,7 +1714,7 @@ impl<'tcx> TyTrait<'tcx> {
 /// Note that a `TraitRef` introduces a level of region binding, to
 /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
 /// U>` or higher-ranked object types.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: &'tcx Substs<'tcx>,
@@ -1605,57 +1847,77 @@ pub enum type_err<'tcx> {
     terr_projection_bounds_length(expected_found<usize>),
 }
 
-/// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
-/// as well as the existential type parameter in an object type.
-#[derive(PartialEq, Eq, Hash, Clone, Debug)]
-pub struct ParamBounds<'tcx> {
-    pub region_bounds: Vec<ty::Region>,
-    pub builtin_bounds: BuiltinBounds,
-    pub trait_bounds: Vec<PolyTraitRef<'tcx>>,
-    pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
-}
-
 /// Bounds suitable for an existentially quantified type parameter
-/// such as those that appear in object types or closure types. The
-/// major difference between this case and `ParamBounds` is that
-/// general purpose trait bounds are omitted and there must be
-/// *exactly one* region.
-#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+/// such as those that appear in object types or closure types.
+#[derive(PartialEq, Eq, Hash, Clone)]
 pub struct ExistentialBounds<'tcx> {
     pub region_bound: ty::Region,
     pub builtin_bounds: BuiltinBounds,
     pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
+
+    // If true, this TyTrait used a "default bound" in the surface
+    // syntax.  This makes no difference to the type system but is
+    // handy for error reporting.
+    pub region_bound_will_change: bool,
 }
 
-pub type BuiltinBounds = EnumSet<BuiltinBound>;
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub struct BuiltinBounds(EnumSet<BuiltinBound>);
 
-#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash,
-           Debug, Copy)]
-#[repr(usize)]
-pub enum BuiltinBound {
-    BoundSend,
-    BoundSized,
-    BoundCopy,
-    BoundSync,
+impl BuiltinBounds {
+       pub fn empty() -> BuiltinBounds {
+        BuiltinBounds(EnumSet::new())
+    }
+
+    pub fn iter(&self) -> enum_set::Iter<BuiltinBound> {
+        self.into_iter()
+    }
+
+    pub fn to_predicates<'tcx>(&self,
+                               tcx: &ty::ctxt<'tcx>,
+                               self_ty: Ty<'tcx>) -> Vec<Predicate<'tcx>> {
+        self.iter().filter_map(|builtin_bound|
+            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) {
+                Ok(trait_ref) => Some(trait_ref.as_predicate()),
+                Err(ErrorReported) => { None }
+            }
+        ).collect()
+    }
+}
+
+impl ops::Deref for BuiltinBounds {
+    type Target = EnumSet<BuiltinBound>;
+    fn deref(&self) -> &Self::Target { &self.0 }
+}
+
+impl ops::DerefMut for BuiltinBounds {
+    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
 }
 
-pub fn empty_builtin_bounds() -> BuiltinBounds {
-    EnumSet::new()
+impl<'a> IntoIterator for &'a BuiltinBounds {
+    type Item = BuiltinBound;
+    type IntoIter = enum_set::Iter<BuiltinBound>;
+    fn into_iter(self) -> Self::IntoIter {
+        (**self).into_iter()
+    }
 }
 
-pub fn all_builtin_bounds() -> BuiltinBounds {
-    let mut set = EnumSet::new();
-    set.insert(BoundSend);
-    set.insert(BoundSized);
-    set.insert(BoundSync);
-    set
+#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash,
+           Debug, Copy)]
+#[repr(usize)]
+pub enum BuiltinBound {
+    Send,
+    Sized,
+    Copy,
+    Sync,
 }
 
 /// An existential bound that does not implement any traits.
 pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> {
     ty::ExistentialBounds { region_bound: r,
-                            builtin_bounds: empty_builtin_bounds(),
-                            projection_bounds: Vec::new() }
+                            builtin_bounds: BuiltinBounds::empty(),
+                            projection_bounds: Vec::new(),
+                            region_bound_will_change: false, }
 }
 
 impl CLike for BuiltinBound {
@@ -1733,7 +1995,7 @@ impl cmp::PartialEq for InferRegion {
 }
 
 impl fmt::Debug for TyVid {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "_#{}t", self.index)
     }
 }
@@ -1789,24 +2051,27 @@ impl fmt::Debug for IntVarValue {
 /// from `T:'a` annotations appearing in the type definition.  If
 /// this is `None`, then the default is inherited from the
 /// surrounding context. See RFC #599 for details.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone)]
 pub enum ObjectLifetimeDefault {
     /// Require an explicit annotation. Occurs when multiple
     /// `T:'a` constraints are found.
     Ambiguous,
 
+    /// Use the base default, typically 'static, but in a fn body it is a fresh variable
+    BaseDefault,
+
     /// Use the given region as the default.
     Specific(Region),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct TypeParameterDef<'tcx> {
     pub name: ast::Name,
     pub def_id: ast::DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
     pub default: Option<Ty<'tcx>>,
-    pub object_lifetime_default: Option<ObjectLifetimeDefault>,
+    pub object_lifetime_default: ObjectLifetimeDefault,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
@@ -1862,7 +2127,7 @@ impl<'tcx> Generics<'tcx> {
 }
 
 /// Bounds on generics.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct GenericPredicates<'tcx> {
     pub predicates: VecPerParamSpace<Predicate<'tcx>>,
 }
@@ -1892,7 +2157,7 @@ impl<'tcx> GenericPredicates<'tcx> {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub enum Predicate<'tcx> {
     /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -1998,9 +2263,32 @@ impl<'tcx> Predicate<'tcx> {
                 Predicate::Projection(ty::Binder(data.subst(tcx, substs))),
         }
     }
+
+    // Indicates whether this predicate references only 'global'
+    // types/lifetimes that are the same regardless of what fn we are
+    // in. This is used for caching. Errs on the side of returning
+    // false.
+    pub fn is_global(&self) -> bool {
+        match *self {
+            ty::Predicate::Trait(ref data) => {
+                let substs = data.skip_binder().trait_ref.substs;
+
+                substs.types.iter().all(|t| ty::type_is_global(t)) && {
+                    match substs.regions {
+                        subst::ErasedRegions => true,
+                        subst::NonerasedRegions(ref r) => r.iter().all(|r| r.is_global()),
+                    }
+                }
+            }
+
+            _ => {
+                false
+            }
+        }
+    }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>
 }
@@ -2048,7 +2336,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::R
 /// equality between arbitrary types. Processing an instance of Form
 /// #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct ProjectionPredicate<'tcx> {
     pub projection_ty: ProjectionTy<'tcx>,
     pub ty: Ty<'tcx>,
@@ -2180,7 +2468,7 @@ impl<'tcx> Predicate<'tcx> {
                 let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice();
                 trait_inputs.iter()
                             .cloned()
-                            .chain(Some(data.0.ty).into_iter())
+                            .chain(Some(data.0.ty))
                             .collect()
             }
         };
@@ -2237,7 +2525,7 @@ impl<'tcx> Predicate<'tcx> {
 /// `[[], [U:Bar<T>]]`.  Now if there were some particular reference
 /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
 /// [usize:Bar<isize>]]`.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct InstantiatedPredicates<'tcx> {
     pub predicates: VecPerParamSpace<Predicate<'tcx>>,
 }
@@ -2301,7 +2589,7 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> {
 
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
-    /// into Obligations.
+    /// into Obligations, and elaborated and normalized.
     pub caller_bounds: Vec<ty::Predicate<'tcx>>,
 
     /// Caches the results of trait selection. This cache is used
@@ -2423,7 +2711,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
             }
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
-                    ast::ItemFn(_, _, _, _, ref body) => {
+                    ast::ItemFn(_, _, _, _, _, ref body) => {
                         // We assume this is a function.
                         let fn_def_id = ast_util::local_def(id);
                         let fn_scheme = lookup_item_type(cx, fn_def_id);
@@ -2571,8 +2859,8 @@ impl<'tcx> TraitDef<'tcx> {
                        tcx: &ctxt<'tcx>,
                        impl_def_id: DefId,
                        impl_trait_ref: TraitRef<'tcx>) {
-        debug!("TraitDef::record_impl for {}, from {}",
-               self.repr(tcx), impl_trait_ref.repr(tcx));
+        debug!("TraitDef::record_impl for {:?}, from {:?}",
+               self, impl_trait_ref);
 
         // We don't want to borrow_mut after we already populated all impls,
         // so check if an impl is present with an immutable borrow first.
@@ -2721,44 +3009,51 @@ impl<'tcx> CommonTypes<'tcx> {
            -> CommonTypes<'tcx>
     {
         CommonTypes {
-            bool: intern_ty(arena, interner, ty_bool),
-            char: intern_ty(arena, interner, ty_char),
-            err: intern_ty(arena, interner, ty_err),
-            isize: intern_ty(arena, interner, ty_int(ast::TyIs)),
-            i8: intern_ty(arena, interner, ty_int(ast::TyI8)),
-            i16: intern_ty(arena, interner, ty_int(ast::TyI16)),
-            i32: intern_ty(arena, interner, ty_int(ast::TyI32)),
-            i64: intern_ty(arena, interner, ty_int(ast::TyI64)),
-            usize: intern_ty(arena, interner, ty_uint(ast::TyUs)),
-            u8: intern_ty(arena, interner, ty_uint(ast::TyU8)),
-            u16: intern_ty(arena, interner, ty_uint(ast::TyU16)),
-            u32: intern_ty(arena, interner, ty_uint(ast::TyU32)),
-            u64: intern_ty(arena, interner, ty_uint(ast::TyU64)),
-            f32: intern_ty(arena, interner, ty_float(ast::TyF32)),
-            f64: intern_ty(arena, interner, ty_float(ast::TyF64)),
-        }
-    }
-}
-
-pub fn mk_ctxt<'tcx>(s: Session,
-                     arenas: &'tcx CtxtArenas<'tcx>,
-                     def_map: DefMap,
-                     named_region_map: resolve_lifetime::NamedRegionMap,
-                     map: ast_map::Map<'tcx>,
-                     freevars: RefCell<FreevarMap>,
-                     region_maps: RegionMaps,
-                     lang_items: middle::lang_items::LanguageItems,
-                     stability: stability::Index) -> ctxt<'tcx>
+            bool: intern_ty(arena, interner, TyBool),
+            char: intern_ty(arena, interner, TyChar),
+            err: intern_ty(arena, interner, TyError),
+            isize: intern_ty(arena, interner, TyInt(ast::TyIs)),
+            i8: intern_ty(arena, interner, TyInt(ast::TyI8)),
+            i16: intern_ty(arena, interner, TyInt(ast::TyI16)),
+            i32: intern_ty(arena, interner, TyInt(ast::TyI32)),
+            i64: intern_ty(arena, interner, TyInt(ast::TyI64)),
+            usize: intern_ty(arena, interner, TyUint(ast::TyUs)),
+            u8: intern_ty(arena, interner, TyUint(ast::TyU8)),
+            u16: intern_ty(arena, interner, TyUint(ast::TyU16)),
+            u32: intern_ty(arena, interner, TyUint(ast::TyU32)),
+            u64: intern_ty(arena, interner, TyUint(ast::TyU64)),
+            f32: intern_ty(arena, interner, TyFloat(ast::TyF32)),
+            f64: intern_ty(arena, interner, TyFloat(ast::TyF64)),
+        }
+    }
+}
+
+/// Create a type context and call the closure with a `&ty::ctxt` reference
+/// 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 with_ctxt<'tcx, F, R>(s: Session,
+                             arenas: &'tcx CtxtArenas<'tcx>,
+                             def_map: DefMap,
+                             named_region_map: resolve_lifetime::NamedRegionMap,
+                             map: ast_map::Map<'tcx>,
+                             freevars: RefCell<FreevarMap>,
+                             region_maps: RegionMaps,
+                             lang_items: middle::lang_items::LanguageItems,
+                             stability: stability::Index<'tcx>,
+                             f: F) -> (Session, R)
+                             where F: FnOnce(&ctxt<'tcx>) -> R
 {
     let mut interner = FnvHashMap();
     let common_types = CommonTypes::new(&arenas.type_, &mut interner);
 
-    ctxt {
+    tls::enter(ctxt {
         arenas: arenas,
         interner: RefCell::new(interner),
         substs_interner: RefCell::new(FnvHashMap()),
         bare_fn_interner: RefCell::new(FnvHashMap()),
         region_interner: RefCell::new(FnvHashMap()),
+        stability_interner: RefCell::new(FnvHashMap()),
         types: common_types,
         named_region_map: named_region_map,
         region_maps: region_maps,
@@ -2769,23 +3064,21 @@ pub fn mk_ctxt<'tcx>(s: Session,
         def_map: def_map,
         node_types: RefCell::new(FnvHashMap()),
         item_substs: RefCell::new(NodeMap()),
-        impl_trait_refs: RefCell::new(NodeMap()),
+        impl_trait_refs: RefCell::new(DefIdMap()),
         trait_defs: RefCell::new(DefIdMap()),
         predicates: RefCell::new(DefIdMap()),
         super_predicates: RefCell::new(DefIdMap()),
-        object_cast_map: RefCell::new(NodeMap()),
+        fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
         map: map,
         freevars: freevars,
         tcache: RefCell::new(DefIdMap()),
         rcache: RefCell::new(FnvHashMap()),
-        short_names_cache: RefCell::new(FnvHashMap()),
         tc_cache: RefCell::new(FnvHashMap()),
         ast_ty_to_ty_cache: RefCell::new(NodeMap()),
         enum_var_cache: RefCell::new(DefIdMap()),
         impl_or_trait_items: RefCell::new(DefIdMap()),
         trait_item_def_ids: RefCell::new(DefIdMap()),
         trait_items_cache: RefCell::new(DefIdMap()),
-        impl_trait_cache: RefCell::new(DefIdMap()),
         ty_param_defs: RefCell::new(NodeMap()),
         adjustments: RefCell::new(NodeMap()),
         normalized_cache: RefCell::new(FnvHashMap()),
@@ -2803,6 +3096,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         upvar_capture_map: RefCell::new(FnvHashMap()),
         extern_const_statics: RefCell::new(DefIdMap()),
         extern_const_variants: RefCell::new(DefIdMap()),
+        extern_const_fns: RefCell::new(DefIdMap()),
         method_map: RefCell::new(FnvHashMap()),
         dependency_formats: RefCell::new(FnvHashMap()),
         closure_kinds: RefCell::new(DefIdMap()),
@@ -2810,14 +3104,12 @@ pub fn mk_ctxt<'tcx>(s: Session,
         node_lint_levels: RefCell::new(FnvHashMap()),
         transmute_restrictions: RefCell::new(Vec::new()),
         stability: RefCell::new(stability),
-        associated_types: RefCell::new(DefIdMap()),
         selection_cache: traits::SelectionCache::new(),
         repr_hint_cache: RefCell::new(DefIdMap()),
-        type_impls_copy_cache: RefCell::new(HashMap::new()),
-        type_impls_sized_cache: RefCell::new(HashMap::new()),
         const_qualif_map: RefCell::new(NodeMap()),
         custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
-   }
+        cast_kinds: RefCell::new(NodeMap()),
+   }, f)
 }
 
 // Type constructors
@@ -2883,25 +3175,25 @@ impl<'tcx> ctxt<'tcx> {
         self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
     }
 
-    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> bool {
+    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> {
         pat_util::pat_contains_ref_binding(&self.def_map, pat)
     }
 
-    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> bool {
+    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> {
         pat_util::arm_contains_ref_binding(&self.def_map, arm)
     }
 }
 
 // Interns a type/name combination, stores the resulting box in cx.interner,
 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
-pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> {
+pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: TypeVariants<'tcx>) -> Ty<'tcx> {
     let mut interner = cx.interner.borrow_mut();
     intern_ty(&cx.arenas.type_, &mut *interner, st)
 }
 
 fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
                    interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
-                   st: sty<'tcx>)
+                   st: TypeVariants<'tcx>)
                    -> Ty<'tcx>
 {
     match interner.get(&st) {
@@ -2913,7 +3205,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
 
     let ty = match () {
         () => type_arena.alloc(TyS { sty: st,
-                                     flags: flags.flags,
+                                     flags: Cell::new(flags.flags),
                                      region_depth: flags.depth, }),
     };
 
@@ -2937,14 +3229,14 @@ impl FlagComputation {
         FlagComputation { flags: TypeFlags::empty(), depth: 0 }
     }
 
-    fn for_sty(st: &sty) -> FlagComputation {
+    fn for_sty(st: &TypeVariants) -> FlagComputation {
         let mut result = FlagComputation::new();
         result.add_sty(st);
         result
     }
 
     fn add_flags(&mut self, flags: TypeFlags) {
-        self.flags = self.flags | flags;
+        self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
     }
 
     fn add_depth(&mut self, depth: u32) {
@@ -2967,28 +3259,29 @@ impl FlagComputation {
         }
     }
 
-    fn add_sty(&mut self, st: &sty) {
+    fn add_sty(&mut self, st: &TypeVariants) {
         match st {
-            &ty_bool |
-            &ty_char |
-            &ty_int(_) |
-            &ty_float(_) |
-            &ty_uint(_) |
-            &ty_str => {
+            &TyBool |
+            &TyChar |
+            &TyInt(_) |
+            &TyFloat(_) |
+            &TyUint(_) |
+            &TyStr => {
             }
 
-            // You might think that we could just return ty_err for
-            // any type containing ty_err as a component, and get
+            // You might think that we could just return TyError for
+            // any type containing TyError as a component, and get
             // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
             // the exception of function types that return bot).
             // But doing so caused sporadic memory corruption, and
             // neither I (tjc) nor nmatsakis could figure out why,
             // so we're doing it this way.
-            &ty_err => {
+            &TyError => {
                 self.add_flags(TypeFlags::HAS_TY_ERR)
             }
 
-            &ty_param(ref p) => {
+            &TyParam(ref p) => {
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
                 if p.space == subst::SelfSpace {
                     self.add_flags(TypeFlags::HAS_SELF);
                 } else {
@@ -2996,61 +3289,64 @@ impl FlagComputation {
                 }
             }
 
-            &ty_closure(_, substs) => {
+            &TyClosure(_, substs) => {
+                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
                 self.add_substs(substs);
             }
 
-            &ty_infer(_) => {
+            &TyInfer(_) => {
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right?
                 self.add_flags(TypeFlags::HAS_TY_INFER)
             }
 
-            &ty_enum(_, substs) | &ty_struct(_, substs) => {
+            &TyEnum(_, substs) | &TyStruct(_, substs) => {
                 self.add_substs(substs);
             }
 
-            &ty_projection(ref data) => {
+            &TyProjection(ref data) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_projection_ty(data);
             }
 
-            &ty_trait(box TyTrait { ref principal, ref bounds }) => {
+            &TyTrait(box TraitTy { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
                 computation.add_substs(principal.0.substs);
                 for projection_bound in &bounds.projection_bounds {
                     let mut proj_computation = FlagComputation::new();
                     proj_computation.add_projection_predicate(&projection_bound.0);
-                    computation.add_bound_computation(&proj_computation);
+                    self.add_bound_computation(&proj_computation);
                 }
                 self.add_bound_computation(&computation);
 
                 self.add_bounds(bounds);
             }
 
-            &ty_uniq(tt) | &ty_vec(tt, _) => {
+            &TyBox(tt) | &TyArray(tt, _) | &TySlice(tt) => {
                 self.add_ty(tt)
             }
 
-            &ty_ptr(ref m) => {
+            &TyRawPtr(ref m) => {
                 self.add_ty(m.ty);
             }
 
-            &ty_rptr(r, ref m) => {
+            &TyRef(r, ref m) => {
                 self.add_region(*r);
                 self.add_ty(m.ty);
             }
 
-            &ty_tup(ref ts) => {
+            &TyTuple(ref ts) => {
                 self.add_tys(&ts[..]);
             }
 
-            &ty_bare_fn(_, ref f) => {
+            &TyBareFn(_, ref f) => {
                 self.add_fn_sig(&f.sig);
             }
         }
     }
 
     fn add_ty(&mut self, ty: Ty) {
-        self.add_flags(ty.flags);
+        self.add_flags(ty.flags.get());
         self.add_depth(ty.region_depth);
     }
 
@@ -3073,14 +3369,16 @@ impl FlagComputation {
     }
 
     fn add_region(&mut self, r: Region) {
-        self.add_flags(TypeFlags::HAS_REGIONS);
         match r {
             ty::ReInfer(_) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
-            ty::ReLateBound(debruijn, _) => {
-                self.add_flags(TypeFlags::HAS_RE_LATE_BOUND);
-                self.add_depth(debruijn.depth);
-            }
-            _ => { }
+            ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); }
+            ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
+            ty::ReStatic => {}
+            _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
+        }
+
+        if !r.is_global() {
+            self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
         }
     }
 
@@ -3098,7 +3396,7 @@ impl FlagComputation {
         match substs.regions {
             subst::ErasedRegions => {}
             subst::NonerasedRegions(ref regions) => {
-                for &r in regions.iter() {
+                for &r in regions {
                     self.add_region(r);
                 }
             }
@@ -3138,28 +3436,28 @@ pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> {
 }
 
 pub fn mk_str<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_str)
+    mk_t(cx, TyStr)
 }
 
 pub fn mk_str_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, m: ast::Mutability) -> Ty<'tcx> {
     mk_rptr(cx, r,
             mt {
-                ty: mk_t(cx, ty_str),
+                ty: mk_t(cx, TyStr),
                 mutbl: m
             })
 }
 
 pub fn mk_enum<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
     // take a copy of substs so that we own the vectors inside
-    mk_t(cx, ty_enum(did, substs))
+    mk_t(cx, TyEnum(did, substs))
 }
 
-pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_uniq(ty)) }
+pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, TyBox(ty)) }
 
-pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_ptr(tm)) }
+pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, TyRawPtr(tm)) }
 
 pub fn mk_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_rptr(r, tm))
+    mk_t(cx, TyRef(r, tm))
 }
 
 pub fn mk_mut_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -3182,7 +3480,10 @@ pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
 }
 
 pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option<usize>) -> Ty<'tcx> {
-    mk_t(cx, ty_vec(ty, sz))
+    match sz {
+        Some(n) => mk_t(cx, TyArray(ty, n)),
+        None => mk_t(cx, TySlice(ty))
+    }
 }
 
 pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
@@ -3194,7 +3495,7 @@ pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx
 }
 
 pub fn mk_tup<'tcx>(cx: &ctxt<'tcx>, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
-    mk_t(cx, ty_tup(ts))
+    mk_t(cx, TyTuple(ts))
 }
 
 pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
@@ -3202,13 +3503,13 @@ pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
 }
 
 pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_bool)
+    mk_t(cx, TyBool)
 }
 
 pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
                         opt_def_id: Option<ast::DefId>,
                         fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_bare_fn(opt_def_id, fty))
+    mk_t(cx, TyBareFn(opt_def_id, fty))
 }
 
 pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
@@ -3236,11 +3537,11 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
 {
     assert!(bound_list_is_sorted(&bounds.projection_bounds));
 
-    let inner = box TyTrait {
+    let inner = box TraitTy {
         principal: principal,
         bounds: bounds
     };
-    mk_t(cx, ty_trait(inner))
+    mk_t(cx, TyTrait(inner))
 }
 
 fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
@@ -3259,18 +3560,18 @@ pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>,
                            -> Ty<'tcx> {
     // take a copy of substs so that we own the vectors inside
     let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
-    mk_t(cx, ty_projection(inner))
+    mk_t(cx, TyProjection(inner))
 }
 
 pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId,
                        substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
     // take a copy of substs so that we own the vectors inside
-    mk_t(cx, ty_struct(struct_id, substs))
+    mk_t(cx, TyStruct(struct_id, substs))
 }
 
 pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>)
                         -> Ty<'tcx> {
-    mk_t(cx, ty_closure(closure_id, substs))
+    mk_t(cx, TyClosure(closure_id, substs))
 }
 
 pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> {
@@ -3286,14 +3587,14 @@ pub fn mk_float_var<'tcx>(cx: &ctxt<'tcx>, v: FloatVid) -> Ty<'tcx> {
 }
 
 pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> {
-    mk_t(cx, ty_infer(it))
+    mk_t(cx, TyInfer(it))
 }
 
 pub fn mk_param<'tcx>(cx: &ctxt<'tcx>,
                       space: subst::ParamSpace,
                       index: u32,
                       name: ast::Name) -> Ty<'tcx> {
-    mk_t(cx, ty_param(ParamTy { space: space, idx: index, name: name }))
+    mk_t(cx, TyParam(ParamTy { space: space, idx: index, name: name }))
 }
 
 pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
@@ -3328,14 +3629,14 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
         match self.sty {
-            ty::ty_param(ref d) => Some(d.clone()),
+            ty::TyParam(ref d) => Some(d.clone()),
             _ => None,
         }
     }
 
     pub fn is_param(&self, space: ParamSpace, index: u32) -> bool {
         match self.sty {
-            ty::ty_param(ref data) => data.space == space && data.idx == index,
+            ty::TyParam(ref data) => data.space == space && data.idx == index,
             _ => false,
         }
     }
@@ -3410,32 +3711,21 @@ impl<'tcx> ItemSubsts<'tcx> {
     }
 }
 
-impl<'tcx> ParamBounds<'tcx> {
-    pub fn empty() -> ParamBounds<'tcx> {
-        ParamBounds {
-            builtin_bounds: empty_builtin_bounds(),
-            trait_bounds: Vec::new(),
-            region_bounds: Vec::new(),
-            projection_bounds: Vec::new(),
-        }
-    }
-}
-
 // Type utilities
 
 pub fn type_is_nil(ty: Ty) -> bool {
     match ty.sty {
-        ty_tup(ref tys) => tys.is_empty(),
+        TyTuple(ref tys) => tys.is_empty(),
         _ => false
     }
 }
 
 pub fn type_is_error(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::HAS_TY_ERR)
+    ty.flags.get().intersects(TypeFlags::HAS_TY_ERR)
 }
 
 pub fn type_needs_subst(ty: Ty) -> bool {
-    ty.flags.intersects(TypeFlags::NEEDS_SUBST)
+    ty.flags.get().intersects(TypeFlags::NEEDS_SUBST)
 }
 
 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
@@ -3444,69 +3734,57 @@ pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
 
 pub fn type_is_ty_var(ty: Ty) -> bool {
     match ty.sty {
-        ty_infer(TyVar(_)) => true,
+        TyInfer(TyVar(_)) => true,
         _ => false
     }
 }
 
-pub fn type_is_bool(ty: Ty) -> bool { ty.sty == ty_bool }
+pub fn type_is_bool(ty: Ty) -> bool { ty.sty == TyBool }
 
 pub fn type_is_self(ty: Ty) -> bool {
     match ty.sty {
-        ty_param(ref p) => p.space == subst::SelfSpace,
+        TyParam(ref p) => p.space == subst::SelfSpace,
         _ => false
     }
 }
 
 fn type_is_slice(ty: Ty) -> bool {
     match ty.sty {
-        ty_ptr(mt) | ty_rptr(_, mt) => match mt.ty.sty {
-            ty_vec(_, None) | ty_str => true,
+        TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty {
+            TySlice(_) | TyStr => true,
             _ => false,
         },
         _ => false
     }
 }
 
-pub fn type_is_vec(ty: Ty) -> bool {
-    match ty.sty {
-        ty_vec(..) => true,
-        ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..}) |
-        ty_uniq(ty) => match ty.sty {
-            ty_vec(_, None) => true,
-            _ => false
-        },
-        _ => false
-    }
-}
-
 pub fn type_is_structural(ty: Ty) -> bool {
     match ty.sty {
-      ty_struct(..) | ty_tup(_) | ty_enum(..) |
-      ty_vec(_, Some(_)) | ty_closure(..) => true,
+      TyStruct(..) | TyTuple(_) | TyEnum(..) |
+      TyArray(..) | TyClosure(..) => true,
       _ => type_is_slice(ty) | type_is_trait(ty)
     }
 }
 
 pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
     match ty.sty {
-        ty_struct(did, _) => lookup_simd(cx, did),
+        TyStruct(did, _) => lookup_simd(cx, did),
         _ => false
     }
 }
 
 pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
-        ty_vec(ty, _) => ty,
-        ty_str => mk_mach_uint(cx, ast::TyU8),
+        TyArray(ty, _) | TySlice(ty) => ty,
+        TyStr => mk_mach_uint(cx, ast::TyU8),
         _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
-                                 ty_to_string(cx, ty))),
+                                  ty)),
     }
 }
 
 pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
-        ty_struct(did, substs) => {
+        TyStruct(did, substs) => {
             let fields = lookup_struct_fields(cx, did);
             lookup_field_type(cx, did, fields[0].id, substs)
         }
@@ -3516,7 +3794,7 @@ pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
 
 pub fn simd_size(cx: &ctxt, ty: Ty) -> usize {
     match ty.sty {
-        ty_struct(did, _) => {
+        TyStruct(did, _) => {
             let fields = lookup_struct_fields(cx, did);
             fields.len()
         }
@@ -3526,35 +3804,35 @@ pub fn simd_size(cx: &ctxt, ty: Ty) -> usize {
 
 pub fn type_is_region_ptr(ty: Ty) -> bool {
     match ty.sty {
-        ty_rptr(..) => true,
+        TyRef(..) => true,
         _ => false
     }
 }
 
 pub fn type_is_unsafe_ptr(ty: Ty) -> bool {
     match ty.sty {
-      ty_ptr(_) => return true,
+      TyRawPtr(_) => return true,
       _ => return false
     }
 }
 
 pub fn type_is_unique(ty: Ty) -> bool {
     match ty.sty {
-        ty_uniq(_) => true,
+        TyBox(_) => true,
         _ => false
     }
 }
 
 /*
  A scalar type is one that denotes an atomic datum, with no sub-components.
- (A ty_ptr is scalar because it represents a non-managed pointer, so its
+ (A TyRawPtr is scalar because it represents a non-managed pointer, so its
  contents are abstract to rustc.)
 */
 pub fn type_is_scalar(ty: Ty) -> bool {
     match ty.sty {
-      ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
-      ty_bare_fn(..) | ty_ptr(_) => true,
+      TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
+      TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
+      TyBareFn(..) | TyRawPtr(_) => true,
       _ => false
     }
 }
@@ -3562,8 +3840,8 @@ pub fn type_is_scalar(ty: Ty) -> bool {
 /// Returns true if this type is a floating point type and false otherwise.
 pub fn type_is_floating_point(ty: Ty) -> bool {
     match ty.sty {
-        ty_float(_) |
-        ty_infer(FloatVar(_)) =>
+        TyFloat(_) |
+        TyInfer(FloatVar(_)) =>
             true,
 
         _ =>
@@ -3676,7 +3954,7 @@ impl TypeContents {
             *self & TC::ReachesAll)
     }
 
-    /// Includes only those bits that still apply when indirected through an unsafe pointer (`*`)
+    /// Includes only those bits that still apply when indirected through a raw pointer (`*`)
     pub fn unsafe_pointer(&self) -> TypeContents {
         *self & TC::ReachesAll
     }
@@ -3722,10 +4000,6 @@ impl fmt::Debug for TypeContents {
     }
 }
 
-pub fn type_interior_is_unsafe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    type_contents(cx, ty).interior_unsafe()
-}
-
 pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
     return memoized(&cx.tc_cache, ty, |ty| {
         tc_ty(cx, ty, &mut FnvHashMap())
@@ -3768,51 +4042,52 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
 
         let result = match ty.sty {
             // usize and isize are ffi-unsafe
-            ty_uint(ast::TyUs) | ty_int(ast::TyIs) => {
+            TyUint(ast::TyUs) | TyInt(ast::TyIs) => {
                 TC::ReachesFfiUnsafe
             }
 
             // Scalar and unique types are sendable, and durable
-            ty_infer(ty::FreshIntTy(_)) | ty_infer(ty::FreshFloatTy(_)) |
-            ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-            ty_bare_fn(..) | ty::ty_char => {
+            TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) |
+            TyBool | TyInt(_) | TyUint(_) | TyFloat(_) |
+            TyBareFn(..) | ty::TyChar => {
                 TC::None
             }
 
-            ty_uniq(typ) => {
+            TyBox(typ) => {
                 TC::ReachesFfiUnsafe | match typ.sty {
-                    ty_str => TC::OwnsOwned,
+                    TyStr => TC::OwnsOwned,
                     _ => tc_ty(cx, typ, cache).owned_pointer(),
                 }
             }
 
-            ty_trait(box TyTrait { ref bounds, .. }) => {
+            TyTrait(box TraitTy { ref bounds, .. }) => {
                 object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
             }
 
-            ty_ptr(ref mt) => {
+            TyRawPtr(ref mt) => {
                 tc_ty(cx, mt.ty, cache).unsafe_pointer()
             }
 
-            ty_rptr(r, ref mt) => {
+            TyRef(r, ref mt) => {
                 TC::ReachesFfiUnsafe | match mt.ty.sty {
-                    ty_str => borrowed_contents(*r, ast::MutImmutable),
-                    ty_vec(..) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r,
+                    TyStr => borrowed_contents(*r, ast::MutImmutable),
+                    TyArray(..) |
+                    TySlice(_) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r,
                                                                                       mt.mutbl)),
                     _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, mt.mutbl)),
                 }
             }
 
-            ty_vec(ty, Some(_)) => {
+            TyArray(ty, _) => {
                 tc_ty(cx, ty, cache)
             }
 
-            ty_vec(ty, None) => {
+            TySlice(ty) => {
                 tc_ty(cx, ty, cache) | TC::Nonsized
             }
-            ty_str => TC::Nonsized,
+            TyStr => TC::Nonsized,
 
-            ty_struct(did, substs) => {
+            TyStruct(did, substs) => {
                 let flds = struct_fields(cx, did, substs);
                 let mut res =
                     TypeContents::union(&flds[..],
@@ -3828,19 +4103,19 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 apply_lang_items(cx, did, res)
             }
 
-            ty_closure(did, substs) => {
+            TyClosure(did, substs) => {
                 // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
                 let param_env = ty::empty_parameter_environment(cx);
                 let upvars = closure_upvars(&param_env, did, substs).unwrap();
                 TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
             }
 
-            ty_tup(ref tys) => {
+            TyTuple(ref tys) => {
                 TypeContents::union(&tys[..],
                                     |ty| tc_ty(cx, *ty, cache))
             }
 
-            ty_enum(did, substs) => {
+            TyEnum(did, substs) => {
                 let variants = substd_enum_variants(cx, did, substs);
                 let mut res =
                     TypeContents::union(&variants[..], |variant| {
@@ -3882,7 +4157,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
 
                                 if variants[data_idx].args.len() == 1 {
                                     match variants[data_idx].args[0].sty {
-                                        ty_bare_fn(..) => { res = res - TC::ReachesFfiUnsafe; }
+                                        TyBareFn(..) => { res = res - TC::ReachesFfiUnsafe; }
                                         _ => { }
                                     }
                                 }
@@ -3895,13 +4170,13 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 apply_lang_items(cx, did, res)
             }
 
-            ty_projection(..) |
-            ty_param(_) => {
+            TyProjection(..) |
+            TyParam(_) => {
                 TC::All
             }
 
-            ty_infer(_) |
-            ty_err => {
+            TyInfer(_) |
+            TyError => {
                 cx.sess.bug("asked to compute contents of error type");
             }
         };
@@ -3953,42 +4228,30 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
     }
 }
 
-fn type_impls_bound<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
-                             cache: &RefCell<HashMap<Ty<'tcx>,bool>>,
+fn type_impls_bound<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
+                             tcx: &ty::ctxt<'tcx>,
                              ty: Ty<'tcx>,
                              bound: ty::BuiltinBound,
                              span: Span)
                              -> bool
 {
-    assert!(!ty::type_needs_infer(ty));
-
-    if !type_has_params(ty) && !type_has_self(ty) {
-        match cache.borrow().get(&ty) {
-            None => {}
-            Some(&result) => {
-                debug!("type_impls_bound({}, {:?}) = {:?} (cached)",
-                       ty.repr(param_env.tcx),
-                       bound,
-                       result);
-                return result
-            }
+    let pe;
+    let param_env = match param_env {
+        Some(e) => e,
+        None => {
+            pe = empty_parameter_environment(tcx);
+            &pe
         }
-    }
-
-    let infcx = infer::new_infer_ctxt(param_env.tcx);
+    };
+    let infcx = infer::new_infer_ctxt(tcx);
 
     let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span);
 
-    debug!("type_impls_bound({}, {:?}) = {:?}",
-           ty.repr(param_env.tcx),
+    debug!("type_impls_bound({:?}, {:?}) = {:?}",
+           ty,
            bound,
            is_impld);
 
-    if !type_has_params(ty) && !type_has_self(ty) {
-        let old_value = cache.borrow_mut().insert(ty, is_impld);
-        assert!(old_value.is_none());
-    }
-
     is_impld
 }
 
@@ -3997,17 +4260,85 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
                                       ty: Ty<'tcx>)
                                       -> bool
 {
-    let tcx = param_env.tcx;
-    !type_impls_bound(param_env, &tcx.type_impls_copy_cache, ty, ty::BoundCopy, span)
+    if ty.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
+        return ty.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
+    }
+
+    assert!(!ty::type_needs_infer(ty));
+
+    // Fast-path for primitive types
+    let result = match ty.sty {
+        TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+        TyRawPtr(..) | TyBareFn(..) | TyRef(_, mt {
+            mutbl: ast::MutImmutable, ..
+        }) => Some(false),
+
+        TyStr | TyBox(..) | TyRef(_, mt {
+            mutbl: ast::MutMutable, ..
+        }) => Some(true),
+
+        TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
+        TyClosure(..) | TyEnum(..) | TyStruct(..) |
+        TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
+    }.unwrap_or_else(|| !type_impls_bound(Some(param_env),
+                                          param_env.tcx,
+                                          ty,
+                                          ty::BoundCopy,
+                                          span));
+
+    if !type_has_params(ty) && !type_has_self(ty) {
+        ty.flags.set(ty.flags.get() | if result {
+            TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
+        } else {
+            TypeFlags::MOVENESS_CACHED
+        });
+    }
+
+    result
 }
 
-pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
+#[inline]
+pub fn type_is_sized<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
+                              tcx: &ty::ctxt<'tcx>,
                               span: Span,
                               ty: Ty<'tcx>)
                               -> bool
 {
-    let tcx = param_env.tcx;
-    type_impls_bound(param_env, &tcx.type_impls_sized_cache, ty, ty::BoundSized, span)
+    if ty.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
+        let result = ty.flags.get().intersects(TypeFlags::IS_SIZED);
+        return result;
+    }
+
+    type_is_sized_uncached(param_env, tcx, span, ty)
+}
+
+fn type_is_sized_uncached<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
+                                   tcx: &ty::ctxt<'tcx>,
+                                   span: Span,
+                                   ty: Ty<'tcx>) -> bool {
+    assert!(!ty::type_needs_infer(ty));
+
+    // Fast-path for primitive types
+    let result = match ty.sty {
+        TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+        TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
+        TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
+
+        TyStr | TyTrait(..) | TySlice(_) => Some(false),
+
+        TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
+        TyInfer(..) | TyError => None
+    }.unwrap_or_else(|| type_impls_bound(param_env, tcx, ty, ty::BoundSized, span));
+
+    if !type_has_params(ty) && !type_has_self(ty) {
+        ty.flags.set(ty.flags.get() | if result {
+            TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
+        } else {
+            TypeFlags::SIZEDNESS_CACHED
+        });
+    }
+
+    result
 }
 
 pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -4019,63 +4350,59 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
     fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
                            r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
         debug!("type_requires({:?}, {:?})?",
-               ::util::ppaux::ty_to_string(cx, r_ty),
-               ::util::ppaux::ty_to_string(cx, ty));
+               r_ty, ty);
 
         let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
 
         debug!("type_requires({:?}, {:?})? {:?}",
-               ::util::ppaux::ty_to_string(cx, r_ty),
-               ::util::ppaux::ty_to_string(cx, ty),
-               r);
+               r_ty, ty, r);
         return r;
     }
 
     fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
                               r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
         debug!("subtypes_require({:?}, {:?})?",
-               ::util::ppaux::ty_to_string(cx, r_ty),
-               ::util::ppaux::ty_to_string(cx, ty));
+               r_ty, ty);
 
         let r = match ty.sty {
             // fixed length vectors need special treatment compared to
             // normal vectors, since they don't necessarily have the
             // possibility to have length zero.
-            ty_vec(_, Some(0)) => false, // don't need no contents
-            ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
-
-            ty_bool |
-            ty_char |
-            ty_int(_) |
-            ty_uint(_) |
-            ty_float(_) |
-            ty_str |
-            ty_bare_fn(..) |
-            ty_param(_) |
-            ty_projection(_) |
-            ty_vec(_, None) => {
+            TyArray(_, 0) => false, // don't need no contents
+            TyArray(ty, _) => type_requires(cx, seen, r_ty, ty),
+
+            TyBool |
+            TyChar |
+            TyInt(_) |
+            TyUint(_) |
+            TyFloat(_) |
+            TyStr |
+            TyBareFn(..) |
+            TyParam(_) |
+            TyProjection(_) |
+            TySlice(_) => {
                 false
             }
-            ty_uniq(typ) => {
+            TyBox(typ) => {
                 type_requires(cx, seen, r_ty, typ)
             }
-            ty_rptr(_, ref mt) => {
+            TyRef(_, ref mt) => {
                 type_requires(cx, seen, r_ty, mt.ty)
             }
 
-            ty_ptr(..) => {
+            TyRawPtr(..) => {
                 false           // unsafe ptrs can always be NULL
             }
 
-            ty_trait(..) => {
+            TyTrait(..) => {
                 false
             }
 
-            ty_struct(ref did, _) if seen.contains(did) => {
+            TyStruct(ref did, _) if seen.contains(did) => {
                 false
             }
 
-            ty_struct(did, substs) => {
+            TyStruct(did, substs) => {
                 seen.push(did);
                 let fields = struct_fields(cx, did, substs);
                 let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
@@ -4083,23 +4410,23 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
                 r
             }
 
-            ty_err |
-            ty_infer(_) |
-            ty_closure(..) => {
+            TyError |
+            TyInfer(_) |
+            TyClosure(..) => {
                 // this check is run on type definitions, so we don't expect to see
                 // inference by-products or closure types
                 cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
             }
 
-            ty_tup(ref ts) => {
+            TyTuple(ref ts) => {
                 ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
             }
 
-            ty_enum(ref did, _) if seen.contains(did) => {
+            TyEnum(ref did, _) if seen.contains(did) => {
                 false
             }
 
-            ty_enum(did, substs) => {
+            TyEnum(did, substs) => {
                 seen.push(did);
                 let vs = enum_variants(cx, did);
                 let r = !vs.is_empty() && vs.iter().all(|variant| {
@@ -4114,9 +4441,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
         };
 
         debug!("subtypes_require({:?}, {:?})? {:?}",
-               ::util::ppaux::ty_to_string(cx, r_ty),
-               ::util::ppaux::ty_to_string(cx, ty),
-               r);
+               r_ty, ty, r);
 
         return r;
     }
@@ -4158,27 +4483,27 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
                                        seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
                                        -> Representability {
         match ty.sty {
-            ty_tup(ref ts) => {
+            TyTuple(ref ts) => {
                 find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
             }
             // Fixed-length vectors.
             // FIXME(#11924) Behavior undecided for zero-length vectors.
-            ty_vec(ty, Some(_)) => {
+            TyArray(ty, _) => {
                 is_type_structurally_recursive(cx, sp, seen, ty)
             }
-            ty_struct(did, substs) => {
+            TyStruct(did, substs) => {
                 let fields = struct_fields(cx, did, substs);
                 find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
             }
-            ty_enum(did, substs) => {
+            TyEnum(did, substs) => {
                 let vs = enum_variants(cx, did);
                 let iter = vs.iter()
-                    .flat_map(|variant| { variant.args.iter() })
+                    .flat_map(|variant| &variant.args)
                     .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
 
                 find_nonrepresentable(cx, sp, seen, iter)
             }
-            ty_closure(..) => {
+            TyClosure(..) => {
                 // this check is run on type definitions, so we don't expect
                 // to see closure types
                 cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
@@ -4189,7 +4514,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
 
     fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool {
         match ty.sty {
-            ty_struct(ty_did, _) | ty_enum(ty_did, _) => {
+            TyStruct(ty_did, _) | TyEnum(ty_did, _) => {
                  ty_did == did
             }
             _ => false
@@ -4198,8 +4523,8 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
 
     fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         match (&a.sty, &b.sty) {
-            (&ty_struct(did_a, ref substs_a), &ty_struct(did_b, ref substs_b)) |
-            (&ty_enum(did_a, ref substs_a), &ty_enum(did_b, ref substs_b)) => {
+            (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
+            (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
                 if did_a != did_b {
                     return false;
                 }
@@ -4207,7 +4532,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
                 let types_a = substs_a.types.get_slice(subst::TypeSpace);
                 let types_b = substs_b.types.get_slice(subst::TypeSpace);
 
-                let mut pairs = types_a.iter().zip(types_b.iter());
+                let mut pairs = types_a.iter().zip(types_b);
 
                 pairs.all(|(&a, &b)| same_type(a, b))
             }
@@ -4222,11 +4547,10 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
     fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
                                             seen: &mut Vec<Ty<'tcx>>,
                                             ty: Ty<'tcx>) -> Representability {
-        debug!("is_type_structurally_recursive: {:?}",
-               ::util::ppaux::ty_to_string(cx, ty));
+        debug!("is_type_structurally_recursive: {:?}", ty);
 
         match ty.sty {
-            ty_struct(did, _) | ty_enum(did, _) => {
+            TyStruct(did, _) | TyEnum(did, _) => {
                 {
                     // Iterate through stack of previously seen types.
                     let mut iter = seen.iter();
@@ -4243,8 +4567,8 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
                         Some(&seen_type) => {
                             if same_struct_or_enum_def_id(seen_type, did) {
                                 debug!("SelfRecursive: {:?} contains {:?}",
-                                       ::util::ppaux::ty_to_string(cx, seen_type),
-                                       ::util::ppaux::ty_to_string(cx, ty));
+                                       seen_type,
+                                       ty);
                                 return SelfRecursive;
                             }
                         }
@@ -4263,8 +4587,8 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
                     for &seen_type in iter {
                         if same_type(ty, seen_type) {
                             debug!("ContainsRecursive: {:?} contains {:?}",
-                                   ::util::ppaux::ty_to_string(cx, seen_type),
-                                   ::util::ppaux::ty_to_string(cx, ty));
+                                   seen_type,
+                                   ty);
                             return ContainsRecursive;
                         }
                     }
@@ -4284,81 +4608,71 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
         }
     }
 
-    debug!("is_type_representable: {:?}",
-           ::util::ppaux::ty_to_string(cx, ty));
+    debug!("is_type_representable: {:?}", ty);
 
     // To avoid a stack overflow when checking an enum variant or struct that
     // contains a different, structurally recursive type, maintain a stack
     // of seen types and check recursion for each of them (issues #3008, #3779).
     let mut seen: Vec<Ty> = Vec::new();
     let r = is_type_structurally_recursive(cx, sp, &mut seen, ty);
-    debug!("is_type_representable: {:?} is {:?}",
-           ::util::ppaux::ty_to_string(cx, ty), r);
+    debug!("is_type_representable: {:?} is {:?}", ty, r);
     r
 }
 
 pub fn type_is_trait(ty: Ty) -> bool {
-    type_trait_info(ty).is_some()
-}
-
-pub fn type_trait_info<'tcx>(ty: Ty<'tcx>) -> Option<&'tcx TyTrait<'tcx>> {
     match ty.sty {
-        ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match ty.sty {
-            ty_trait(ref t) => Some(&**t),
-            _ => None
-        },
-        ty_trait(ref t) => Some(&**t),
-        _ => None
+        TyTrait(..) => true,
+        _ => false
     }
 }
 
 pub fn type_is_integral(ty: Ty) -> bool {
     match ty.sty {
-      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
+      TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
       _ => false
     }
 }
 
 pub fn type_is_fresh(ty: Ty) -> bool {
     match ty.sty {
-      ty_infer(FreshTy(_)) => true,
-      ty_infer(FreshIntTy(_)) => true,
-      ty_infer(FreshFloatTy(_)) => true,
+      TyInfer(FreshTy(_)) => true,
+      TyInfer(FreshIntTy(_)) => true,
+      TyInfer(FreshFloatTy(_)) => true,
       _ => false
     }
 }
 
 pub fn type_is_uint(ty: Ty) -> bool {
     match ty.sty {
-      ty_infer(IntVar(_)) | ty_uint(ast::TyUs) => true,
+      TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true,
       _ => false
     }
 }
 
 pub fn type_is_char(ty: Ty) -> bool {
     match ty.sty {
-        ty_char => true,
+        TyChar => true,
         _ => false
     }
 }
 
 pub fn type_is_bare_fn(ty: Ty) -> bool {
     match ty.sty {
-        ty_bare_fn(..) => true,
+        TyBareFn(..) => true,
         _ => false
     }
 }
 
 pub fn type_is_bare_fn_item(ty: Ty) -> bool {
     match ty.sty {
-        ty_bare_fn(Some(_), _) => true,
+        TyBareFn(Some(_), _) => true,
         _ => false
     }
 }
 
 pub fn type_is_fp(ty: Ty) -> bool {
     match ty.sty {
-      ty_infer(FloatVar(_)) | ty_float(_) => true,
+      TyInfer(FloatVar(_)) | TyFloat(_) => true,
       _ => false
     }
 }
@@ -4369,15 +4683,15 @@ pub fn type_is_numeric(ty: Ty) -> bool {
 
 pub fn type_is_signed(ty: Ty) -> bool {
     match ty.sty {
-      ty_int(_) => true,
+      TyInt(_) => true,
       _ => false
     }
 }
 
 pub fn type_is_machine(ty: Ty) -> bool {
     match ty.sty {
-        ty_int(ast::TyIs) | ty_uint(ast::TyUs) => false,
-        ty_int(..) | ty_uint(..) | ty_float(..) => true,
+        TyInt(ast::TyIs) | TyUint(ast::TyUs) => false,
+        TyInt(..) | TyUint(..) | TyFloat(..) => true,
         _ => false
     }
 }
@@ -4386,7 +4700,7 @@ pub fn type_is_machine(ty: Ty) -> bool {
 // constructors
 pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
     match ty.sty {
-        ty_enum(did, _) => {
+        TyEnum(did, _) => {
             let variants = enum_variants(cx, did);
             if variants.is_empty() {
                 false
@@ -4404,22 +4718,22 @@ pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
 pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
     match ty.sty {
-        ty_uniq(ty) => {
+        TyBox(ty) => {
             Some(mt {
                 ty: ty,
                 mutbl: ast::MutImmutable,
             })
         },
-        ty_rptr(_, mt) => Some(mt),
-        ty_ptr(mt) if explicit => Some(mt),
+        TyRef(_, mt) => Some(mt),
+        TyRawPtr(mt) if explicit => Some(mt),
         _ => None
     }
 }
 
 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
-        ty_uniq(ty) => ty,
-        ty_rptr(_, mt) | ty_ptr(mt) => mt.ty,
+        TyBox(ty) => ty,
+        TyRef(_, mt) | TyRawPtr(mt) => mt.ty,
         _ => ty
     }
 }
@@ -4427,7 +4741,7 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
 // Returns the type of ty[i]
 pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
-        ty_vec(ty, _) => Some(ty),
+        TyArray(ty, _) | TySlice(ty) => Some(ty),
         _ => None
     }
 }
@@ -4437,8 +4751,8 @@ pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
 // which can't actually be indexed.
 pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
-        ty_vec(ty, _) => Some(ty),
-        ty_str => Some(tcx.types.u8),
+        TyArray(ty, _) | TySlice(ty) => Some(ty),
+        TyStr => Some(tcx.types.u8),
         _ => None
     }
 }
@@ -4451,19 +4765,19 @@ pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>,
                                    variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
 
     match (&ty.sty, variant) {
-        (&ty_tup(ref v), None) => v.get(i).cloned(),
+        (&TyTuple(ref v), None) => v.get(i).cloned(),
 
 
-        (&ty_struct(def_id, substs), None) => lookup_struct_fields(cx, def_id)
+        (&TyStruct(def_id, substs), None) => lookup_struct_fields(cx, def_id)
             .get(i)
             .map(|&t|lookup_item_type(cx, t.id).ty.subst(cx, substs)),
 
-        (&ty_enum(def_id, substs), Some(variant_def_id)) => {
+        (&TyEnum(def_id, substs), Some(variant_def_id)) => {
             let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
             variant_info.args.get(i).map(|t|t.subst(cx, substs))
         }
 
-        (&ty_enum(def_id, substs), None) => {
+        (&TyEnum(def_id, substs), None) => {
             assert!(enum_is_univariant(cx, def_id));
             let enum_variants = enum_variants(cx, def_id);
             let variant_info = &(*enum_variants)[0];
@@ -4482,16 +4796,16 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
                               variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
 
     match (&ty.sty, variant) {
-        (&ty_struct(def_id, substs), None) => {
+        (&TyStruct(def_id, substs), None) => {
             let r = lookup_struct_fields(cx, def_id);
             r.iter().find(|f| f.name == n)
                 .map(|&f| lookup_field_type(cx, def_id, f.id, substs))
         }
-        (&ty_enum(def_id, substs), Some(variant_def_id)) => {
+        (&TyEnum(def_id, substs), Some(variant_def_id)) => {
             let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
             variant_info.arg_names.as_ref()
                 .expect("must have struct enum variant if accessing a named fields")
-                .iter().zip(variant_info.args.iter())
+                .iter().zip(&variant_info.args)
                 .find(|&(&name, _)| name == n)
                 .map(|(_name, arg_t)| arg_t.subst(cx, substs))
         }
@@ -4499,16 +4813,6 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
     }
 }
 
-pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
-                                  -> ty::TraitRef<'tcx> {
-    match cx.impl_trait_refs.borrow().get(&id) {
-        Some(ty) => *ty,
-        None => cx.sess.bug(
-            &format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
-                    cx.map.node_to_string(id)))
-    }
-}
-
 pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
     match node_id_to_type_opt(cx, id) {
        Some(ty) => ty,
@@ -4534,7 +4838,7 @@ pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts
 
 pub fn fn_is_variadic(fty: Ty) -> bool {
     match fty.sty {
-        ty_bare_fn(_, ref f) => f.sig.0.variadic,
+        TyBareFn(_, ref f) => f.sig.0.variadic,
         ref s => {
             panic!("fn_is_variadic() called on non-fn type: {:?}", s)
         }
@@ -4543,7 +4847,7 @@ pub fn fn_is_variadic(fty: Ty) -> bool {
 
 pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
     match fty.sty {
-        ty_bare_fn(_, ref f) => &f.sig,
+        TyBareFn(_, ref f) => &f.sig,
         ref s => {
             panic!("ty_fn_sig() called on non-fn type: {:?}", s)
         }
@@ -4553,7 +4857,7 @@ pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
 /// Returns the ABI of the given function.
 pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
     match fty.sty {
-        ty_bare_fn(_, ref f) => f.abi,
+        TyBareFn(_, ref f) => f.abi,
         _ => panic!("ty_fn_abi() called on non-fn type"),
     }
 }
@@ -4565,7 +4869,7 @@ pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder<Vec<Ty<'tcx>>> {
 
 pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> {
     match fty.sty {
-        ty_bare_fn(_, ref f) => f.sig.output(),
+        TyBareFn(_, ref f) => f.sig.output(),
         ref s => {
             panic!("ty_fn_ret() called on non-fn type: {:?}", s)
         }
@@ -4574,7 +4878,7 @@ pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> {
 
 pub fn is_fn_ty(fty: Ty) -> bool {
     match fty.sty {
-        ty_bare_fn(..) => true,
+        TyBareFn(..) => true,
         _ => false
     }
 }
@@ -4583,7 +4887,7 @@ pub fn ty_region(tcx: &ctxt,
                  span: Span,
                  ty: Ty) -> Region {
     match ty.sty {
-        ty_rptr(r, _) => *r,
+        TyRef(r, _) => *r,
         ref s => {
             tcx.sess.span_bug(
                 span,
@@ -4698,7 +5002,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                           -> Ty<'tcx> where
     F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
 {
-    if let ty_err = unadjusted_ty.sty {
+    if let TyError = unadjusted_ty.sty {
         return unadjusted_ty;
     }
 
@@ -4707,20 +5011,20 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
             match *adjustment {
                AdjustReifyFnPointer => {
                     match unadjusted_ty.sty {
-                        ty::ty_bare_fn(Some(_), b) => {
+                        ty::TyBareFn(Some(_), b) => {
                             ty::mk_bare_fn(cx, None, b)
                         }
                         _ => {
                             cx.sess.bug(
                                 &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                          {}", unadjusted_ty.repr(cx)));
+                                          {:?}", unadjusted_ty));
                         }
                     }
                 }
 
                AdjustUnsafeFnPointer => {
                     match unadjusted_ty.sty {
-                        ty::ty_bare_fn(None, b) => cx.safe_to_unsafe_fn_ty(b),
+                        ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
                         ref b => {
                             cx.sess.bug(
                                 &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
@@ -4754,7 +5058,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                                         span,
                                         &format!("the {}th autoderef failed: {}",
                                                 i,
-                                                ty_to_string(cx, adjusted_ty))
+                                                 adjusted_ty)
                                         );
                                 }
                             }
@@ -4798,96 +5102,27 @@ pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
     }
 }
 
-pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
-    match expr_kind(tcx, e) {
-        LvalueExpr => true,
-        RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
-    }
-}
-
-/// We categorize expressions into three kinds.  The distinction between
-/// lvalue/rvalue is fundamental to the language.  The distinction between the
-/// two kinds of rvalues is an artifact of trans which reflects how we will
-/// generate code for that kind of expression.  See trans/expr.rs for more
-/// information.
-#[derive(Copy, Clone)]
-pub enum ExprKind {
-    LvalueExpr,
-    RvalueDpsExpr,
-    RvalueDatumExpr,
-    RvalueStmtExpr
-}
-
-pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
-    if tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)) {
-        // Overloaded operations are generally calls, and hence they are
-        // generated via DPS, but there are a few exceptions:
-        return match expr.node {
-            // `a += b` has a unit result.
-            ast::ExprAssignOp(..) => RvalueStmtExpr,
-
-            // the deref method invoked for `*a` always yields an `&T`
-            ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
-
-            // the index method invoked for `a[i]` always yields an `&T`
-            ast::ExprIndex(..) => LvalueExpr,
-
-            // in the general case, result could be any type, use DPS
-            _ => RvalueDpsExpr
-        };
-    }
-
-    match expr.node {
+pub fn expr_is_lval(tcx: &ctxt, expr: &ast::Expr) -> bool {
+     match expr.node {
         ast::ExprPath(..) => {
-            match resolve_expr(tcx, expr) {
-                def::DefVariant(tid, vid, _) => {
-                    let variant_info = enum_variant_with_id(tcx, tid, vid);
-                    if !variant_info.args.is_empty() {
-                        // N-ary variant.
-                        RvalueDatumExpr
-                    } else {
-                        // Nullary variant.
-                        RvalueDpsExpr
-                    }
+            // We can't use resolve_expr here, as this needs to run on broken
+            // programs. We don't need to through - associated items are all
+            // rvalues.
+            match tcx.def_map.borrow().get(&expr.id) {
+                Some(&def::PathResolution {
+                    base_def: def::DefStatic(..), ..
+                }) | Some(&def::PathResolution {
+                    base_def: def::DefUpvar(..), ..
+                }) | Some(&def::PathResolution {
+                    base_def: def::DefLocal(..), ..
+                }) => {
+                    true
                 }
 
-                def::DefStruct(_) => {
-                    match tcx.node_types.borrow().get(&expr.id) {
-                        Some(ty) => match ty.sty {
-                            ty_bare_fn(..) => RvalueDatumExpr,
-                            _ => RvalueDpsExpr
-                        },
-                        // See ExprCast below for why types might be missing.
-                        None => RvalueDatumExpr
-                     }
-                }
+                Some(..) => false,
 
-                // Special case: A unit like struct's constructor must be called without () at the
-                // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
-                // of unit structs this is should not be interpreted as function pointer but as
-                // call to the constructor.
-                def::DefFn(_, true) => RvalueDpsExpr,
-
-                // Fn pointers are just scalar values.
-                def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr,
-
-                // Note: there is actually a good case to be made that
-                // DefArg's, particularly those of immediate type, ought to
-                // considered rvalues.
-                def::DefStatic(..) |
-                def::DefUpvar(..) |
-                def::DefLocal(..) => LvalueExpr,
-
-                def::DefConst(..) |
-                def::DefAssociatedConst(..) => RvalueDatumExpr,
-
-                def => {
-                    tcx.sess.span_bug(
-                        expr.span,
-                        &format!("uncategorized def for expr {}: {:?}",
-                                expr.id,
-                                def));
-                }
+                None => tcx.sess.span_bug(expr.span, &format!(
+                    "no def for path {}", expr.id))
             }
         }
 
@@ -4895,7 +5130,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprField(..) |
         ast::ExprTupField(..) |
         ast::ExprIndex(..) => {
-            LvalueExpr
+            true
         }
 
         ast::ExprCall(..) |
@@ -4908,25 +5143,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprClosure(..) |
         ast::ExprBlock(..) |
         ast::ExprRepeat(..) |
-        ast::ExprVec(..) => {
-            RvalueDpsExpr
-        }
-
-        ast::ExprIfLet(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-        }
-        ast::ExprWhileLet(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-        }
-
-        ast::ExprForLoop(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-        }
-
-        ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
-            RvalueDpsExpr
-        }
-
+        ast::ExprVec(..) |
         ast::ExprBreak(..) |
         ast::ExprAgain(..) |
         ast::ExprRet(..) |
@@ -4934,34 +5151,21 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprLoop(..) |
         ast::ExprAssign(..) |
         ast::ExprInlineAsm(..) |
-        ast::ExprAssignOp(..) => {
-            RvalueStmtExpr
-        }
-
-        ast::ExprLit(_) | // Note: LitStr is carved out above
+        ast::ExprAssignOp(..) |
+        ast::ExprLit(_) |
         ast::ExprUnary(..) |
-        ast::ExprBox(None, _) |
+        ast::ExprBox(..) |
         ast::ExprAddrOf(..) |
         ast::ExprBinary(..) |
         ast::ExprCast(..) => {
-            RvalueDatumExpr
-        }
-
-        ast::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) {
-                RvalueDatumExpr
-            } else {
-                RvalueDpsExpr
-            }
+            false
         }
 
-        ast::ExprParen(ref e) => expr_kind(tcx, &**e),
+        ast::ExprParen(ref e) => expr_is_lval(tcx, e),
 
+        ast::ExprIfLet(..) |
+        ast::ExprWhileLet(..) |
+        ast::ExprForLoop(..) |
         ast::ExprMac(..) => {
             tcx.sess.span_bug(
                 expr.span,
@@ -4996,51 +5200,43 @@ pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
     trait_items.iter().position(|m| m.name() == id)
 }
 
-pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
+pub fn ty_sort_string(cx: &ctxt, ty: Ty) -> String {
     match ty.sty {
-        ty_bool | ty_char | ty_int(_) |
-        ty_uint(_) | ty_float(_) | ty_str => {
-            ::util::ppaux::ty_to_string(cx, ty)
-        }
-        ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, ty),
-
-        ty_enum(id, _) => format!("enum `{}`", item_path_str(cx, id)),
-        ty_uniq(_) => "box".to_string(),
-        ty_vec(_, Some(n)) => format!("array of {} elements", n),
-        ty_vec(_, None) => "slice".to_string(),
-        ty_ptr(_) => "*-ptr".to_string(),
-        ty_rptr(_, _) => "&-ptr".to_string(),
-        ty_bare_fn(Some(_), _) => format!("fn item"),
-        ty_bare_fn(None, _) => "fn pointer".to_string(),
-        ty_trait(ref inner) => {
+        TyBool | TyChar | TyInt(_) |
+        TyUint(_) | TyFloat(_) | TyStr => ty.to_string(),
+        TyTuple(ref tys) if tys.is_empty() => ty.to_string(),
+
+        TyEnum(id, _) => format!("enum `{}`", item_path_str(cx, id)),
+        TyBox(_) => "box".to_string(),
+        TyArray(_, n) => format!("array of {} elements", n),
+        TySlice(_) => "slice".to_string(),
+        TyRawPtr(_) => "*-ptr".to_string(),
+        TyRef(_, _) => "&-ptr".to_string(),
+        TyBareFn(Some(_), _) => format!("fn item"),
+        TyBareFn(None, _) => "fn pointer".to_string(),
+        TyTrait(ref inner) => {
             format!("trait {}", item_path_str(cx, inner.principal_def_id()))
         }
-        ty_struct(id, _) => {
+        TyStruct(id, _) => {
             format!("struct `{}`", item_path_str(cx, id))
         }
-        ty_closure(..) => "closure".to_string(),
-        ty_tup(_) => "tuple".to_string(),
-        ty_infer(TyVar(_)) => "inferred type".to_string(),
-        ty_infer(IntVar(_)) => "integral variable".to_string(),
-        ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
-        ty_infer(FreshTy(_)) => "skolemized type".to_string(),
-        ty_infer(FreshIntTy(_)) => "skolemized integral type".to_string(),
-        ty_infer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
-        ty_projection(_) => "associated type".to_string(),
-        ty_param(ref p) => {
+        TyClosure(..) => "closure".to_string(),
+        TyTuple(_) => "tuple".to_string(),
+        TyInfer(TyVar(_)) => "inferred type".to_string(),
+        TyInfer(IntVar(_)) => "integral variable".to_string(),
+        TyInfer(FloatVar(_)) => "floating-point variable".to_string(),
+        TyInfer(FreshTy(_)) => "skolemized type".to_string(),
+        TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(),
+        TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
+        TyProjection(_) => "associated type".to_string(),
+        TyParam(ref p) => {
             if p.space == subst::SelfSpace {
                 "Self".to_string()
             } else {
                 "type parameter".to_string()
             }
         }
-        ty_err => "type error".to_string(),
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        ty::type_err_to_str(tcx, self)
+        TyError => "type error".to_string(),
     }
 }
 
@@ -5048,128 +5244,128 @@ impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
 /// afterwards to present additional details, particularly when it comes to lifetime-related
 /// errors.
-pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
-    match *err {
-        terr_cyclic_ty => "cyclic type of infinite size".to_string(),
-        terr_mismatch => "types differ".to_string(),
-        terr_unsafety_mismatch(values) => {
-            format!("expected {} fn, found {} fn",
-                    values.expected,
-                    values.found)
-        }
-        terr_abi_mismatch(values) => {
-            format!("expected {} fn, found {} fn",
-                    values.expected,
-                    values.found)
-        }
-        terr_mutability => "values differ in mutability".to_string(),
-        terr_box_mutability => {
-            "boxed values differ in mutability".to_string()
-        }
-        terr_vec_mutability => "vectors differ in mutability".to_string(),
-        terr_ptr_mutability => "pointers differ in mutability".to_string(),
-        terr_ref_mutability => "references differ in mutability".to_string(),
-        terr_ty_param_size(values) => {
-            format!("expected a type with {} type params, \
-                     found one with {} type params",
-                    values.expected,
-                    values.found)
-        }
-        terr_fixed_array_size(values) => {
-            format!("expected an array with a fixed size of {} elements, \
-                     found one with {} elements",
-                    values.expected,
-                    values.found)
-        }
-        terr_tuple_size(values) => {
-            format!("expected a tuple with {} elements, \
-                     found one with {} elements",
-                    values.expected,
-                    values.found)
-        }
-        terr_arg_count => {
-            "incorrect number of function parameters".to_string()
-        }
-        terr_regions_does_not_outlive(..) => {
-            "lifetime mismatch".to_string()
-        }
-        terr_regions_not_same(..) => {
-            "lifetimes are not the same".to_string()
-        }
-        terr_regions_no_overlap(..) => {
-            "lifetimes do not intersect".to_string()
-        }
-        terr_regions_insufficiently_polymorphic(br, _) => {
-            format!("expected bound lifetime parameter {}, \
-                     found concrete lifetime",
-                    bound_region_ptr_to_string(cx, br))
-        }
-        terr_regions_overly_polymorphic(br, _) => {
-            format!("expected concrete lifetime, \
-                     found bound lifetime parameter {}",
-                    bound_region_ptr_to_string(cx, br))
-        }
-        terr_sorts(values) => {
-            // A naive approach to making sure that we're not reporting silly errors such as:
-            // (expected closure, found closure).
-            let expected_str = ty_sort_string(cx, values.expected);
-            let found_str = ty_sort_string(cx, values.found);
-            if expected_str == found_str {
-                format!("expected {}, found a different {}", expected_str, found_str)
-            } else {
-                format!("expected {}, found {}", expected_str, found_str)
+impl<'tcx> fmt::Display for type_err<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            terr_cyclic_ty => write!(f, "cyclic type of infinite size"),
+            terr_mismatch => write!(f, "types differ"),
+            terr_unsafety_mismatch(values) => {
+                write!(f, "expected {} fn, found {} fn",
+                       values.expected,
+                       values.found)
+            }
+            terr_abi_mismatch(values) => {
+                write!(f, "expected {} fn, found {} fn",
+                       values.expected,
+                       values.found)
+            }
+            terr_mutability => write!(f, "values differ in mutability"),
+            terr_box_mutability => {
+                write!(f, "boxed values differ in mutability")
+            }
+            terr_vec_mutability => write!(f, "vectors differ in mutability"),
+            terr_ptr_mutability => write!(f, "pointers differ in mutability"),
+            terr_ref_mutability => write!(f, "references differ in mutability"),
+            terr_ty_param_size(values) => {
+                write!(f, "expected a type with {} type params, \
+                           found one with {} type params",
+                       values.expected,
+                       values.found)
+            }
+            terr_fixed_array_size(values) => {
+                write!(f, "expected an array with a fixed size of {} elements, \
+                           found one with {} elements",
+                       values.expected,
+                       values.found)
+            }
+            terr_tuple_size(values) => {
+                write!(f, "expected a tuple with {} elements, \
+                           found one with {} elements",
+                       values.expected,
+                       values.found)
+            }
+            terr_arg_count => {
+                write!(f, "incorrect number of function parameters")
+            }
+            terr_regions_does_not_outlive(..) => {
+                write!(f, "lifetime mismatch")
+            }
+            terr_regions_not_same(..) => {
+                write!(f, "lifetimes are not the same")
+            }
+            terr_regions_no_overlap(..) => {
+                write!(f, "lifetimes do not intersect")
+            }
+            terr_regions_insufficiently_polymorphic(br, _) => {
+                write!(f, "expected bound lifetime parameter {}, \
+                           found concrete lifetime", br)
+            }
+            terr_regions_overly_polymorphic(br, _) => {
+                write!(f, "expected concrete lifetime, \
+                           found bound lifetime parameter {}", br)
+            }
+            terr_sorts(values) => tls::with(|tcx| {
+                // A naive approach to making sure that we're not reporting silly errors such as:
+                // (expected closure, found closure).
+                let expected_str = ty_sort_string(tcx, values.expected);
+                let found_str = ty_sort_string(tcx, values.found);
+                if expected_str == found_str {
+                    write!(f, "expected {}, found a different {}", expected_str, found_str)
+                } else {
+                    write!(f, "expected {}, found {}", expected_str, found_str)
+                }
+            }),
+            terr_traits(values) => tls::with(|tcx| {
+                write!(f, "expected trait `{}`, found trait `{}`",
+                       item_path_str(tcx, values.expected),
+                       item_path_str(tcx, values.found))
+            }),
+            terr_builtin_bounds(values) => {
+                if values.expected.is_empty() {
+                    write!(f, "expected no bounds, found `{}`",
+                           values.found)
+                } else if values.found.is_empty() {
+                    write!(f, "expected bounds `{}`, found no bounds",
+                           values.expected)
+                } else {
+                    write!(f, "expected bounds `{}`, found bounds `{}`",
+                           values.expected,
+                           values.found)
+                }
             }
-        }
-        terr_traits(values) => {
-            format!("expected trait `{}`, found trait `{}`",
-                    item_path_str(cx, values.expected),
-                    item_path_str(cx, values.found))
-        }
-        terr_builtin_bounds(values) => {
-            if values.expected.is_empty() {
-                format!("expected no bounds, found `{}`",
-                        values.found.user_string(cx))
-            } else if values.found.is_empty() {
-                format!("expected bounds `{}`, found no bounds",
-                        values.expected.user_string(cx))
-            } else {
-                format!("expected bounds `{}`, found bounds `{}`",
-                        values.expected.user_string(cx),
-                        values.found.user_string(cx))
+            terr_integer_as_char => {
+                write!(f, "expected an integral type, found `char`")
+            }
+            terr_int_mismatch(ref values) => {
+                write!(f, "expected `{:?}`, found `{:?}`",
+                       values.expected,
+                       values.found)
+            }
+            terr_float_mismatch(ref values) => {
+                write!(f, "expected `{:?}`, found `{:?}`",
+                       values.expected,
+                       values.found)
+            }
+            terr_variadic_mismatch(ref values) => {
+                write!(f, "expected {} fn, found {} function",
+                       if values.expected { "variadic" } else { "non-variadic" },
+                       if values.found { "variadic" } else { "non-variadic" })
+            }
+            terr_convergence_mismatch(ref values) => {
+                write!(f, "expected {} fn, found {} function",
+                       if values.expected { "converging" } else { "diverging" },
+                       if values.found { "converging" } else { "diverging" })
+            }
+            terr_projection_name_mismatched(ref values) => {
+                write!(f, "expected {}, found {}",
+                       values.expected,
+                       values.found)
+            }
+            terr_projection_bounds_length(ref values) => {
+                write!(f, "expected {} associated type bindings, found {}",
+                       values.expected,
+                       values.found)
             }
-        }
-        terr_integer_as_char => {
-            "expected an integral type, found `char`".to_string()
-        }
-        terr_int_mismatch(ref values) => {
-            format!("expected `{:?}`, found `{:?}`",
-                    values.expected,
-                    values.found)
-        }
-        terr_float_mismatch(ref values) => {
-            format!("expected `{:?}`, found `{:?}`",
-                    values.expected,
-                    values.found)
-        }
-        terr_variadic_mismatch(ref values) => {
-            format!("expected {} fn, found {} function",
-                    if values.expected { "variadic" } else { "non-variadic" },
-                    if values.found { "variadic" } else { "non-variadic" })
-        }
-        terr_convergence_mismatch(ref values) => {
-            format!("expected {} fn, found {} function",
-                    if values.expected { "converging" } else { "diverging" },
-                    if values.found { "converging" } else { "diverging" })
-        }
-        terr_projection_name_mismatched(ref values) => {
-            format!("expected {}, found {}",
-                    token::get_name(values.expected),
-                    token::get_name(values.found))
-        }
-        terr_projection_bounds_length(ref values) => {
-            format!("expected {} associated type bindings, found {}",
-                    values.expected,
-                    values.found)
         }
     }
 }
@@ -5303,12 +5499,12 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
 /// the future).
 fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
                                           def_id: ast::DefId,
-                                          map: &mut DefIdMap<V>,
+                                          map: &RefCell<DefIdMap<V>>,
                                           load_external: F) -> V where
     V: Clone,
     F: FnOnce() -> V,
 {
-    match map.get(&def_id).cloned() {
+    match map.borrow().get(&def_id).cloned() {
         Some(v) => { return v; }
         None => { }
     }
@@ -5317,7 +5513,7 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
         panic!("No def'n found for {:?} in tcx.{}", def_id, descr);
     }
     let v = load_external();
-    map.insert(def_id, v.clone());
+    map.borrow_mut().insert(def_id, v.clone());
     v
 }
 
@@ -5383,33 +5579,9 @@ pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
 
 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                                 -> ImplOrTraitItem<'tcx> {
-    lookup_locally_or_in_crate_store("impl_or_trait_items",
-                                     id,
-                                     &mut *cx.impl_or_trait_items
-                                             .borrow_mut(),
-                                     || {
-        csearch::get_impl_or_trait_item(cx, id)
-    })
-}
-
-/// Returns true if the given ID refers to an associated type and false if it
-/// refers to anything else.
-pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
-    memoized(&cx.associated_types, id, |id: ast::DefId| {
-        if id.krate == ast::LOCAL_CRATE {
-            match cx.impl_or_trait_items.borrow().get(&id) {
-                Some(ref item) => {
-                    match **item {
-                        TypeTraitItem(_) => true,
-                        _ => false,
-                    }
-                }
-                None => false,
-            }
-        } else {
-            csearch::is_associated_type(&cx.sess.cstore, id)
-        }
-    })
+    lookup_locally_or_in_crate_store(
+        "impl_or_trait_items", id, &cx.impl_or_trait_items,
+        || csearch::get_impl_or_trait_item(cx, id))
 }
 
 /// Returns the parameter index that the given associated type corresponds to.
@@ -5417,7 +5589,7 @@ pub fn associated_type_parameter_index(cx: &ctxt,
                                        trait_def: &TraitDef,
                                        associated_type_id: ast::DefId)
                                        -> usize {
-    for type_parameter_def in trait_def.generics.types.iter() {
+    for type_parameter_def in &trait_def.generics.types {
         if type_parameter_def.def_id == associated_type_id {
             return type_parameter_def.index as usize
         }
@@ -5427,34 +5599,33 @@ pub fn associated_type_parameter_index(cx: &ctxt,
 
 pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
                           -> Rc<Vec<ImplOrTraitItemId>> {
-    lookup_locally_or_in_crate_store("trait_item_def_ids",
-                                     id,
-                                     &mut *cx.trait_item_def_ids.borrow_mut(),
-                                     || {
-        Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
-    })
+    lookup_locally_or_in_crate_store(
+        "trait_item_def_ids", id, &cx.trait_item_def_ids,
+        || Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id)))
 }
 
+/// Returns the trait-ref corresponding to a given impl, or None if it is
+/// an inherent impl.
 pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                            -> Option<TraitRef<'tcx>> {
-    memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
-        if id.krate == ast::LOCAL_CRATE {
-            debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-            if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
-                match item.node {
-                    ast::ItemImpl(_, _, _, Some(_), _, _) |
-                    ast::ItemDefaultImpl(..) => {
-                        Some(ty::impl_id_to_trait_ref(cx, id.node))
-                    }
-                    _ => None
-                }
-            } else {
-                None
-            }
+                            -> Option<TraitRef<'tcx>>
+{
+    lookup_locally_or_in_crate_store(
+        "impl_trait_refs", id, &cx.impl_trait_refs,
+        || csearch::get_impl_trait(cx, id))
+}
+
+/// Returns whether this DefId refers to an impl
+pub fn is_impl<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> bool {
+    if id.krate == ast::LOCAL_CRATE {
+        if let Some(ast_map::NodeItem(
+            &ast::Item { node: ast::ItemImpl(..), .. })) = cx.map.find(id.node) {
+            true
         } else {
-            csearch::get_impl_trait(cx, id)
+            false
         }
-    })
+    } else {
+        csearch::is_impl(&cx.sess.cstore, id)
+    }
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
@@ -5480,11 +5651,11 @@ pub fn try_add_builtin_trait(
 
 pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> {
     match ty.sty {
-        ty_trait(ref tt) =>
+        TyTrait(ref tt) =>
             Some(tt.principal_def_id()),
-        ty_struct(id, _) |
-        ty_enum(id, _) |
-        ty_closure(id, _) =>
+        TyStruct(id, _) |
+        TyEnum(id, _) |
+        TyClosure(id, _) =>
             Some(id),
         _ =>
             None
@@ -5638,7 +5809,7 @@ pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
 
 pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
     match ty.sty {
-       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
+       TyEnum(did, _) => (*enum_variants(cx, did)).is_empty(),
        _ => false
      }
 }
@@ -5801,7 +5972,7 @@ fn report_discrim_overflow(cx: &ctxt,
     let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
     let computed_value = repr_type.disr_string(computed_value);
     let prev_val = repr_type.disr_string(prev_val);
-    let repr_type = repr_type.to_ty(cx).user_string(cx);
+    let repr_type = repr_type.to_ty(cx);
     span_err!(cx.sess, variant_span, E0370,
               "enum discriminant overflowed on value after {}: {}; \
                set explicitly via {} = {} if that is desired outcome",
@@ -5851,8 +6022,8 @@ fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
                 // more robust (on case-by-case basis).
 
                 match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) {
-                    Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
-                    Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
+                    Ok(ConstVal::Int(val)) => current_disr_val = val as Disr,
+                    Ok(ConstVal::Uint(val)) => current_disr_val = val as Disr,
                     Ok(_) => {
                         let sign_desc = if repr_type.is_signed() { "signed" } else { "unsigned" };
                         span_err!(cx.sess, e.span, E0079,
@@ -5937,70 +6108,35 @@ pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
                               did: ast::DefId)
                               -> TypeScheme<'tcx> {
     lookup_locally_or_in_crate_store(
-        "tcache", did, &mut *cx.tcache.borrow_mut(),
+        "tcache", did, &cx.tcache,
         || csearch::get_type(cx, did))
 }
 
 /// Given the did of a trait, returns its canonical trait ref.
 pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                               -> &'tcx TraitDef<'tcx> {
-    memoized(&cx.trait_defs, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
-    })
+    lookup_locally_or_in_crate_store(
+        "trait_defs", did, &cx.trait_defs,
+        || cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
+    )
 }
 
 /// Given the did of an item, returns its full set of predicates.
 pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                                 -> GenericPredicates<'tcx>
 {
-    memoized(&cx.predicates, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        csearch::get_predicates(cx, did)
-    })
+    lookup_locally_or_in_crate_store(
+        "predicates", did, &cx.predicates,
+        || csearch::get_predicates(cx, did))
 }
 
 /// Given the did of a trait, returns its superpredicates.
 pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                                      -> GenericPredicates<'tcx>
 {
-    memoized(&cx.super_predicates, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        csearch::get_super_predicates(cx, did)
-    })
-}
-
-pub fn predicates<'tcx>(
-    tcx: &ctxt<'tcx>,
-    param_ty: Ty<'tcx>,
-    bounds: &ParamBounds<'tcx>)
-    -> Vec<Predicate<'tcx>>
-{
-    let mut vec = Vec::new();
-
-    for builtin_bound in &bounds.builtin_bounds {
-        match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
-            Ok(trait_ref) => { vec.push(trait_ref.as_predicate()); }
-            Err(ErrorReported) => { }
-        }
-    }
-
-    for &region_bound in &bounds.region_bounds {
-        // account for the binder being introduced below; no need to shift `param_ty`
-        // because, at present at least, it can only refer to early-bound regions
-        let region_bound = ty_fold::shift_region(region_bound, 1);
-        vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).as_predicate());
-    }
-
-    for bound_trait_ref in &bounds.trait_bounds {
-        vec.push(bound_trait_ref.as_predicate());
-    }
-
-    for projection in &bounds.projection_bounds {
-        vec.push(projection.as_predicate());
-    }
-
-    vec
+    lookup_locally_or_in_crate_store(
+        "super_predicates", did, &cx.super_predicates,
+        || csearch::get_super_predicates(cx, did))
 }
 
 /// Get the attributes of a definition.
@@ -6121,7 +6257,7 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
 /// if not a structure at all. Corresponds to the only possible unsized
 /// field, and its type can be used to determine unsizing strategy.
 pub fn struct_tail<'tcx>(cx: &ctxt<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> {
-    while let ty_struct(def_id, substs) = ty.sty {
+    while let TyStruct(def_id, substs) = ty.sty {
         match struct_fields(cx, def_id, substs).last() {
             Some(f) => ty = f.mt.ty,
             None => break
@@ -6140,7 +6276,7 @@ pub fn struct_lockstep_tails<'tcx>(cx: &ctxt<'tcx>,
                                    target: Ty<'tcx>)
                                    -> (Ty<'tcx>, Ty<'tcx>) {
     let (mut a, mut b) = (source, target);
-    while let (&ty_struct(a_did, a_substs), &ty_struct(b_did, b_substs)) = (&a.sty, &b.sty) {
+    while let (&TyStruct(a_did, a_substs), &TyStruct(b_did, b_substs)) = (&a.sty, &b.sty) {
         if a_did != b_did {
             continue;
         }
@@ -6227,15 +6363,15 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
     match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.usize)) {
         Ok(val) => {
             let found = match val {
-                const_eval::const_uint(count) => return count as usize,
-                const_eval::const_int(count) if count >= 0 => return count as usize,
-                const_eval::const_int(_) => "negative integer",
-                const_eval::const_float(_) => "float",
-                const_eval::const_str(_) => "string",
-                const_eval::const_bool(_) => "boolean",
-                const_eval::const_binary(_) => "binary array",
-                const_eval::Struct(..) => "struct",
-                const_eval::Tuple(_) => "tuple"
+                ConstVal::Uint(count) => return count as usize,
+                ConstVal::Int(count) if count >= 0 => return count as usize,
+                ConstVal::Int(_) => "negative integer",
+                ConstVal::Float(_) => "float",
+                ConstVal::Str(_) => "string",
+                ConstVal::Bool(_) => "boolean",
+                ConstVal::Binary(_) => "binary array",
+                ConstVal::Struct(..) => "struct",
+                ConstVal::Tuple(_) => "tuple"
             };
             span_err!(tcx.sess, count_expr.span, E0306,
                 "expected positive integer for repeat count, found {}",
@@ -6296,8 +6432,8 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
                                     -> Vec<ty::Region>
 {
     debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})",
-           erased_self_ty.repr(tcx),
-           predicates.repr(tcx));
+           erased_self_ty,
+           predicates);
 
     assert!(!erased_self_ty.has_escaping_regions());
 
@@ -6337,7 +6473,7 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
 
 pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
     lookup_locally_or_in_crate_store(
-        "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
+        "item_variance_map", item_id, &tcx.item_variance_map,
         || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
 }
 
@@ -6415,7 +6551,7 @@ pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast
         return;
     }
 
-    debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx));
+    debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
 
     if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
         record_trait_has_default_impl(tcx, trait_id);
@@ -6572,47 +6708,47 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
         };
         maybe_walk_ty(ty, |ty| {
             match ty.sty {
-                ty_bool => byte!(2),
-                ty_char => byte!(3),
-                ty_int(i) => {
+                TyBool => byte!(2),
+                TyChar => byte!(3),
+                TyInt(i) => {
                     byte!(4);
                     hash!(i);
                 }
-                ty_uint(u) => {
+                TyUint(u) => {
                     byte!(5);
                     hash!(u);
                 }
-                ty_float(f) => {
+                TyFloat(f) => {
                     byte!(6);
                     hash!(f);
                 }
-                ty_str => {
+                TyStr => {
                     byte!(7);
                 }
-                ty_enum(d, _) => {
+                TyEnum(d, _) => {
                     byte!(8);
                     did(state, d);
                 }
-                ty_uniq(_) => {
+                TyBox(_) => {
                     byte!(9);
                 }
-                ty_vec(_, Some(n)) => {
+                TyArray(_, n) => {
                     byte!(10);
                     n.hash(state);
                 }
-                ty_vec(_, None) => {
+                TySlice(_) => {
                     byte!(11);
                 }
-                ty_ptr(m) => {
+                TyRawPtr(m) => {
                     byte!(12);
                     mt(state, m);
                 }
-                ty_rptr(r, m) => {
+                TyRef(r, m) => {
                     byte!(13);
                     region(state, *r);
                     mt(state, m);
                 }
-                ty_bare_fn(opt_def_id, ref b) => {
+                TyBareFn(opt_def_id, ref b) => {
                     byte!(14);
                     hash!(opt_def_id);
                     hash!(b.unsafety);
@@ -6620,39 +6756,39 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                     fn_sig(state, &b.sig);
                     return false;
                 }
-                ty_trait(ref data) => {
+                TyTrait(ref data) => {
                     byte!(17);
                     did(state, data.principal_def_id());
                     hash!(data.bounds);
 
                     let principal = anonymize_late_bound_regions(tcx, &data.principal).0;
-                    for subty in principal.substs.types.iter() {
-                        helper(tcx, *subty, svh, state);
+                    for subty in &principal.substs.types {
+                        helper(tcx, subty, svh, state);
                     }
 
                     return false;
                 }
-                ty_struct(d, _) => {
+                TyStruct(d, _) => {
                     byte!(18);
                     did(state, d);
                 }
-                ty_tup(ref inner) => {
+                TyTuple(ref inner) => {
                     byte!(19);
                     hash!(inner.len());
                 }
-                ty_param(p) => {
+                TyParam(p) => {
                     byte!(20);
                     hash!(p.space);
                     hash!(p.idx);
                     hash!(token::get_name(p.name));
                 }
-                ty_infer(_) => unreachable!(),
-                ty_err => byte!(21),
-                ty_closure(d, _) => {
+                TyInfer(_) => unreachable!(),
+                TyError => byte!(21),
+                TyClosure(d, _) => {
                     byte!(22);
                     did(state, d);
                 }
-                ty_projection(ref data) => {
+                TyProjection(ref data) => {
                     byte!(23);
                     did(state, data.trait_ref.def_id);
                     hash!(token::get_name(data.item_name));
@@ -6663,14 +6799,14 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
     }
 }
 
-impl Variance {
-    pub fn to_string(self) -> &'static str {
-        match self {
+impl fmt::Debug for Variance {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(match *self {
             Covariant => "+",
             Contravariant => "-",
             Invariant => "o",
             Bivariant => "*",
-        }
+        })
     }
 }
 
@@ -6724,7 +6860,7 @@ pub fn construct_free_substs<'a,'tcx>(
                                   defs: &[TypeParameterDef<'tcx>]) {
         for def in defs {
             debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
-                   def.repr(tcx));
+                   def);
             let ty = ty::mk_param_from_def(tcx, def);
             types.push(def.space, ty);
        }
@@ -6757,8 +6893,8 @@ pub fn construct_parameter_environment<'a,'tcx>(
 
     debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}",
            free_id,
-           free_substs.repr(tcx),
-           predicates.repr(tcx));
+           free_substs,
+           predicates);
 
     //
     // Finally, we have to normalize the bounds in the environment, in
@@ -6916,34 +7052,35 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
                                     ty: Ty) {
     walk_ty(ty, |ty| {
         match ty.sty {
-            ty_rptr(region, _) => {
+            TyRef(region, _) => {
                 accumulator.push(*region)
             }
-            ty_trait(ref t) => {
+            TyTrait(ref t) => {
                 accumulator.push_all(t.principal.0.substs.regions().as_slice());
             }
-            ty_enum(_, substs) |
-            ty_struct(_, substs) => {
+            TyEnum(_, substs) |
+            TyStruct(_, substs) => {
                 accum_substs(accumulator, substs);
             }
-            ty_closure(_, substs) => {
+            TyClosure(_, substs) => {
                 accum_substs(accumulator, substs);
             }
-            ty_bool |
-            ty_char |
-            ty_int(_) |
-            ty_uint(_) |
-            ty_float(_) |
-            ty_uniq(_) |
-            ty_str |
-            ty_vec(_, _) |
-            ty_ptr(_) |
-            ty_bare_fn(..) |
-            ty_tup(_) |
-            ty_projection(_) |
-            ty_param(_) |
-            ty_infer(_) |
-            ty_err => {
+            TyBool |
+            TyChar |
+            TyInt(_) |
+            TyUint(_) |
+            TyFloat(_) |
+            TyBox(_) |
+            TyStr |
+            TyArray(_, _) |
+            TySlice(_) |
+            TyRawPtr(_) |
+            TyBareFn(..) |
+            TyTuple(_) |
+            TyProjection(_) |
+            TyParam(_) |
+            TyInfer(_) |
+            TyError => {
             }
         }
     });
@@ -6952,7 +7089,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
         match substs.regions {
             subst::ErasedRegions => {}
             subst::NonerasedRegions(ref regions) => {
-                for region in regions.iter() {
+                for region in regions {
                     accumulator.push(*region)
                 }
             }
@@ -7013,9 +7150,9 @@ pub fn liberate_late_bound_regions<'tcx, T>(
     all_outlive_scope: region::DestructionScopeData,
     value: &Binder<T>)
     -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
-    replace_late_bound_regions(
+    ty_fold::replace_late_bound_regions(
         tcx, value,
         |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0
 }
@@ -7024,9 +7161,9 @@ pub fn count_late_bound_regions<'tcx, T>(
     tcx: &ty::ctxt<'tcx>,
     value: &Binder<T>)
     -> usize
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
-    let (_, skol_map) = replace_late_bound_regions(tcx, value, |_| ty::ReStatic);
+    let (_, skol_map) = ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic);
     skol_map.len()
 }
 
@@ -7034,7 +7171,7 @@ pub fn binds_late_bound_regions<'tcx, T>(
     tcx: &ty::ctxt<'tcx>,
     value: &Binder<T>)
     -> bool
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
     count_late_bound_regions(tcx, value) > 0
 }
@@ -7045,7 +7182,7 @@ pub fn flatten_late_bound_regions<'tcx, T>(
     tcx: &ty::ctxt<'tcx>,
     bound2_value: &Binder<Binder<T>>)
     -> Binder<T>
-    where T: TypeFoldable<'tcx> + Repr<'tcx>
+    where T: TypeFoldable<'tcx>
 {
     let bound0_value = bound2_value.skip_binder().skip_binder();
     let value = ty_fold::fold_regions(tcx, bound0_value, |region, current_depth| {
@@ -7067,7 +7204,7 @@ pub fn no_late_bound_regions<'tcx, T>(
     tcx: &ty::ctxt<'tcx>,
     value: &Binder<T>)
     -> Option<T>
-    where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone
+    where T : TypeFoldable<'tcx>
 {
     if binds_late_bound_regions(tcx, value) {
         None
@@ -7082,9 +7219,9 @@ pub fn erase_late_bound_regions<'tcx, T>(
     tcx: &ty::ctxt<'tcx>,
     value: &Binder<T>)
     -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
-    replace_late_bound_regions(tcx, value, |_| ty::ReStatic).0
+    ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic).0
 }
 
 /// Rewrite any late-bound regions so that they are anonymous.  Region numbers are
@@ -7099,56 +7236,15 @@ pub fn anonymize_late_bound_regions<'tcx, T>(
     tcx: &ctxt<'tcx>,
     sig: &Binder<T>)
     -> Binder<T>
-    where T : TypeFoldable<'tcx> + Repr<'tcx>,
+    where T : TypeFoldable<'tcx>,
 {
     let mut counter = 0;
-    ty::Binder(replace_late_bound_regions(tcx, sig, |_| {
+    ty::Binder(ty_fold::replace_late_bound_regions(tcx, sig, |_| {
         counter += 1;
         ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter))
     }).0)
 }
 
-/// Replaces the late-bound-regions in `value` that are bound by `value`.
-pub fn replace_late_bound_regions<'tcx, T, F>(
-    tcx: &ty::ctxt<'tcx>,
-    binder: &Binder<T>,
-    mut mapf: F)
-    -> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
-    where T : TypeFoldable<'tcx> + Repr<'tcx>,
-          F : FnMut(BoundRegion) -> ty::Region,
-{
-    debug!("replace_late_bound_regions({})", binder.repr(tcx));
-
-    let mut map = FnvHashMap();
-
-    // Note: fold the field `0`, not the binder, so that late-bound
-    // regions bound by `binder` are considered free.
-    let value = ty_fold::fold_regions(tcx, &binder.0, |region, current_depth| {
-        debug!("region={}", region.repr(tcx));
-        match region {
-            ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
-                let region = *map.entry(br).or_insert_with(|| mapf(br));
-
-                if let ty::ReLateBound(debruijn1, br) = region {
-                    // If the callback returns a late-bound region,
-                    // that region should always use depth 1. Then we
-                    // adjust it to the correct depth.
-                    assert_eq!(debruijn1.depth, 1);
-                    ty::ReLateBound(debruijn, br)
-                } else {
-                    region
-                }
-            }
-            _ => {
-                region
-            }
-        }
-    });
-
-    debug!("resulting map: {:?} value: {:?}", map, value.repr(tcx));
-    (value, map)
-}
-
 impl DebruijnIndex {
     pub fn new(depth: u32) -> DebruijnIndex {
         assert!(depth > 0);
@@ -7160,84 +7256,45 @@ impl DebruijnIndex {
     }
 }
 
-impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for AutoAdjustment<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             AdjustReifyFnPointer => {
-                format!("AdjustReifyFnPointer")
+                write!(f, "AdjustReifyFnPointer")
             }
             AdjustUnsafeFnPointer => {
-                format!("AdjustUnsafeFnPointer")
+                write!(f, "AdjustUnsafeFnPointer")
             }
             AdjustDerefRef(ref data) => {
-                data.repr(tcx)
+                write!(f, "{:?}", data)
             }
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for AutoDerefRef<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("AutoDerefRef({}, unsize={}, {})",
-                self.autoderefs, self.unsize.repr(tcx), self.autoref.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for AutoRef<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        match *self {
-            AutoPtr(a, b) => {
-                format!("AutoPtr({},{:?})", a.repr(tcx), b)
-            }
-            AutoUnsafe(ref a) => {
-                format!("AutoUnsafe({:?})", a)
-            }
-        }
+impl<'tcx> fmt::Debug for AutoDerefRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
+               self.autoderefs, self.unsize, self.autoref)
     }
 }
 
-impl<'tcx> Repr<'tcx> for TyTrait<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("TyTrait({},{})",
-                self.principal.repr(tcx),
-                self.bounds.repr(tcx))
+impl<'tcx> fmt::Debug for TraitTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TraitTy({:?},{:?})",
+               self.principal,
+               self.bounds)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::Predicate<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Predicate::Trait(ref a) => a.repr(tcx),
-            Predicate::Equate(ref pair) => pair.repr(tcx),
-            Predicate::RegionOutlives(ref pair) => pair.repr(tcx),
-            Predicate::TypeOutlives(ref pair) => pair.repr(tcx),
-            Predicate::Projection(ref pair) => pair.repr(tcx),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for vtable_origin<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            vtable_static(def_id, ref tys, ref vtable_res) => {
-                format!("vtable_static({:?}:{}, {}, {})",
-                        def_id,
-                        ty::item_path_str(tcx, def_id),
-                        tys.repr(tcx),
-                        vtable_res.repr(tcx))
-            }
-
-            vtable_param(x, y) => {
-                format!("vtable_param({:?}, {})", x, y)
-            }
-
-            vtable_closure(def_id) => {
-                format!("vtable_closure({:?})", def_id)
-            }
-
-            vtable_error => {
-                format!("vtable_error")
-            }
+            Predicate::Trait(ref a) => write!(f, "{:?}", a),
+            Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
+            Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
+            Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
+            Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
         }
     }
 }
@@ -7282,7 +7339,7 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
     let tcx = param_env.tcx;
 
     let did = match self_type.sty {
-        ty::ty_struct(struct_did, substs) => {
+        ty::TyStruct(struct_did, substs) => {
             let fields = ty::struct_fields(tcx, struct_did, substs);
             for field in &fields {
                 if type_moves_by_default(param_env, span, field.mt.ty) {
@@ -7291,9 +7348,9 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
             }
             struct_did
         }
-        ty::ty_enum(enum_did, substs) => {
+        ty::TyEnum(enum_did, substs) => {
             let enum_variants = ty::enum_variants(tcx, enum_did);
-            for variant in &*enum_variants {
+            for variant in enum_variants.iter() {
                 for variant_arg_type in &variant.args {
                     let substd_arg_type =
                         variant_arg_type.subst(tcx, substs);
@@ -7443,14 +7500,6 @@ impl<'tcx> RegionEscape for ProjectionTy<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ProjectionPredicate<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ProjectionPredicate({}, {})",
-                self.projection_ty.repr(tcx),
-                self.ty.repr(tcx))
-    }
-}
-
 pub trait HasProjectionTypes {
     fn has_projection_types(&self) -> bool;
 }
@@ -7685,48 +7734,47 @@ impl ReferencesError for Region
     }
 }
 
-impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ClosureTy({},{},{})",
-                self.unsafety,
-                self.sig.repr(tcx),
-                self.abi)
+impl<'tcx> fmt::Debug for ClosureTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ClosureTy({},{:?},{})",
+               self.unsafety,
+               self.sig,
+               self.abi)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ClosureUpvar<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ClosureUpvar({},{})",
-                self.def.repr(tcx),
-                self.ty.repr(tcx))
+impl<'tcx> fmt::Debug for ClosureUpvar<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ClosureUpvar({:?},{:?})",
+               self.def,
+               self.ty)
     }
 }
 
-impl<'tcx> Repr<'tcx> for field<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("field({},{})",
-                self.name.repr(tcx),
-                self.mt.repr(tcx))
+impl<'tcx> fmt::Debug for field<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "field({},{})", self.name, self.mt)
     }
 }
 
-impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ParameterEnvironment(\
-            free_substs={}, \
-            implicit_region_bound={}, \
-            caller_bounds={})",
-            self.free_substs.repr(tcx),
-            self.implicit_region_bound.repr(tcx),
-            self.caller_bounds.repr(tcx))
+impl<'a, 'tcx> fmt::Debug for ParameterEnvironment<'a, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ParameterEnvironment(\
+            free_substs={:?}, \
+            implicit_region_bound={:?}, \
+            caller_bounds={:?})",
+            self.free_substs,
+            self.implicit_region_bound,
+            self.caller_bounds)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ObjectLifetimeDefault {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for ObjectLifetimeDefault {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ObjectLifetimeDefault::Ambiguous => format!("Ambiguous"),
-            ObjectLifetimeDefault::Specific(ref r) => r.repr(tcx),
+            ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"),
+            ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"),
+            ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r),
         }
     }
 }
index 19a82e3f35492058f23c8ec13f59e66de78229f8..8bfc8b090d58f311a7028de4d29b89339b70f7ac 100644 (file)
@@ -38,18 +38,20 @@ use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty};
 use middle::traits;
+
+use std::fmt;
 use std::rc::Rc;
 use syntax::abi;
 use syntax::ast;
 use syntax::owned_slice::OwnedSlice;
-use util::ppaux::Repr;
+use util::nodemap::FnvHashMap;
 
 ///////////////////////////////////////////////////////////////////////////
 // Two generic traits
 
 /// The TypeFoldable trait is implemented for every type that can be folded.
 /// Basically, every type that has a corresponding method in TypeFolder.
-pub trait TypeFoldable<'tcx>: Repr<'tcx> + Clone {
+pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
 }
 
@@ -73,7 +75,7 @@ pub trait TypeFolder<'tcx> : Sized {
     fn exit_region_binder(&mut self) { }
 
     fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
-        where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone
+        where T : TypeFoldable<'tcx>
     {
         // FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`.
         super_fold_binder(self, t)
@@ -196,7 +198,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
     }
 }
 
-impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>+Clone> TypeFoldable<'tcx> for ty::Binder<T> {
+impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
         folder.fold_binder(self)
     }
@@ -336,27 +338,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::vtable_origin<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::vtable_origin<'tcx> {
-        match *self {
-            ty::vtable_static(def_id, ref substs, ref origins) => {
-                let r_substs = substs.fold_with(folder);
-                let r_origins = origins.fold_with(folder);
-                ty::vtable_static(def_id, r_substs, r_origins)
-            }
-            ty::vtable_param(n, b) => {
-                ty::vtable_param(n, b)
-            }
-            ty::vtable_closure(def_id) => {
-                ty::vtable_closure(def_id)
-            }
-            ty::vtable_error => {
-                ty::vtable_error
-            }
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
     fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
         *self
@@ -369,17 +350,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::ParamBounds<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds<'tcx> {
-        ty::ParamBounds {
-            region_bounds: self.region_bounds.fold_with(folder),
-            builtin_bounds: self.builtin_bounds.fold_with(folder),
-            trait_bounds: self.trait_bounds.fold_with(folder),
-            projection_bounds: self.projection_bounds.fold_with(folder),
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef<'tcx> {
         ty::TypeParameterDef {
@@ -399,6 +369,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
             ty::ObjectLifetimeDefault::Ambiguous =>
                 ty::ObjectLifetimeDefault::Ambiguous,
 
+            ty::ObjectLifetimeDefault::BaseDefault =>
+                ty::ObjectLifetimeDefault::BaseDefault,
+
             ty::ObjectLifetimeDefault::Specific(r) =>
                 ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
         }
@@ -499,6 +472,16 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<
     }
 }
 
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableClosureData<'tcx, N> {
+        traits::VtableClosureData {
+            closure_def_id: self.closure_def_id,
+            substs: self.substs.fold_with(folder),
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
 impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
         traits::VtableDefaultImplData {
@@ -521,8 +504,8 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
         match *self {
             traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
             traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
-            traits::VtableClosure(d, ref s) => {
-                traits::VtableClosure(d, s.fold_with(folder))
+            traits::VtableClosure(ref d) => {
+                traits::VtableClosure(d.fold_with(folder))
             }
             traits::VtableFnPointer(ref d) => {
                 traits::VtableFnPointer(d.fold_with(folder))
@@ -610,51 +593,54 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
                                                 ty: Ty<'tcx>)
                                                 -> Ty<'tcx> {
     let sty = match ty.sty {
-        ty::ty_uniq(typ) => {
-            ty::ty_uniq(typ.fold_with(this))
+        ty::TyBox(typ) => {
+            ty::TyBox(typ.fold_with(this))
         }
-        ty::ty_ptr(ref tm) => {
-            ty::ty_ptr(tm.fold_with(this))
+        ty::TyRawPtr(ref tm) => {
+            ty::TyRawPtr(tm.fold_with(this))
         }
-        ty::ty_vec(typ, sz) => {
-            ty::ty_vec(typ.fold_with(this), sz)
+        ty::TyArray(typ, sz) => {
+            ty::TyArray(typ.fold_with(this), sz)
         }
-        ty::ty_enum(tid, ref substs) => {
+        ty::TySlice(typ) => {
+            ty::TySlice(typ.fold_with(this))
+        }
+        ty::TyEnum(tid, ref substs) => {
             let substs = substs.fold_with(this);
-            ty::ty_enum(tid, this.tcx().mk_substs(substs))
+            ty::TyEnum(tid, this.tcx().mk_substs(substs))
         }
-        ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
-            ty::ty_trait(box ty::TyTrait {
+        ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
+            ty::TyTrait(box ty::TraitTy {
                 principal: principal.fold_with(this),
                 bounds: bounds.fold_with(this),
             })
         }
-        ty::ty_tup(ref ts) => {
-            ty::ty_tup(ts.fold_with(this))
+        ty::TyTuple(ref ts) => {
+            ty::TyTuple(ts.fold_with(this))
         }
-        ty::ty_bare_fn(opt_def_id, ref f) => {
+        ty::TyBareFn(opt_def_id, ref f) => {
             let bfn = f.fold_with(this);
-            ty::ty_bare_fn(opt_def_id, this.tcx().mk_bare_fn(bfn))
+            ty::TyBareFn(opt_def_id, this.tcx().mk_bare_fn(bfn))
         }
-        ty::ty_rptr(r, ref tm) => {
+        ty::TyRef(r, ref tm) => {
             let r = r.fold_with(this);
-            ty::ty_rptr(this.tcx().mk_region(r), tm.fold_with(this))
+            ty::TyRef(this.tcx().mk_region(r), tm.fold_with(this))
         }
-        ty::ty_struct(did, ref substs) => {
+        ty::TyStruct(did, ref substs) => {
             let substs = substs.fold_with(this);
-            ty::ty_struct(did, this.tcx().mk_substs(substs))
+            ty::TyStruct(did, this.tcx().mk_substs(substs))
         }
-        ty::ty_closure(did, ref substs) => {
+        ty::TyClosure(did, ref substs) => {
             let s = substs.fold_with(this);
-            ty::ty_closure(did, this.tcx().mk_substs(s))
+            ty::TyClosure(did, this.tcx().mk_substs(s))
         }
-        ty::ty_projection(ref data) => {
-            ty::ty_projection(data.fold_with(this))
+        ty::TyProjection(ref data) => {
+            ty::TyProjection(data.fold_with(this))
         }
-        ty::ty_bool | ty::ty_char | ty::ty_str |
-        ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
-        ty::ty_err | ty::ty_infer(_) |
-        ty::ty_param(..) => {
+        ty::TyBool | ty::TyChar | ty::TyStr |
+        ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
+        ty::TyError | ty::TyInfer(_) |
+        ty::TyParam(..) => {
             ty.sty.clone()
         }
     };
@@ -742,6 +728,7 @@ pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
         region_bound: bounds.region_bound.fold_with(this),
         builtin_bounds: bounds.builtin_bounds,
         projection_bounds: bounds.projection_bounds.fold_with(this),
+        region_bound_will_change: bounds.region_bound_will_change,
     }
 }
 
@@ -849,19 +836,99 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         match r {
             ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
-                debug!("RegionFolder.fold_region({}) skipped bound region (current depth={})",
-                       r.repr(self.tcx()), self.current_depth);
+                debug!("RegionFolder.fold_region({:?}) skipped bound region (current depth={})",
+                       r, self.current_depth);
                 r
             }
             _ => {
-                debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
-                       r.repr(self.tcx()), self.current_depth);
+                debug!("RegionFolder.fold_region({:?}) folding free region (current_depth={})",
+                       r, self.current_depth);
                 (self.fld_r)(r, self.current_depth)
             }
         }
     }
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Late-bound region replacer
+
+// Replaces the escaping regions in a type.
+
+struct RegionReplacer<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    current_depth: u32,
+    fld_r: &'a mut (FnMut(ty::BoundRegion) -> ty::Region + 'a),
+    map: FnvHashMap<ty::BoundRegion, ty::Region>
+}
+
+impl<'a, 'tcx> RegionReplacer<'a, 'tcx> {
+    fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionReplacer<'a, 'tcx>
+        where F : FnMut(ty::BoundRegion) -> ty::Region
+    {
+        RegionReplacer {
+            tcx: tcx,
+            current_depth: 1,
+            fld_r: fld_r,
+            map: FnvHashMap()
+        }
+    }
+}
+
+pub fn replace_late_bound_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
+                                            value: &ty::Binder<T>,
+                                            mut f: F)
+                                            -> (T, FnvHashMap<ty::BoundRegion, ty::Region>)
+    where F : FnMut(ty::BoundRegion) -> ty::Region,
+          T : TypeFoldable<'tcx>,
+{
+    debug!("replace_late_bound_regions({:?})", value);
+    let mut replacer = RegionReplacer::new(tcx, &mut f);
+    let result = value.skip_binder().fold_with(&mut replacer);
+    (result, replacer.map)
+}
+
+impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
+{
+    fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
+
+    fn enter_region_binder(&mut self) {
+        self.current_depth += 1;
+    }
+
+    fn exit_region_binder(&mut self) {
+        self.current_depth -= 1;
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty::type_escapes_depth(t, self.current_depth-1) {
+            return t;
+        }
+
+        super_fold_ty(self, t)
+    }
+
+    fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+        match r {
+            ty::ReLateBound(debruijn, br) if debruijn.depth == self.current_depth => {
+                debug!("RegionReplacer.fold_region({:?}) folding region (current_depth={})",
+                       r, self.current_depth);
+                let fld_r = &mut self.fld_r;
+                let region = *self.map.entry(br).or_insert_with(|| fld_r(br));
+                if let ty::ReLateBound(debruijn1, br) = region {
+                    // If the callback returns a late-bound region,
+                    // that region should always use depth 1. Then we
+                    // adjust it to the correct depth.
+                    assert_eq!(debruijn1.depth, 1);
+                    ty::ReLateBound(debruijn, br)
+                } else {
+                    region
+                }
+            }
+            r => r
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Region eraser
 //
@@ -882,6 +949,14 @@ pub fn erase_regions<'tcx, T: TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>, t: T) ->
 impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
 
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty::type_has_erasable_regions(t) {
+            return t;
+        }
+
+        super_fold_ty(self, t)
+    }
+
     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         // because whether or not a region is bound affects subtyping,
         // we can't erase the bound/free distinction, but we can
@@ -913,10 +988,10 @@ pub fn shift_region(region: ty::Region, amount: u32) -> ty::Region {
     }
 }
 
-pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>>(tcx: &ty::ctxt<'tcx>,
-                                                            amount: u32, value: &T) -> T {
-    debug!("shift_regions(value={}, amount={})",
-           value.repr(tcx), amount);
+pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>,
+                                                 amount: u32, value: &T) -> T {
+    debug!("shift_regions(value={:?}, amount={})",
+           value, amount);
 
     value.fold_with(&mut RegionFolder::new(tcx, &mut |region, _current_depth| {
         shift_region(region, amount)
index 526ad0ec1c9d2d4b6f3ff3c1420ac0b71d2b7720..5776235780a3a927b225d5e5d7074f72bb7bb63b 100644 (file)
@@ -10,7 +10,6 @@
 
 use middle::ty::{self, Ty};
 use middle::ty_relate::{self, Relate, TypeRelation, RelateResult};
-use util::ppaux::Repr;
 
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// substituted with values so as to make it equal to A. Matching is
@@ -43,6 +42,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
     fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx }
     fn a_is_expected(&self) -> bool { true } // irrelevant
 
+    fn will_change(&mut self, _: bool, _: bool) -> bool {
+        // we're ignoring regions in this code
+        false
+    }
+
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
                                                _: ty::Variance,
                                                a: &T,
@@ -53,31 +57,31 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
     }
 
     fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
+        debug!("{}.regions({:?}, {:?})",
                self.tag(),
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
+               a,
+               b);
         Ok(a)
     }
 
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.tcx()), b.repr(self.tcx()));
+        debug!("{}.tys({:?}, {:?})", self.tag(),
+               a, b);
         if a == b { return Ok(a); }
 
         match (&a.sty, &b.sty) {
-            (_, &ty::ty_infer(ty::FreshTy(_))) |
-            (_, &ty::ty_infer(ty::FreshIntTy(_))) |
-            (_, &ty::ty_infer(ty::FreshFloatTy(_))) => {
+            (_, &ty::TyInfer(ty::FreshTy(_))) |
+            (_, &ty::TyInfer(ty::FreshIntTy(_))) |
+            (_, &ty::TyInfer(ty::FreshFloatTy(_))) => {
                 Ok(a)
             }
 
-            (&ty::ty_infer(_), _) |
-            (_, &ty::ty_infer(_)) => {
+            (&ty::TyInfer(_), _) |
+            (_, &ty::TyInfer(_)) => {
                 Err(ty::terr_sorts(ty_relate::expected_found(self, &a, &b)))
             }
 
-            (&ty::ty_err, _) | (_, &ty::ty_err) => {
+            (&ty::TyError, _) | (_, &ty::TyError) => {
                 Ok(self.tcx().types.err)
             }
 
index 0ef7b5be1fbd805377471a6ed68d90be58bff8d0..ace450f301955473702db633e3a5487c46be42b5 100644 (file)
@@ -19,10 +19,14 @@ use middle::ty_fold::TypeFoldable;
 use std::rc::Rc;
 use syntax::abi;
 use syntax::ast;
-use util::ppaux::Repr;
 
 pub type RelateResult<'tcx, T> = Result<T, ty::type_err<'tcx>>;
 
+#[derive(Clone, Debug)]
+pub enum Cause {
+    ExistentialRegionBound(bool), // if true, this is a default, else explicit
+}
+
 pub trait TypeRelation<'a,'tcx> : Sized {
     fn tcx(&self) -> &'a ty::ctxt<'tcx>;
 
@@ -33,6 +37,19 @@ pub trait TypeRelation<'a,'tcx> : Sized {
     /// relation. Just affects error messages.
     fn a_is_expected(&self) -> bool;
 
+    fn with_cause<F,R>(&mut self, _cause: Cause, f: F) -> R
+        where F: FnOnce(&mut Self) -> R
+    {
+        f(self)
+    }
+
+    /// Hack for deciding whether the lifetime bound defaults change
+    /// will be a breaking change or not. The bools indicate whether
+    /// `a`/`b` have a default that will change to `'static`; the
+    /// result is true if this will potentially affect the affect of
+    /// relating `a` and `b`.
+    fn will_change(&mut self, a: bool, b: bool) -> bool;
+
     /// Generic relation routine suitable for most anything.
     fn relate<T:Relate<'a,'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
         Relate::relate(self, a, b)
@@ -79,10 +96,10 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::mt<'tcx> {
                  -> RelateResult<'tcx, ty::mt<'tcx>>
         where R: TypeRelation<'a,'tcx>
     {
-        debug!("{}.mts({}, {})",
+        debug!("{}.mts({:?}, {:?})",
                relation.tag(),
-               a.repr(relation.tcx()),
-               b.repr(relation.tcx()));
+               a,
+               b);
         if a.mutbl != b.mutbl {
             Err(ty::terr_mutability)
         } else {
@@ -107,10 +124,10 @@ fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R,
                                     -> RelateResult<'tcx, Substs<'tcx>>
     where R: TypeRelation<'a,'tcx>
 {
-    debug!("substs: item_def_id={} a_subst={} b_subst={}",
-           item_def_id.repr(relation.tcx()),
-           a_subst.repr(relation.tcx()),
-           b_subst.repr(relation.tcx()));
+    debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}",
+           item_def_id,
+           a_subst,
+           b_subst);
 
     let variances;
     let opt_variances = if relation.tcx().variance_computed.get() {
@@ -191,14 +208,13 @@ fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R,
                                       -> RelateResult<'tcx, Vec<ty::Region>>
     where R: TypeRelation<'a,'tcx>
 {
-    let tcx = relation.tcx();
     let num_region_params = a_rs.len();
 
-    debug!("relate_region_params(a_rs={}, \
-            b_rs={}, variances={})",
-           a_rs.repr(tcx),
-           b_rs.repr(tcx),
-           variances.repr(tcx));
+    debug!("relate_region_params(a_rs={:?}, \
+            b_rs={:?}, variances={:?})",
+           a_rs,
+           b_rs,
+           variances);
 
     assert_eq!(num_region_params,
                variances.map_or(num_region_params,
@@ -274,8 +290,7 @@ fn relate_arg_vecs<'a,'tcx:'a,R>(relation: &mut R,
         return Err(ty::terr_arg_count);
     }
 
-    a_args.iter()
-          .zip(b_args.iter())
+    a_args.iter().zip(b_args)
           .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b))
           .collect()
 }
@@ -355,8 +370,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec<ty::PolyProjectionPredicate<'tcx>> {
         if a.len() != b.len() {
             Err(ty::terr_projection_bounds_length(expected_found(relation, &a.len(), &b.len())))
         } else {
-            a.iter()
-                .zip(b.iter())
+            a.iter().zip(b)
                 .map(|(a, b)| relation.relate(a, b))
                 .collect()
         }
@@ -370,14 +384,21 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> {
                  -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
         where R: TypeRelation<'a,'tcx>
     {
-        let r = try!(relation.relate_with_variance(ty::Contravariant,
-                                                   &a.region_bound,
-                                                   &b.region_bound));
+        let will_change = relation.will_change(a.region_bound_will_change,
+                                               b.region_bound_will_change);
+
+        let r =
+            try!(relation.with_cause(
+                Cause::ExistentialRegionBound(will_change),
+                |relation| relation.relate_with_variance(ty::Contravariant,
+                                                         &a.region_bound,
+                                                         &b.region_bound)));
         let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds));
         let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds));
         Ok(ty::ExistentialBounds { region_bound: r,
                                    builtin_bounds: nb,
-                                   projection_bounds: pb })
+                                   projection_bounds: pb,
+                                   region_bound_will_change: will_change })
     }
 }
 
@@ -440,87 +461,87 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
     let b_sty = &b.sty;
     debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
     match (a_sty, b_sty) {
-        (&ty::ty_infer(_), _) |
-        (_, &ty::ty_infer(_)) =>
+        (&ty::TyInfer(_), _) |
+        (_, &ty::TyInfer(_)) =>
         {
             // The caller should handle these cases!
             tcx.sess.bug("var types encountered in super_relate_tys")
         }
 
-        (&ty::ty_err, _) | (_, &ty::ty_err) =>
+        (&ty::TyError, _) | (_, &ty::TyError) =>
         {
             Ok(tcx.types.err)
         }
 
-        (&ty::ty_char, _) |
-        (&ty::ty_bool, _) |
-        (&ty::ty_int(_), _) |
-        (&ty::ty_uint(_), _) |
-        (&ty::ty_float(_), _) |
-        (&ty::ty_str, _)
+        (&ty::TyChar, _) |
+        (&ty::TyBool, _) |
+        (&ty::TyInt(_), _) |
+        (&ty::TyUint(_), _) |
+        (&ty::TyFloat(_), _) |
+        (&ty::TyStr, _)
             if a == b =>
         {
             Ok(a)
         }
 
-        (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p))
+        (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p))
             if a_p.idx == b_p.idx && a_p.space == b_p.space =>
         {
             Ok(a)
         }
 
-        (&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs))
+        (&ty::TyEnum(a_id, a_substs), &ty::TyEnum(b_id, b_substs))
             if a_id == b_id =>
         {
             let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
             Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
         }
 
-        (&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) =>
+        (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) =>
         {
             let principal = try!(relation.relate(&a_.principal, &b_.principal));
             let bounds = try!(relation.relate(&a_.bounds, &b_.bounds));
             Ok(ty::mk_trait(tcx, principal, bounds))
         }
 
-        (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
+        (&ty::TyStruct(a_id, a_substs), &ty::TyStruct(b_id, b_substs))
             if a_id == b_id =>
         {
             let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
             Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
         }
 
-        (&ty::ty_closure(a_id, a_substs),
-         &ty::ty_closure(b_id, b_substs))
+        (&ty::TyClosure(a_id, a_substs),
+         &ty::TyClosure(b_id, b_substs))
             if a_id == b_id =>
         {
-            // All ty_closure types with the same id represent
+            // All TyClosure types with the same id represent
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
             let substs = try!(relate_substs(relation, None, a_substs, b_substs));
             Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs)))
         }
 
-        (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) =>
+        (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
         {
             let typ = try!(relation.relate(&a_inner, &b_inner));
             Ok(ty::mk_uniq(tcx, typ))
         }
 
-        (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) =>
+        (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) =>
         {
             let mt = try!(relation.relate(a_mt, b_mt));
             Ok(ty::mk_ptr(tcx, mt))
         }
 
-        (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) =>
+        (&ty::TyRef(a_r, ref a_mt), &ty::TyRef(b_r, ref b_mt)) =>
         {
             let r = try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r));
             let mt = try!(relation.relate(a_mt, b_mt));
             Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
         }
 
-        (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) =>
+        (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) =>
         {
             let t = try!(relation.relate(&a_t, &b_t));
             if sz_a == sz_b {
@@ -530,17 +551,16 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             }
         }
 
-        (&ty::ty_vec(a_t, None), &ty::ty_vec(b_t, None)) =>
+        (&ty::TySlice(a_t), &ty::TySlice(b_t)) =>
         {
             let t = try!(relation.relate(&a_t, &b_t));
             Ok(ty::mk_vec(tcx, t, None))
         }
 
-        (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) =>
+        (&ty::TyTuple(ref as_), &ty::TyTuple(ref bs)) =>
         {
             if as_.len() == bs.len() {
-                let ts = try!(as_.iter()
-                                 .zip(bs.iter())
+                let ts = try!(as_.iter().zip(bs)
                                  .map(|(a, b)| relation.relate(a, b))
                                  .collect::<Result<_, _>>());
                 Ok(ty::mk_tup(tcx, ts))
@@ -552,14 +572,14 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             }
         }
 
-        (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty))
+        (&ty::TyBareFn(a_opt_def_id, a_fty), &ty::TyBareFn(b_opt_def_id, b_fty))
             if a_opt_def_id == b_opt_def_id =>
         {
             let fty = try!(relation.relate(a_fty, b_fty));
             Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
         }
 
-        (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) =>
+        (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) =>
         {
             let projection_ty = try!(relation.relate(a_data, b_data));
             Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
index ec09d6dcc1ee2c05e35f121c7b4d1e5e7af6f942..b34eb2ddb1e913ebfae6ba52e55013321f3929d6 100644 (file)
@@ -68,33 +68,33 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
 
 fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
-        ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
-        ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
+        ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
+        ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyError => {
         }
-        ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
+        ty::TyBox(ty) | ty::TyArray(ty, _) | ty::TySlice(ty) => {
             stack.push(ty);
         }
-        ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
+        ty::TyRawPtr(ref mt) | ty::TyRef(_, ref mt) => {
             stack.push(mt.ty);
         }
-        ty::ty_projection(ref data) => {
+        ty::TyProjection(ref data) => {
             push_reversed(stack, data.trait_ref.substs.types.as_slice());
         }
-        ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+        ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
             push_reversed(stack, principal.substs().types.as_slice());
             push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| {
                 pred.0.ty
             }).collect::<Vec<_>>());
         }
-        ty::ty_enum(_, ref substs) |
-        ty::ty_struct(_, ref substs) |
-        ty::ty_closure(_, ref substs) => {
+        ty::TyEnum(_, ref substs) |
+        ty::TyStruct(_, ref substs) |
+        ty::TyClosure(_, ref substs) => {
             push_reversed(stack, substs.types.as_slice());
         }
-        ty::ty_tup(ref ts) => {
+        ty::TyTuple(ref ts) => {
             push_reversed(stack, ts);
         }
-        ty::ty_bare_fn(_, ref ft) => {
+        ty::TyBareFn(_, ref ft) => {
             push_sig_subtypes(stack, &ft.sig);
         }
     }
index 04df464129541aeee9fd75253d187d3f36f931e9..5faaa53e4d0b5e3ed2354eddebcfe715e1b927ec 100644 (file)
@@ -20,6 +20,7 @@ use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax::ast;
+use syntax::feature_gate::AttributeType;
 
 use std::collections::HashMap;
 use std::borrow::ToOwned;
@@ -54,6 +55,9 @@ pub struct Registry<'a> {
 
     #[doc(hidden)]
     pub llvm_passes: Vec<String>,
+
+    #[doc(hidden)]
+    pub attributes: Vec<(String, AttributeType)>,
 }
 
 impl<'a> Registry<'a> {
@@ -67,6 +71,7 @@ impl<'a> Registry<'a> {
             lint_passes: vec!(),
             lint_groups: HashMap::new(),
             llvm_passes: vec!(),
+            attributes: vec!(),
         }
     }
 
@@ -132,4 +137,19 @@ impl<'a> Registry<'a> {
     pub fn register_llvm_pass(&mut self, name: &str) {
         self.llvm_passes.push(name.to_owned());
     }
+
+
+    /// Register an attribute with an attribute type.
+    ///
+    /// Registered attributes will bypass the `custom_attribute` feature gate.
+    /// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
+    /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
+    pub fn register_attribute(&mut self, name: String, ty: AttributeType) {
+        if let AttributeType::Gated(..) = ty {
+            self.sess.span_err(self.krate_span, "plugin tried to register a gated \
+                                                 attribute. Only `Normal`, `Whitelisted`, \
+                                                 and `CrateLevel` attributes are allowed");
+        }
+        self.attributes.push((name, ty));
+    }
 }
index b999929c4af9e4a5a24d75e4c15042865f9aa1ae..c6ce3a22d9b1c87cae3f3face29a9c151a529ea6 100644 (file)
@@ -32,6 +32,7 @@ use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
 use syntax::parse;
 use syntax::parse::token::InternedString;
+use syntax::feature_gate::UnstableFeatures;
 
 use getopts;
 use std::collections::HashMap;
@@ -119,21 +120,6 @@ pub struct Options {
     pub unstable_features: UnstableFeatures
 }
 
-#[derive(Clone, Copy)]
-pub enum UnstableFeatures {
-    /// Hard errors for unstable features are active, as on
-    /// beta/stable channels.
-    Disallow,
-    /// Use the default lint levels
-    Default,
-    /// 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.
-    Cheat
-}
-
 #[derive(Clone, PartialEq, Eq)]
 pub enum PrintRequest {
     FileNames,
@@ -852,7 +838,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
         parse::parse_meta_from_source_str("cfgspec".to_string(),
                                           s.to_string(),
                                           Vec::new(),
-                                          &parse::new_parse_sess())
+                                          &parse::ParseSess::new())
     }).collect::<ast::CrateConfig>()
 }
 
@@ -1074,7 +1060,7 @@ pub fn get_unstable_features_setting() -> UnstableFeatures {
     match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) {
         (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat,
         (true, _, _) => UnstableFeatures::Disallow,
-        (false, _, _) => UnstableFeatures::Default
+        (false, _, _) => UnstableFeatures::Allow
     }
 }
 
index 7a8ce1bf48e47d283e7e285315987658c5073d4e..6b5f58720ab15c75e974f6fb62cb2557a9b17d31 100644 (file)
@@ -23,6 +23,7 @@ use syntax::parse;
 use syntax::parse::token;
 use syntax::parse::ParseSess;
 use syntax::{ast, codemap};
+use syntax::feature_gate::AttributeType;
 
 use rustc_back::target::Target;
 
@@ -54,6 +55,7 @@ pub struct Session {
     pub lint_store: RefCell<lint::LintStore>,
     pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
     pub plugin_llvm_passes: RefCell<Vec<String>>,
+    pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
     pub crate_types: RefCell<Vec<config::CrateType>>,
     pub crate_metadata: RefCell<Vec<String>>,
     pub features: RefCell<feature_gate::Features>,
@@ -64,7 +66,9 @@ pub struct Session {
     /// operations such as auto-dereference and monomorphization.
     pub recursion_limit: Cell<usize>,
 
-    pub can_print_warnings: bool
+    pub can_print_warnings: bool,
+
+    next_node_id: Cell<ast::NodeId>
 }
 
 impl Session {
@@ -213,16 +217,23 @@ impl Session {
         lints.insert(id, vec!((lint_id, sp, msg)));
     }
     pub fn next_node_id(&self) -> ast::NodeId {
-        self.parse_sess.next_node_id()
+        self.reserve_node_ids(1)
     }
     pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
-        self.parse_sess.reserve_node_ids(count)
+        let id = self.next_node_id.get();
+
+        match id.checked_add(count) {
+            Some(next) => self.next_node_id.set(next),
+            None => self.bug("Input too large, ran out of node ids!")
+        }
+
+        id
     }
     pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler {
         &self.parse_sess.span_diagnostic
     }
     pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
-        &self.parse_sess.span_diagnostic.cm
+        self.parse_sess.codemap()
     }
     // This exists to help with refactoring to eliminate impossible
     // cases later on
@@ -359,9 +370,9 @@ pub fn build_session(sopts: config::Options,
 
     let codemap = codemap::CodeMap::new();
     let diagnostic_handler =
-        diagnostic::default_handler(sopts.color, Some(registry), can_print_warnings);
+        diagnostic::Handler::new(sopts.color, Some(registry), can_print_warnings);
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, codemap);
+        diagnostic::SpanHandler::new(diagnostic_handler, codemap);
 
     build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
 }
@@ -378,7 +389,7 @@ pub fn build_session_(sopts: config::Options,
     }
     };
     let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
-    let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
+    let p_s = parse::ParseSess::with_span_handler(span_diagnostic);
     let default_sysroot = match sopts.maybe_sysroot {
         Some(_) => None,
         None => Some(filesearch::get_or_default_sysroot())
@@ -416,12 +427,14 @@ pub fn build_session_(sopts: config::Options,
         lint_store: RefCell::new(lint::LintStore::new()),
         lints: RefCell::new(NodeMap()),
         plugin_llvm_passes: RefCell::new(Vec::new()),
+        plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         crate_metadata: RefCell::new(Vec::new()),
         delayed_span_bug: RefCell::new(None),
         features: RefCell::new(feature_gate::Features::new()),
         recursion_limit: Cell::new(64),
-        can_print_warnings: can_print_warnings
+        can_print_warnings: can_print_warnings,
+        next_node_id: Cell::new(1)
     };
 
     sess
index 3ae78fa7c19048157619e40d683735edc823ce42..4936e049ef2ee0e2c26da0c5e7be48430d7095ed 100644 (file)
 use std::path::{self, Path, PathBuf};
 use std::ffi::OsString;
 
-// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
-// (a verbatim path). This form of path is generally pretty rare, but the
-// implementation of `fs::canonicalize` currently generates paths of this form,
-// meaning that we're going to be passing quite a few of these down to gcc.
+// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
+// verbatim paths under the hood to non-verbatim paths! This manifests itself as
+// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the
+// real bug seems to lie in msvcrt.dll.
+//
+// Verbatim paths are generally pretty rare, but the implementation of
+// `fs::canonicalize` currently generates paths of this form, meaning that we're
+// going to be passing quite a few of these down to gcc, so we need to deal with
+// this case.
 //
 // For now we just strip the "verbatim prefix" of `\\?\` from the path. This
 // will probably lose information in some cases, but there's not a whole lot
-// more we can do with a buggy gcc...
+// more we can do with a buggy msvcrt...
+//
+// For some more information, see this comment:
+//   https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
 pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
     if !cfg!(windows) {
         return p.to_path_buf()
@@ -28,11 +36,20 @@ pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
         Some(path::Component::Prefix(p)) => p,
         _ => return p.to_path_buf(),
     };
-    let disk = match prefix.kind() {
-        path::Prefix::VerbatimDisk(disk) => disk,
-        _ => return p.to_path_buf(),
-    };
-    let mut base = OsString::from(format!("{}:", disk as char));
-    base.push(components.as_path());
-    PathBuf::from(base)
+    match prefix.kind() {
+        path::Prefix::VerbatimDisk(disk) => {
+            let mut base = OsString::from(format!("{}:", disk as char));
+            base.push(components.as_path());
+            PathBuf::from(base)
+        }
+        path::Prefix::VerbatimUNC(server, share) => {
+            let mut base = OsString::from(r"\\");
+            base.push(server);
+            base.push(r"\");
+            base.push(share);
+            base.push(components.as_path());
+            PathBuf::from(base)
+        }
+        _ => p.to_path_buf(),
+    }
 }
index cf2911ab182efd9eb8316c0f20461f2c751fb15b..382b78e77bed4c5829832c82a7a0d8d606e14838 100644 (file)
 // except according to those terms.
 
 
-use middle::def;
-use middle::region;
-use middle::subst::{VecPerParamSpace,Subst};
-use middle::subst;
+use middle::subst::{self, Subst};
 use middle::ty::{BoundRegion, BrAnon, BrNamed};
 use middle::ty::{ReEarlyBound, BrFresh, ctxt};
 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
 use middle::ty::{ReSkolemized, ReVar, BrEnv};
-use middle::ty::{mt, Ty, ParamTy};
-use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
-use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
-use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
-use middle::ty::ty_closure;
-use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
+use middle::ty::{mt, Ty};
+use middle::ty::{TyBool, TyChar, TyStruct, TyEnum};
+use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyBareFn};
+use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
+use middle::ty::TyClosure;
+use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
 use middle::ty;
-use middle::ty_fold::TypeFoldable;
+use middle::ty_fold::{self, TypeFoldable};
 
-use std::collections::HashMap;
-use std::collections::hash_state::HashState;
-use std::hash::Hash;
-use std::rc::Rc;
+use std::fmt;
 use syntax::abi;
-use syntax::ast_map;
-use syntax::codemap::{Span, Pos};
 use syntax::parse::token;
-use syntax::print::pprust;
-use syntax::ptr::P;
 use syntax::{ast, ast_util};
-use syntax::owned_slice::OwnedSlice;
 
-/// Produces a string suitable for debugging output.
-pub trait Repr<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String;
+pub fn verbose() -> bool {
+    ty::tls::with(|tcx| tcx.sess.verbose())
 }
 
-/// Produces a string suitable for showing to the user.
-pub trait UserString<'tcx> : Repr<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String;
-}
-
-pub fn note_and_explain_region(cx: &ctxt,
-                               prefix: &str,
-                               region: ty::Region,
-                               suffix: &str) -> Option<Span> {
-    match explain_region_and_span(cx, region) {
-      (ref str, Some(span)) => {
-        cx.sess.span_note(
-            span,
-            &format!("{}{}{}", prefix, *str, suffix));
-        Some(span)
-      }
-      (ref str, None) => {
-        cx.sess.note(
-            &format!("{}{}{}", prefix, *str, suffix));
-        None
-      }
-    }
-}
-
-/// When a free region is associated with `item`, how should we describe the item in the error
-/// message.
-fn item_scope_tag(item: &ast::Item) -> &'static str {
-    match item.node {
-        ast::ItemImpl(..) => "impl",
-        ast::ItemStruct(..) => "struct",
-        ast::ItemEnum(..) => "enum",
-        ast::ItemTrait(..) => "trait",
-        ast::ItemFn(..) => "function body",
-        _ => "item"
-    }
-}
-
-pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
-                            -> (String, Option<Span>) {
-    return match region {
-      ReScope(scope) => {
-        let new_string;
-        let on_unknown_scope = || {
-          (format!("unknown scope: {:?}.  Please report a bug.", scope), None)
-        };
-        let span = match scope.span(&cx.map) {
-          Some(s) => s,
-          None => return on_unknown_scope(),
-        };
-        let tag = match cx.map.find(scope.node_id()) {
-          Some(ast_map::NodeBlock(_)) => "block",
-          Some(ast_map::NodeExpr(expr)) => match expr.node {
-              ast::ExprCall(..) => "call",
-              ast::ExprMethodCall(..) => "method call",
-              ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
-              ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) =>  "while let",
-              ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) =>  "for",
-              ast::ExprMatch(..) => "match",
-              _ => "expression",
-          },
-          Some(ast_map::NodeStmt(_)) => "statement",
-          Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
-          Some(_) | None => {
-            // this really should not happen
-            return on_unknown_scope();
-          }
-        };
-        let scope_decorated_tag = match scope {
-            region::CodeExtent::Misc(_) => tag,
-            region::CodeExtent::ParameterScope { .. } => {
-                "scope of parameters for function"
-            }
-            region::CodeExtent::DestructionScope(_) => {
-                new_string = format!("destruction scope surrounding {}", tag);
-                &*new_string
-            }
-            region::CodeExtent::Remainder(r) => {
-                new_string = format!("block suffix following statement {}",
-                                     r.first_statement_index);
-                &*new_string
-            }
-        };
-        explain_span(cx, scope_decorated_tag, span)
-
-      }
-
-      ReFree(ref fr) => {
-        let prefix = match fr.bound_region {
-          BrAnon(idx) => {
-              format!("the anonymous lifetime #{} defined on", idx + 1)
-          }
-          BrFresh(_) => "an anonymous lifetime defined on".to_string(),
-          _ => {
-              format!("the lifetime {} as defined on",
-                      bound_region_ptr_to_string(cx, fr.bound_region))
-          }
-        };
-
-        match cx.map.find(fr.scope.node_id) {
-          Some(ast_map::NodeBlock(ref blk)) => {
-              let (msg, opt_span) = explain_span(cx, "block", blk.span);
-              (format!("{} {}", prefix, msg), opt_span)
-          }
-          Some(ast_map::NodeItem(it)) => {
-              let tag = item_scope_tag(&*it);
-              let (msg, opt_span) = explain_span(cx, tag, it.span);
-              (format!("{} {}", prefix, msg), opt_span)
-          }
-          Some(_) | None => {
-              // this really should not happen
-              (format!("{} unknown free region bounded by scope {:?}", prefix, fr.scope), None)
-          }
-        }
-      }
-
-      ReStatic => { ("the static lifetime".to_string(), None) }
-
-      ReEmpty => { ("the empty lifetime".to_string(), None) }
-
-      ReEarlyBound(ref data) => {
-        (format!("{}", token::get_name(data.name)), None)
-      }
-
-      // I believe these cases should not occur (except when debugging,
-      // perhaps)
-      ty::ReInfer(_) | ty::ReLateBound(..) => {
-        (format!("lifetime {:?}", region), None)
-      }
-    };
-
-    fn explain_span(cx: &ctxt, heading: &str, span: Span)
-                    -> (String, Option<Span>) {
-        let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
-        (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
-         Some(span))
-    }
-}
-
-pub fn bound_region_ptr_to_string(cx: &ctxt, br: BoundRegion) -> String {
-    bound_region_to_string(cx, "", false, br)
-}
-
-pub fn bound_region_to_string(cx: &ctxt,
-                           prefix: &str, space: bool,
-                           br: BoundRegion) -> String {
-    let space_str = if space { " " } else { "" };
-
-    if cx.sess.verbose() {
-        return format!("{}{}{}", prefix, br.repr(cx), space_str)
-    }
-
-    match br {
-        BrNamed(_, name) => {
-            format!("{}{}{}", prefix, token::get_name(name), space_str)
-        }
-        BrAnon(_) | BrFresh(_) | BrEnv => prefix.to_string()
-    }
-}
-
-// In general, if you are giving a region error message,
-// you should use `explain_region()` or, better yet,
-// `note_and_explain_region()`
-pub fn region_ptr_to_string(cx: &ctxt, region: Region) -> String {
-    region_to_string(cx, "&", true, region)
-}
-
-pub fn region_to_string(cx: &ctxt, prefix: &str, space: bool, region: Region) -> String {
-    let space_str = if space { " " } else { "" };
-
-    if cx.sess.verbose() {
-        return format!("{}{}{}", prefix, region.repr(cx), space_str)
-    }
-
-    // These printouts are concise.  They do not contain all the information
-    // the user might want to diagnose an error, but there is basically no way
-    // to fit that into a short string.  Hence the recommendation to use
-    // `explain_region()` or `note_and_explain_region()`.
-    match region {
-        ty::ReScope(_) => prefix.to_string(),
-        ty::ReEarlyBound(ref data) => {
-            token::get_name(data.name).to_string()
-        }
-        ty::ReLateBound(_, br) => bound_region_to_string(cx, prefix, space, br),
-        ty::ReFree(ref fr) => bound_region_to_string(cx, prefix, space, fr.bound_region),
-        ty::ReInfer(ReSkolemized(_, br)) => {
-            bound_region_to_string(cx, prefix, space, br)
-        }
-        ty::ReInfer(ReVar(_)) => prefix.to_string(),
-        ty::ReStatic => format!("{}'static{}", prefix, space_str),
-        ty::ReEmpty => format!("{}'<empty>{}", prefix, space_str),
-    }
-}
-
-pub fn mutability_to_string(m: ast::Mutability) -> String {
-    match m {
-        ast::MutMutable => "mut ".to_string(),
-        ast::MutImmutable => "".to_string(),
-    }
-}
-
-pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String {
-    format!("{}{}",
-        mutability_to_string(m.mutbl),
-        ty_to_string(cx, m.ty))
-}
-
-pub fn vec_map_to_string<T, F>(ts: &[T], f: F) -> String where
-    F: FnMut(&T) -> String,
-{
-    let tstrs = ts.iter().map(f).collect::<Vec<String>>();
-    format!("[{}]", tstrs.connect(", "))
-}
-
-pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
-    fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
-                               opt_def_id: Option<ast::DefId>,
-                               unsafety: ast::Unsafety,
-                               abi: abi::Abi,
-                               ident: Option<ast::Ident>,
-                               sig: &ty::PolyFnSig<'tcx>)
-                               -> String {
-        let mut s = String::new();
-
-        match unsafety {
-            ast::Unsafety::Normal => {}
-            ast::Unsafety::Unsafe => {
-                s.push_str(&unsafety.to_string());
-                s.push(' ');
-            }
-        };
-
-        if abi != abi::Rust {
-            s.push_str(&format!("extern {} ", abi.to_string()));
-        };
-
-        s.push_str("fn");
-
-        match ident {
-            Some(i) => {
-                s.push(' ');
-                s.push_str(&token::get_ident(i));
-            }
-            _ => { }
-        }
-
-        push_sig_to_string(cx, &mut s, '(', ')', sig);
-
-        match opt_def_id {
-            Some(def_id) => {
-                s.push_str(" {");
-                let path_str = ty::item_path_str(cx, def_id);
-                s.push_str(&path_str[..]);
-                s.push_str("}");
-            }
-            None => { }
-        }
-
-        s
-    }
-
-    fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
-        let mut s = String::new();
-        s.push_str("[closure");
-        push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
-        s.push(']');
-        s
-    }
-
-    fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
-                                s: &mut String,
-                                bra: char,
-                                ket: char,
-                                sig: &ty::PolyFnSig<'tcx>) {
-        s.push(bra);
-        let strs = sig.0.inputs
-            .iter()
-            .map(|a| ty_to_string(cx, *a))
-            .collect::<Vec<_>>();
-        s.push_str(&strs.connect(", "));
-        if sig.0.variadic {
-            s.push_str(", ...");
+fn fn_sig(f: &mut fmt::Formatter,
+          inputs: &[Ty],
+          variadic: bool,
+          output: ty::FnOutput)
+          -> fmt::Result {
+    try!(write!(f, "("));
+    let mut inputs = inputs.iter();
+    if let Some(&ty) = inputs.next() {
+        try!(write!(f, "{}", ty));
+        for &ty in inputs {
+            try!(write!(f, ", {}", ty));
         }
-        s.push(ket);
-
-        match sig.0.output {
-            ty::FnConverging(t) => {
-                if !ty::type_is_nil(t) {
-                   s.push_str(" -> ");
-                   s.push_str(&ty_to_string(cx, t));
-                }
-            }
-            ty::FnDiverging => {
-                s.push_str(" -> !");
-            }
-        }
-    }
-
-    fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
-        let print_var_ids = cx.sess.verbose();
-        match ty {
-            ty::TyVar(ref vid) if print_var_ids => vid.repr(cx),
-            ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
-            ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
-            ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
-            ty::FreshTy(v) => format!("FreshTy({})", v),
-            ty::FreshIntTy(v) => format!("FreshIntTy({})", v),
-            ty::FreshFloatTy(v) => format!("FreshFloatTy({})", v)
+        if variadic {
+            try!(write!(f, ", ..."));
         }
     }
+    try!(write!(f, ")"));
 
-    // pretty print the structural type representation:
-    match typ.sty {
-        ty_bool => "bool".to_string(),
-        ty_char => "char".to_string(),
-        ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
-        ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
-        ty_float(t) => ast_util::float_ty_to_string(t).to_string(),
-        ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)),
-        ty_ptr(ref tm) => {
-            format!("*{} {}", match tm.mutbl {
-                ast::MutMutable => "mut",
-                ast::MutImmutable => "const",
-            }, ty_to_string(cx, tm.ty))
-        }
-        ty_rptr(r, ref tm) => {
-            let mut buf = region_ptr_to_string(cx, *r);
-            buf.push_str(&mt_to_string(cx, tm));
-            buf
-        }
-        ty_tup(ref elems) => {
-            let strs = elems
-                .iter()
-                .map(|elem| ty_to_string(cx, *elem))
-                .collect::<Vec<_>>();
-            match &strs[..] {
-                [ref string] => format!("({},)", string),
-                strs => format!("({})", strs.connect(", "))
+    match output {
+        ty::FnConverging(ty) => {
+            if !ty::type_is_nil(ty) {
+                try!(write!(f, " -> {}", ty));
             }
+            Ok(())
         }
-        ty_bare_fn(opt_def_id, ref f) => {
-            bare_fn_to_string(cx, opt_def_id, f.unsafety, f.abi, None, &f.sig)
-        }
-        ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
-        ty_err => "[type error]".to_string(),
-        ty_param(ref param_ty) => param_ty.user_string(cx),
-        ty_enum(did, substs) | ty_struct(did, substs) => {
-            let base = ty::item_path_str(cx, did);
-            parameterized(cx, &base, substs, did, &[],
-                          || ty::lookup_item_type(cx, did).generics)
-        }
-        ty_trait(ref data) => {
-            data.user_string(cx)
-        }
-        ty::ty_projection(ref data) => {
-            format!("<{} as {}>::{}",
-                    data.trait_ref.self_ty().user_string(cx),
-                    data.trait_ref.user_string(cx),
-                    data.item_name.user_string(cx))
-        }
-        ty_str => "str".to_string(),
-        ty_closure(ref did, substs) => {
-            let closure_tys = cx.closure_tys.borrow();
-            closure_tys.get(did).map(|closure_type| {
-                closure_to_string(cx, &closure_type.subst(cx, substs))
-            }).unwrap_or_else(|| {
-                if did.krate == ast::LOCAL_CRATE {
-                    let span = cx.map.span(did.node);
-                    format!("[closure {}]", span.repr(cx))
-                } else {
-                    format!("[closure]")
-                }
-            })
-        }
-        ty_vec(t, sz) => {
-            let inner_str = ty_to_string(cx, t);
-            match sz {
-                Some(n) => format!("[{}; {}]", inner_str, n),
-                None => format!("[{}]", inner_str),
-            }
+        ty::FnDiverging => {
+            write!(f, " -> !")
         }
     }
 }
 
-pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
-                                     -> &'static str {
-    match *category {
-        ty::StaticExplicitSelfCategory => "static",
-        ty::ByValueExplicitSelfCategory => "self",
-        ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
-            "&mut self"
+fn parameterized<GG>(f: &mut fmt::Formatter,
+                     substs: &subst::Substs,
+                     did: ast::DefId,
+                     projections: &[ty::ProjectionPredicate],
+                     get_generics: GG)
+                     -> fmt::Result
+    where GG: for<'tcx> FnOnce(&ty::ctxt<'tcx>) -> ty::Generics<'tcx>
+{
+    let (fn_trait_kind, verbose) = try!(ty::tls::with(|tcx| {
+        try!(write!(f, "{}", ty::item_path_str(tcx, did)));
+        Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose()))
+    }));
+
+    let mut empty = true;
+    let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
+        if empty {
+            empty = false;
+            write!(f, "{}", start)
+        } else {
+            write!(f, "{}", cont)
         }
-        ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
-        ty::ByBoxExplicitSelfCategory => "Box<self>",
-    }
-}
+    };
 
-pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
-                              base: &str,
-                              substs: &subst::Substs<'tcx>,
-                              did: ast::DefId,
-                              projections: &[ty::ProjectionPredicate<'tcx>],
-                              get_generics: GG)
-                              -> String
-    where GG : FnOnce() -> ty::Generics<'tcx>
-{
-    if cx.sess.verbose() {
-        let mut strings = vec![];
+    if verbose {
         match substs.regions {
             subst::ErasedRegions => {
-                strings.push(format!(".."));
+                try!(start_or_continue(f, "<", ", "));
+                try!(write!(f, ".."));
             }
             subst::NonerasedRegions(ref regions) => {
-                for region in regions.iter() {
-                    strings.push(region.repr(cx));
+                for region in regions {
+                    try!(start_or_continue(f, "<", ", "));
+                    try!(write!(f, "{:?}", region));
                 }
             }
         }
-        for ty in substs.types.iter() {
-            strings.push(ty.repr(cx));
+        for &ty in &substs.types {
+            try!(start_or_continue(f, "<", ", "));
+            try!(write!(f, "{}", ty));
         }
-        for projection in projections.iter() {
-            strings.push(format!("{}={}",
-                                 projection.projection_ty.item_name.user_string(cx),
-                                 projection.ty.user_string(cx)));
+        for projection in projections {
+            try!(start_or_continue(f, "<", ", "));
+            try!(write!(f, "{}={}",
+                        projection.projection_ty.item_name,
+                        projection.ty));
         }
-        return if strings.is_empty() {
-            format!("{}", base)
-        } else {
-            format!("{}<{}>", base, strings.connect(","))
-        };
+        return start_or_continue(f, "", ">");
     }
 
-    let mut strs = Vec::new();
+    if fn_trait_kind.is_some() && projections.len() == 1 {
+        let projection_ty = projections[0].ty;
+        if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty {
+            return fn_sig(f, args, false, ty::FnConverging(projection_ty));
+        }
+    }
 
     match substs.regions {
         subst::ErasedRegions => { }
         subst::NonerasedRegions(ref regions) => {
-            for &r in regions.iter() {
-                let s = region_to_string(cx, "", false, r);
+            for &r in regions {
+                try!(start_or_continue(f, "<", ", "));
+                let s = r.to_string();
                 if s.is_empty() {
                     // This happens when the value of the region
                     // parameter is not easily serialized. This may be
                     // because the user omitted it in the first place,
                     // or because it refers to some block in the code,
                     // etc. I'm not sure how best to serialize this.
-                    strs.push(format!("'_"));
+                    try!(write!(f, "'_"));
                 } else {
-                    strs.push(s)
+                    try!(write!(f, "{}", s));
                 }
             }
         }
@@ -502,162 +144,99 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
     // ICEs trying to fetch the generics early in the pipeline. This
     // is kind of a hacky workaround in that -Z verbose is required to
     // avoid those ICEs.
-    let generics = get_generics();
-
-    let has_self = substs.self_ty().is_some();
     let tps = substs.types.get_slice(subst::TypeSpace);
-    let ty_params = generics.types.get_slice(subst::TypeSpace);
-    let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
-    let num_defaults = if has_defaults {
-        ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
-            match def.default {
-                Some(default) => {
-                    if !has_self && ty::type_has_self(default) {
-                        // In an object type, there is no `Self`, and
-                        // thus if the default value references Self,
-                        // the user will be required to give an
-                        // explicit value. We can't even do the
-                        // substitution below to check without causing
-                        // an ICE. (#18956).
-                        false
-                    } else {
-                        default.subst(cx, substs) == actual
+    let num_defaults = ty::tls::with(|tcx| {
+        let generics = get_generics(tcx);
+
+        let has_self = substs.self_ty().is_some();
+        let ty_params = generics.types.get_slice(subst::TypeSpace);
+        if ty_params.last().map_or(false, |def| def.default.is_some()) {
+            let substs = tcx.lift(&substs);
+            ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
+                match def.default {
+                    Some(default) => {
+                        if !has_self && ty::type_has_self(default) {
+                            // In an object type, there is no `Self`, and
+                            // thus if the default value references Self,
+                            // the user will be required to give an
+                            // explicit value. We can't even do the
+                            // substitution below to check without causing
+                            // an ICE. (#18956).
+                            false
+                        } else {
+                            let default = tcx.lift(&default);
+                            substs.and_then(|substs| default.subst(tcx, substs)) == Some(actual)
+                        }
                     }
+                    None => false
                 }
-                None => false
-            }
-        }).count()
-    } else {
-        0
-    };
+            }).count()
+        } else {
+            0
+        }
+    });
 
-    for t in &tps[..tps.len() - num_defaults] {
-        strs.push(ty_to_string(cx, *t))
+    for &ty in &tps[..tps.len() - num_defaults] {
+        try!(start_or_continue(f, "<", ", "));
+        try!(write!(f, "{}", ty));
     }
 
     for projection in projections {
-        strs.push(format!("{}={}",
-                          projection.projection_ty.item_name.user_string(cx),
-                          projection.ty.user_string(cx)));
-    }
-
-    if cx.lang_items.fn_trait_kind(did).is_some() && projections.len() == 1 {
-        let projection_ty = projections[0].ty;
-        let tail =
-            if ty::type_is_nil(projection_ty) {
-                format!("")
-            } else {
-                format!(" -> {}", projection_ty.user_string(cx))
-            };
-        format!("{}({}){}",
-                base,
-                if strs[0].starts_with("(") && strs[0].ends_with(",)") {
-                    &strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)'
-                } else if strs[0].starts_with("(") && strs[0].ends_with(")") {
-                    &strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
-                } else {
-                    &strs[0][..]
-                },
-                tail)
-    } else if !strs.is_empty() {
-        format!("{}<{}>", base, strs.connect(", "))
-    } else {
-        format!("{}", base)
+        try!(start_or_continue(f, "<", ", "));
+        try!(write!(f, "{}={}",
+                    projection.projection_ty.item_name,
+                    projection.ty));
     }
-}
 
-pub fn ty_to_short_str<'tcx>(cx: &ctxt<'tcx>, typ: Ty<'tcx>) -> String {
-    let mut s = typ.repr(cx).to_string();
-    if s.len() >= 32 {
-        s = (&s[0..32]).to_string();
-    }
-    return s;
+    start_or_continue(f, "", ">")
 }
 
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Option<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        match self {
-            &None => "None".to_string(),
-            &Some(ref t) => t.repr(tcx),
-        }
-    }
-}
-
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        (**self).repr(tcx)
-    }
-}
+fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
+                         tcx: &ty::ctxt<'tcx>,
+                         original: &ty::Binder<T>,
+                         lifted: Option<ty::Binder<U>>) -> fmt::Result
+    where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
+{
+    // Replace any anonymous late-bound regions with named
+    // variants, using gensym'd identifiers, so that we can
+    // clearly differentiate between named and unnamed regions in
+    // the output. We'll probably want to tweak this over time to
+    // decide just how much information to give.
+    let value = if let Some(v) = lifted {
+        v
+    } else {
+        return write!(f, "{}", original.0);
+    };
 
-impl<'tcx,T:Repr<'tcx>,U:Repr<'tcx>> Repr<'tcx> for Result<T,U> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        match self {
-            &Ok(ref t) => t.repr(tcx),
-            &Err(ref u) => format!("Err({})", u.repr(tcx))
+    let mut empty = true;
+    let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
+        if empty {
+            empty = false;
+            write!(f, "{}", start)
+        } else {
+            write!(f, "{}", cont)
         }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for () {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        "()".to_string()
-    }
-}
-
-impl<'a, 'tcx, T: ?Sized +Repr<'tcx>> Repr<'tcx> for &'a T {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        Repr::repr(*self, tcx)
-    }
-}
-
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Rc<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        (&**self).repr(tcx)
-    }
-}
-
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Box<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        (&**self).repr(tcx)
-    }
-}
-
-fn repr_vec<'tcx, T:Repr<'tcx>>(tcx: &ctxt<'tcx>, v: &[T]) -> String {
-    vec_map_to_string(v, |t| t.repr(tcx))
-}
-
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for [T] {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        repr_vec(tcx, self)
-    }
-}
-
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        repr_vec(tcx, &self[..])
-    }
-}
-
-// This is necessary to handle types like Option<Vec<T>>, for which
-// autoderef cannot convert the &[T] handler
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        repr_vec(tcx, &self[..])
-    }
-}
+    };
 
-impl<'tcx, T:UserString<'tcx>> UserString<'tcx> for Vec<T> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let strs: Vec<String> =
-            self.iter().map(|t| t.user_string(tcx)).collect();
-        strs.connect(", ")
-    }
-}
+    let new_value = ty_fold::replace_late_bound_regions(tcx, &value, |br| {
+        let _ = start_or_continue(f, "for<", ", ");
+        ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
+            ty::BrNamed(_, name) => {
+                let _ = write!(f, "{}", name);
+                br
+            }
+            ty::BrAnon(_) |
+            ty::BrFresh(_) |
+            ty::BrEnv => {
+                let name = token::intern("'r");
+                let _ = write!(f, "{}", name);
+                ty::BrNamed(ast_util::local_def(ast::DUMMY_NODE_ID), name)
+            }
+        })
+    }).0;
 
-impl<'tcx> Repr<'tcx> for def::Def {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
+    try!(start_or_continue(f, "", "> "));
+    write!(f, "{}", new_value)
 }
 
 /// This curious type is here to help pretty-print trait objects. In
@@ -671,904 +250,596 @@ impl<'tcx> Repr<'tcx> for def::Def {
 /// Right now there is only one trait in an object that can have
 /// projection bounds, so we just stuff them altogether. But in
 /// reality we should eventually sort things out better.
-type TraitAndProjections<'tcx> =
-    (ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
-
-impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let &(ref trait_ref, ref projection_bounds) = self;
-        let base = ty::item_path_str(tcx, trait_ref.def_id);
-        parameterized(tcx,
-                      &base,
-                      trait_ref.substs,
-                      trait_ref.def_id,
-                      &projection_bounds[..],
-                      || ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
+#[derive(Clone, Debug)]
+struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
+
+impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
+    fn fold_with<F:ty_fold::TypeFolder<'tcx>>(&self, folder: &mut F)
+                                              -> TraitAndProjections<'tcx> {
+        TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let &ty::TyTrait { ref principal, ref bounds } = self;
-
-        let mut components = vec![];
+impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
+        parameterized(f, trait_ref.substs,
+                      trait_ref.def_id,
+                      projection_bounds,
+                      |tcx| ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
+    }
+}
 
-        let tap: ty::Binder<TraitAndProjections<'tcx>> =
-            ty::Binder((principal.0.clone(),
-                        bounds.projection_bounds.iter().map(|x| x.0.clone()).collect()));
+impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let bounds = &self.bounds;
 
         // Generate the main trait ref, including associated types.
-        components.push(tap.user_string(tcx));
+        try!(ty::tls::with(|tcx| {
+            let principal = tcx.lift(&self.principal.0)
+                               .expect("could not lift TraitRef for printing");
+            let projections = tcx.lift(&bounds.projection_bounds[..])
+                                 .expect("could not lift projections for printing");
+            let projections = projections.map_in_place(|p| p.0);
+
+            let tap = ty::Binder(TraitAndProjections(principal, projections));
+            in_binder(f, tcx, &ty::Binder(""), Some(tap))
+        }));
 
         // Builtin bounds.
         for bound in &bounds.builtin_bounds {
-            components.push(bound.user_string(tcx));
+            try!(write!(f, " + {:?}", bound));
         }
 
-        // Region, if not obviously implied by builtin bounds.
-        if bounds.region_bound != ty::ReStatic {
-            // Region bound is implied by builtin bounds:
-            components.push(bounds.region_bound.user_string(tcx));
+        // FIXME: It'd be nice to compute from context when this bound
+        // is implied, but that's non-trivial -- we'd perhaps have to
+        // use thread-local data of some kind? There are also
+        // advantages to just showing the region, since it makes
+        // people aware that it's there.
+        let bound = bounds.region_bound.to_string();
+        if !bound.is_empty() {
+            try!(write!(f, " + {}", bound));
         }
 
-        components.retain(|s| !s.is_empty());
-
-        components.connect(" + ")
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
-    fn repr(&self, _tcx: &ctxt<'tcx>) -> String {
-        format!("TypeParameterDef({:?}, {:?}/{})",
-                self.def_id,
-                self.space,
-                self.index)
-    }
-}
+        if bounds.region_bound_will_change && verbose() {
+            try!(write!(f, " [WILL-CHANGE]"));
+        }
 
-impl<'tcx> Repr<'tcx> for ty::RegionParameterDef {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("RegionParameterDef(name={}, def_id={}, bounds={})",
-                token::get_name(self.name),
-                self.def_id.repr(tcx),
-                self.bounds.repr(tcx))
+        Ok(())
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::TyS<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        ty_to_string(tcx, self)
+impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TypeParameterDef({:?}, {:?}/{})",
+               self.def_id, self.space, self.index)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::mt<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        mt_to_string(tcx, self)
+impl<'tcx> fmt::Debug for ty::TyS<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", *self)
     }
 }
 
-impl<'tcx> Repr<'tcx> for subst::Substs<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("Substs[types={}, regions={}]",
-                       self.types.repr(tcx),
-                       self.regions.repr(tcx))
+impl<'tcx> fmt::Display for ty::mt<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}{}",
+               if self.mutbl == ast::MutMutable { "mut " } else { "" },
+               self.ty)
     }
 }
 
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for subst::VecPerParamSpace<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("[{};{};{}]",
-                self.get_slice(subst::TypeSpace).repr(tcx),
-                self.get_slice(subst::SelfSpace).repr(tcx),
-                self.get_slice(subst::FnSpace).repr(tcx))
+impl<'tcx> fmt::Debug for subst::Substs<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Substs[types={:?}, regions={:?}]",
+               self.types, self.regions)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ItemSubsts<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ItemSubsts({})", self.substs.repr(tcx))
+impl<'tcx> fmt::Debug for ty::ItemSubsts<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ItemSubsts({:?})", self.substs)
     }
 }
 
-impl<'tcx> Repr<'tcx> for subst::RegionSubsts {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl fmt::Debug for subst::RegionSubsts {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            subst::ErasedRegions => "erased".to_string(),
-            subst::NonerasedRegions(ref regions) => regions.repr(tcx)
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        let mut res = Vec::new();
-        for b in self {
-            res.push(match b {
-                ty::BoundSend => "Send".to_string(),
-                ty::BoundSized => "Sized".to_string(),
-                ty::BoundCopy => "Copy".to_string(),
-                ty::BoundSync => "Sync".to_string(),
-            });
-        }
-        res.connect("+")
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        let mut res = Vec::new();
-        res.push(self.builtin_bounds.repr(tcx));
-        for t in &self.trait_bounds {
-            res.push(t.repr(tcx));
+            subst::ErasedRegions => write!(f, "erased"),
+            subst::NonerasedRegions(ref regions) => write!(f, "{:?}", regions)
         }
-        res.connect("+")
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // when printing out the debug representation, we don't need
         // to enumerate the `for<...>` etc because the debruijn index
         // tells you everything you need to know.
-        let base = ty::item_path_str(tcx, self.def_id);
-        let result = parameterized(tcx, &base, self.substs, self.def_id, &[],
-                      || ty::lookup_trait_def(tcx, self.def_id).generics.clone());
         match self.substs.self_ty() {
-            None => result,
-            Some(sty) => format!("<{} as {}>", sty.repr(tcx), result)
+            None => write!(f, "{}", *self),
+            Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self)
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("TraitDef(generics={}, trait_ref={})",
-                self.generics.repr(tcx),
-                self.trait_ref.repr(tcx))
+impl<'tcx> fmt::Debug for ty::TraitDef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TraitDef(generics={:?}, trait_ref={:?})",
+               self.generics, self.trait_ref)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::TraitItem {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        let kind = match self.node {
-            ast::ConstTraitItem(..) => "ConstTraitItem",
-            ast::MethodTraitItem(..) => "MethodTraitItem",
-            ast::TypeTraitItem(..) => "TypeTraitItem",
-        };
-        format!("{}({}, id={})", kind, self.ident, self.id)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Expr {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("expr({}: {})", self.id, pprust::expr_to_string(self))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Path {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("path({})", pprust::path_to_string(self))
-    }
-}
-
-impl<'tcx> UserString<'tcx> for ast::Path {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        pprust::path_to_string(self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Ty {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("type({})", pprust::ty_to_string(self))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Item {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("item({})", tcx.map.node_to_string(self.id))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Lifetime {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Stmt {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("stmt({}: {})",
-                ast_util::stmt_id(self),
-                pprust::stmt_to_string(self))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::Pat {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("pat({}: {})", self.id, pprust::pat_to_string(self))
-    }
-}
+impl fmt::Display for ty::BoundRegion {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if verbose() {
+            return write!(f, "{:?}", *self);
+        }
 
-impl<'tcx> Repr<'tcx> for ty::BoundRegion {
-    fn repr(&self, tcx: &ctxt) -> String {
         match *self {
-            ty::BrAnon(id) => format!("BrAnon({})", id),
-            ty::BrNamed(id, name) => {
-                format!("BrNamed({}, {})", id.repr(tcx), token::get_name(name))
-            }
-            ty::BrFresh(id) => format!("BrFresh({})", id),
-            ty::BrEnv => "BrEnv".to_string()
+            BrNamed(_, name) => write!(f, "{}", name),
+            BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::Region {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl fmt::Debug for ty::Region {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::ReEarlyBound(ref data) => {
-                format!("ReEarlyBound({}, {:?}, {}, {})",
-                        data.param_id,
-                        data.space,
-                        data.index,
-                        token::get_name(data.name))
+                write!(f, "ReEarlyBound({}, {:?}, {}, {})",
+                       data.param_id,
+                       data.space,
+                       data.index,
+                       data.name)
             }
 
             ty::ReLateBound(binder_id, ref bound_region) => {
-                format!("ReLateBound({:?}, {})",
-                        binder_id,
-                        bound_region.repr(tcx))
+                write!(f, "ReLateBound({:?}, {:?})",
+                       binder_id,
+                       bound_region)
             }
 
-            ty::ReFree(ref fr) => fr.repr(tcx),
+            ty::ReFree(ref fr) => write!(f, "{:?}", fr),
 
             ty::ReScope(id) => {
-                format!("ReScope({:?})", id)
+                write!(f, "ReScope({:?})", id)
             }
 
-            ty::ReStatic => {
-                "ReStatic".to_string()
-            }
+            ty::ReStatic => write!(f, "ReStatic"),
 
             ty::ReInfer(ReVar(ref vid)) => {
-                format!("{:?}", vid)
+                write!(f, "{:?}", vid)
             }
 
             ty::ReInfer(ReSkolemized(id, ref bound_region)) => {
-                format!("re_skolemized({}, {})", id, bound_region.repr(tcx))
+                write!(f, "ReSkolemized({}, {:?})", id, bound_region)
             }
 
-            ty::ReEmpty => {
-                "ReEmpty".to_string()
-            }
+            ty::ReEmpty => write!(f, "ReEmpty")
         }
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::Region {
-    fn user_string(&self, tcx: &ctxt) -> String {
-        region_to_string(tcx, "", false, *self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::FreeRegion {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("ReFree({}, {})",
-                self.scope.repr(tcx),
-                self.bound_region.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for region::CodeExtent {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        match *self {
-            region::CodeExtent::ParameterScope { fn_id, body_id } =>
-                format!("ParameterScope({}, {})", fn_id, body_id),
-            region::CodeExtent::Misc(node_id) =>
-                format!("Misc({})", node_id),
-            region::CodeExtent::DestructionScope(node_id) =>
-                format!("DestructionScope({})", node_id),
-            region::CodeExtent::Remainder(rem) =>
-                format!("Remainder({}, {})", rem.block, rem.first_statement_index),
+impl fmt::Display for ty::Region {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if verbose() {
+            return write!(f, "{:?}", *self);
         }
-    }
-}
 
-impl<'tcx> Repr<'tcx> for region::DestructionScopeData {
-    fn repr(&self, _tcx: &ctxt) -> String {
+        // These printouts are concise.  They do not contain all the information
+        // the user might want to diagnose an error, but there is basically no way
+        // to fit that into a short string.  Hence the recommendation to use
+        // `explain_region()` or `note_and_explain_region()`.
         match *self {
-            region::DestructionScopeData{ node_id } =>
-                format!("DestructionScopeData {{ node_id: {} }}", node_id),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ast::DefId {
-    fn repr(&self, tcx: &ctxt) -> String {
-        // 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
-        if self.krate == ast::LOCAL_CRATE {
-            match tcx.map.find(self.node) {
-                Some(ast_map::NodeItem(..)) |
-                Some(ast_map::NodeForeignItem(..)) |
-                Some(ast_map::NodeImplItem(..)) |
-                Some(ast_map::NodeTraitItem(..)) |
-                Some(ast_map::NodeVariant(..)) |
-                Some(ast_map::NodeStructCtor(..)) => {
-                    return format!(
-                                "{:?}:{}",
-                                *self,
-                                ty::item_path_str(tcx, *self))
-                }
-                _ => {}
+            ty::ReEarlyBound(ref data) => {
+                write!(f, "{}", data.name)
+            }
+            ty::ReLateBound(_, br) |
+            ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+            ty::ReInfer(ReSkolemized(_, br)) => {
+                write!(f, "{}", br)
             }
+            ty::ReScope(_) |
+            ty::ReInfer(ReVar(_)) => Ok(()),
+            ty::ReStatic => write!(f, "'static"),
+            ty::ReEmpty => write!(f, "'<empty>"),
         }
-        return format!("{:?}", *self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::TypeScheme<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("TypeScheme {{generics: {}, ty: {}}}",
-                self.generics.repr(tcx),
-                self.ty.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::Generics<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("Generics(types: {}, regions: {})",
-                self.types.repr(tcx),
-                self.regions.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::GenericPredicates<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("GenericPredicates(predicates: {})",
-                self.predicates.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::InstantiatedPredicates<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("InstantiatedPredicates({})",
-                self.predicates.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::ItemVariances {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("ItemVariances(types={}, \
-                regions={})",
-                self.types.repr(tcx),
-                self.regions.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::Variance {
-    fn repr(&self, _: &ctxt) -> String {
-        // The first `.to_string()` returns a &'static str (it is not an implementation
-        // of the ToString trait). Because of that, we need to call `.to_string()` again
-        // if we want to have a `String`.
-        let result: &'static str = (*self).to_string();
-        result.to_string()
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::ImplOrTraitItem<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("ImplOrTraitItem({})",
-                match *self {
-                    ty::ImplOrTraitItem::MethodTraitItem(ref i) => i.repr(tcx),
-                    ty::ImplOrTraitItem::ConstTraitItem(ref i) => i.repr(tcx),
-                    ty::ImplOrTraitItem::TypeTraitItem(ref i) => i.repr(tcx),
-                })
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("AssociatedConst(name: {}, ty: {}, vis: {}, def_id: {})",
-                self.name.repr(tcx),
-                self.ty.repr(tcx),
-                self.vis.repr(tcx),
-                self.def_id.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::AssociatedType {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("AssociatedType(name: {}, vis: {}, def_id: {})",
-                self.name.repr(tcx),
-                self.vis.repr(tcx),
-                self.def_id.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::Method<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("Method(name: {}, generics: {}, predicates: {}, fty: {}, \
-                 explicit_self: {}, vis: {}, def_id: {})",
-                self.name.repr(tcx),
-                self.generics.repr(tcx),
-                self.predicates.repr(tcx),
-                self.fty.repr(tcx),
-                self.explicit_self.repr(tcx),
-                self.vis.repr(tcx),
-                self.def_id.repr(tcx))
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::Name {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        token::get_name(*self).to_string()
+impl fmt::Debug for ty::FreeRegion {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ReFree({:?}, {:?})",
+               self.scope, self.bound_region)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ast::Name {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        token::get_name(*self).to_string()
+impl fmt::Debug for ty::ItemVariances {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ItemVariances(types={:?}, regions={:?})",
+               self.types, self.regions)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::Ident {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        token::get_ident(*self).to_string()
+impl<'tcx> fmt::Debug for ty::GenericPredicates<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "GenericPredicates({:?})", self.predicates)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::ExplicitSelf_ {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
+impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "InstantiatedPredicates({:?})",
+               self.predicates)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::Visibility {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::BareFnTy<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("BareFnTy {{unsafety: {}, abi: {}, sig: {}}}",
-                self.unsafety,
-                self.abi.to_string(),
-                self.sig.repr(tcx))
+impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "ImplOrTraitItem("));
+        try!(match *self {
+            ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
+            ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
+            ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
+        });
+        write!(f, ")")
     }
 }
 
-
-impl<'tcx> Repr<'tcx> for ty::FnSig<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("fn{} -> {}", self.inputs.repr(tcx), self.output.repr(tcx))
+impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "fn"));
+        fn_sig(f, &self.inputs, self.variadic, self.output)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::FnOutput<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for ty::MethodOrigin<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ty::FnConverging(ty) =>
-                format!("FnConverging({0})", ty.repr(tcx)),
-            ty::FnDiverging =>
-                "FnDiverging".to_string()
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::MethodCallee<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("MethodCallee {{origin: {}, ty: {}, {}}}",
-                self.origin.repr(tcx),
-                self.ty.repr(tcx),
-                self.substs.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::MethodOrigin<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        match self {
-            &ty::MethodStatic(def_id) => {
-                format!("MethodStatic({})", def_id.repr(tcx))
-            }
-            &ty::MethodStaticClosure(def_id) => {
-                format!("MethodStaticClosure({})", def_id.repr(tcx))
-            }
-            &ty::MethodTypeParam(ref p) => {
-                p.repr(tcx)
+            ty::MethodStatic(def_id) => {
+                write!(f, "MethodStatic({:?})", def_id)
             }
-            &ty::MethodTraitObject(ref p) => {
-                p.repr(tcx)
+            ty::MethodStaticClosure(def_id) => {
+                write!(f, "MethodStaticClosure({:?})", def_id)
             }
+            ty::MethodTypeParam(ref p) => write!(f, "{:?}", p),
+            ty::MethodTraitObject(ref p) => write!(f, "{:?}", p)
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::MethodParam<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("MethodParam({},{})",
-                self.trait_ref.repr(tcx),
-                self.method_num)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::MethodObject<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("MethodObject({},{},{})",
-                self.trait_ref.repr(tcx),
-                self.method_num,
-                self.vtable_index)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::BuiltinBound {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
-}
-
-impl<'tcx> UserString<'tcx> for ty::BuiltinBound {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        match *self {
-            ty::BoundSend => "Send".to_string(),
-            ty::BoundSized => "Sized".to_string(),
-            ty::BoundCopy => "Copy".to_string(),
-            ty::BoundSync => "Sync".to_string(),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for Span {
-    fn repr(&self, tcx: &ctxt) -> String {
-        tcx.sess.codemap().span_to_string(*self).to_string()
+impl<'tcx> fmt::Debug for ty::MethodParam<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "MethodParam({:?},{})",
+               self.trait_ref,
+               self.method_num)
     }
 }
 
-impl<'tcx, A:UserString<'tcx>> UserString<'tcx> for Rc<A> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let this: &A = &**self;
-        this.user_string(tcx)
-    }
-}
-
-impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let mut result = Vec::new();
-        let s = self.builtin_bounds.user_string(tcx);
-        if !s.is_empty() {
-            result.push(s);
-        }
-        for n in &self.trait_bounds {
-            result.push(n.user_string(tcx));
-        }
-        result.connect(" + ")
+impl<'tcx> fmt::Debug for ty::MethodObject<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "MethodObject({:?},{},{})",
+               self.trait_ref,
+               self.method_num,
+               self.vtable_index)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        let mut res = Vec::new();
+impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut empty = true;
+        let mut maybe_continue = |f: &mut fmt::Formatter| {
+            if empty {
+                empty = false;
+                Ok(())
+            } else {
+                write!(f, " + ")
+            }
+        };
 
-        let region_str = self.region_bound.repr(tcx);
+        let region_str = format!("{:?}", self.region_bound);
         if !region_str.is_empty() {
-            res.push(region_str);
+            try!(maybe_continue(f));
+            try!(write!(f, "{}", region_str));
         }
 
         for bound in &self.builtin_bounds {
-            res.push(bound.repr(tcx));
+            try!(maybe_continue(f));
+            try!(write!(f, "{:?}", bound));
         }
 
         for projection_bound in &self.projection_bounds {
-            res.push(projection_bound.repr(tcx));
+            try!(maybe_continue(f));
+            try!(write!(f, "{:?}", projection_bound));
         }
 
-        res.connect("+")
-    }
-}
-
-impl<'tcx> UserString<'tcx> for ty::BuiltinBounds {
-    fn user_string(&self, tcx: &ctxt) -> String {
-        self.iter()
-            .map(|bb| bb.user_string(tcx))
-            .collect::<Vec<String>>()
-            .connect("+")
-            .to_string()
+        Ok(())
     }
 }
 
-impl<'tcx, T> UserString<'tcx> for ty::Binder<T>
-    where T : UserString<'tcx> + TypeFoldable<'tcx>
-{
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        // Replace any anonymous late-bound regions with named
-        // variants, using gensym'd identifiers, so that we can
-        // clearly differentiate between named and unnamed regions in
-        // the output. We'll probably want to tweak this over time to
-        // decide just how much information to give.
-        let mut names = Vec::new();
-        let (unbound_value, _) = ty::replace_late_bound_regions(tcx, self, |br| {
-            ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
-                ty::BrNamed(_, name) => {
-                    names.push(token::get_name(name));
-                    br
-                }
-                ty::BrAnon(_) |
-                ty::BrFresh(_) |
-                ty::BrEnv => {
-                    let name = token::gensym("'r");
-                    names.push(token::get_name(name));
-                    ty::BrNamed(ast_util::local_def(ast::DUMMY_NODE_ID), name)
-                }
-            })
-        });
-        let names: Vec<_> = names.iter().map(|s| &s[..]).collect();
-
-        let value_str = unbound_value.user_string(tcx);
-        if names.is_empty() {
-            value_str
-        } else {
-            format!("for<{}> {}", names.connect(","), value_str)
+impl fmt::Display for ty::BuiltinBounds {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut bounds = self.iter();
+        if let Some(bound) = bounds.next() {
+            try!(write!(f, "{:?}", bound));
+            for bound in bounds {
+                try!(write!(f, " + {:?}", bound));
+            }
         }
+        Ok(())
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        let path_str = ty::item_path_str(tcx, self.def_id);
-        parameterized(tcx, &path_str, self.substs, self.def_id, &[],
-                      || ty::lookup_trait_def(tcx, self.def_id).generics.clone())
+// The generic impl doesn't work yet because projections are not
+// normalized under HRTB.
+/*impl<T> fmt::Display for ty::Binder<T>
+    where T: fmt::Display + for<'a> ty::Lift<'a>,
+          for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
-}
+}*/
 
-impl<'tcx> UserString<'tcx> for Ty<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        ty_to_string(tcx, *self)
+impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> UserString<'tcx> for ast::Ident {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        token::get_name(self.name).to_string()
+impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> Repr<'tcx> for abi::Abi {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        self.to_string()
+impl<'tcx> fmt::Display for ty::Binder<ty::EquatePredicate<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> UserString<'tcx> for abi::Abi {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        self.to_string()
+impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::UpvarId {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("UpvarId({};`{}`;{})",
-                self.var_id,
-                ty::local_var_name_str(tcx, self.var_id),
-                self.closure_expr_id)
+impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> Repr<'tcx> for ast::Mutability {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
+impl fmt::Display for ty::Binder<ty::OutlivesPredicate<ty::Region, ty::Region>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::BorrowKind {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
+impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        parameterized(f, self.substs, self.def_id, &[],
+                      |tcx| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::UpvarBorrow {
-    fn repr(&self, tcx: &ctxt) -> String {
-        format!("UpvarBorrow({}, {})",
-                self.kind.repr(tcx),
-                self.region.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::UpvarCapture {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ty::UpvarCapture::ByValue => format!("ByValue"),
-            ty::UpvarCapture::ByRef(ref data) => format!("ByRef({})", data.repr(tcx)),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::IntVid {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::FloatVid {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::RegionVid {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::TyVid {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::IntVarValue {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
-}
+            TyBool => write!(f, "bool"),
+            TyChar => write!(f, "char"),
+            TyInt(t) => write!(f, "{}", ast_util::int_ty_to_string(t, None)),
+            TyUint(t) => write!(f, "{}", ast_util::uint_ty_to_string(t, None)),
+            TyFloat(t) => write!(f, "{}", ast_util::float_ty_to_string(t)),
+            TyBox(typ) => write!(f, "Box<{}>",  typ),
+            TyRawPtr(ref tm) => {
+                write!(f, "*{} {}", match tm.mutbl {
+                    ast::MutMutable => "mut",
+                    ast::MutImmutable => "const",
+                },  tm.ty)
+            }
+            TyRef(r, ref tm) => {
+                try!(write!(f, "&"));
+                let s = r.to_string();
+                try!(write!(f, "{}", s));
+                if !s.is_empty() {
+                    try!(write!(f, " "));
+                }
+                write!(f, "{}", tm)
+            }
+            TyTuple(ref tys) => {
+                try!(write!(f, "("));
+                let mut tys = tys.iter();
+                if let Some(&ty) = tys.next() {
+                    try!(write!(f, "{},", ty));
+                    if let Some(&ty) = tys.next() {
+                        try!(write!(f, " {}", ty));
+                        for &ty in tys {
+                            try!(write!(f, ", {}", ty));
+                        }
+                    }
+                }
+                write!(f, ")")
+            }
+            TyBareFn(opt_def_id, ref bare_fn) => {
+                if bare_fn.unsafety == ast::Unsafety::Unsafe {
+                    try!(write!(f, "unsafe "));
+                }
 
-impl<'tcx> Repr<'tcx> for ast::IntTy {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
-}
+                if bare_fn.abi != abi::Rust {
+                    try!(write!(f, "extern {} ", bare_fn.abi));
+                }
 
-impl<'tcx> Repr<'tcx> for ast::UintTy {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
-    }
-}
+                try!(write!(f, "{}", bare_fn.sig.0));
 
-impl<'tcx> Repr<'tcx> for ast::FloatTy {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("{:?}", *self)
+                if let Some(def_id) = opt_def_id {
+                    try!(write!(f, " {{{}}}", ty::tls::with(|tcx| {
+                        ty::item_path_str(tcx, def_id)
+                    })));
+                }
+                Ok(())
+            }
+            TyInfer(infer_ty) => write!(f, "{}", infer_ty),
+            TyError => write!(f, "[type error]"),
+            TyParam(ref param_ty) => write!(f, "{}", param_ty),
+            TyEnum(did, substs) | TyStruct(did, substs) => {
+                parameterized(f, substs, did, &[],
+                              |tcx| ty::lookup_item_type(tcx, did).generics)
+            }
+            TyTrait(ref data) => write!(f, "{}", data),
+            ty::TyProjection(ref data) => write!(f, "{}", data),
+            TyStr => write!(f, "str"),
+            TyClosure(ref did, substs) => ty::tls::with(|tcx| {
+                try!(write!(f, "[closure"));
+                let closure_tys = tcx.closure_tys.borrow();
+                try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| {
+                    tcx.lift(&substs).map(|substs| sig.subst(tcx, substs))
+                }).map(|sig| {
+                    fn_sig(f, &sig.0.inputs, false, sig.0.output)
+                }).unwrap_or_else(|| {
+                    if did.krate == ast::LOCAL_CRATE {
+                        try!(write!(f, " {:?}", tcx.map.span(did.node)));
+                    }
+                    Ok(())
+                }));
+                if verbose() {
+                    try!(write!(f, " id={:?}", did));
+                }
+                write!(f, "]")
+            }),
+            TyArray(ty, sz) => write!(f, "[{}; {}]",  ty, sz),
+            TySlice(ty) => write!(f, "[{}]",  ty)
+        }
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ExplicitSelfCategory {
-    fn repr(&self, _: &ctxt) -> String {
-        explicit_self_category_to_str(self).to_string()
+impl<'tcx> fmt::Display for ty::TyS<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.sty)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ParamTy {
-    fn user_string(&self, _tcx: &ctxt) -> String {
-        format!("{}", token::get_name(self.name))
+impl fmt::Debug for ty::UpvarId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "UpvarId({};`{}`;{})",
+               self.var_id,
+               ty::tls::with(|tcx| ty::local_var_name_str(tcx, self.var_id)),
+               self.closure_expr_id)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ParamTy {
-    fn repr(&self, tcx: &ctxt) -> String {
-        let ident = self.user_string(tcx);
-        format!("{}/{:?}.{}", ident, self.space, self.idx)
+impl fmt::Debug for ty::UpvarBorrow {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "UpvarBorrow({:?}, {:?})",
+               self.kind, self.region)
     }
 }
 
-impl<'tcx, A:Repr<'tcx>, B:Repr<'tcx>> Repr<'tcx> for (A,B) {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        let &(ref a, ref b) = self;
-        format!("({},{})", a.repr(tcx), b.repr(tcx))
+impl fmt::Display for ty::InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let print_var_ids = verbose();
+        match *self {
+            ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+            ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+            ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+            ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => write!(f, "_"),
+            ty::FreshTy(v) => write!(f, "FreshTy({})", v),
+            ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
+            ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
+        }
     }
 }
 
-impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("Binder({})", self.0.repr(tcx))
+impl fmt::Display for ty::ExplicitSelfCategory {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(match *self {
+            ty::StaticExplicitSelfCategory => "static",
+            ty::ByValueExplicitSelfCategory => "self",
+            ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
+                "&mut self"
+            }
+            ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
+            ty::ByBoxExplicitSelfCategory => "Box<self>",
+        })
     }
 }
 
-impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
-    where K: Hash + Eq + Repr<'tcx>,
-          V: Repr<'tcx>,
-          S: HashState,
-{
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("HashMap({})",
-                self.iter()
-                    .map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx)))
-                    .collect::<Vec<String>>()
-                    .connect(", "))
+impl fmt::Display for ty::ParamTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.name)
     }
 }
 
-impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate<T,U>
-    where T : Repr<'tcx> + TypeFoldable<'tcx>,
-          U : Repr<'tcx> + TypeFoldable<'tcx>,
-{
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("OutlivesPredicate({}, {})",
-                self.0.repr(tcx),
-                self.1.repr(tcx))
+impl fmt::Debug for ty::ParamTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}/{:?}.{}", self, self.space, self.idx)
     }
 }
 
-impl<'tcx, T, U> UserString<'tcx> for ty::OutlivesPredicate<T,U>
-    where T : UserString<'tcx> + TypeFoldable<'tcx>,
-          U : UserString<'tcx> + TypeFoldable<'tcx>,
+impl<'tcx, T, U> fmt::Display for ty::OutlivesPredicate<T,U>
+    where T: fmt::Display, U: fmt::Display
 {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("{} : {}",
-                self.0.user_string(tcx),
-                self.1.user_string(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for ty::EquatePredicate<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("EquatePredicate({}, {})",
-                self.0.repr(tcx),
-                self.1.repr(tcx))
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} : {}", self.0, self.1)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::EquatePredicate<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("{} == {}",
-                self.0.user_string(tcx),
-                self.1.user_string(tcx))
+impl<'tcx> fmt::Display for ty::EquatePredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} == {}", self.0, self.1)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::TraitPredicate<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("TraitPredicate({})",
-                self.trait_ref.repr(tcx))
+impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TraitPredicate({:?})",
+               self.trait_ref)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::TraitPredicate<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("{} : {}",
-                self.trait_ref.self_ty().user_string(tcx),
-                self.trait_ref.user_string(tcx))
+impl<'tcx> fmt::Display for ty::TraitPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} : {}",
+               self.trait_ref.self_ty(),
+               self.trait_ref)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("{} == {}",
-                self.projection_ty.user_string(tcx),
-                self.ty.user_string(tcx))
+impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ProjectionPredicate({:?}, {:?})",
+               self.projection_ty,
+               self.ty)
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("{}::{}",
-                self.trait_ref.repr(tcx),
-                self.item_name.repr(tcx))
+impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} == {}",
+               self.projection_ty,
+               self.ty)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::ProjectionTy<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("<{} as {}>::{}",
-                self.trait_ref.self_ty().user_string(tcx),
-                self.trait_ref.user_string(tcx),
-                self.item_name.user_string(tcx))
+impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}::{}",
+               self.trait_ref,
+               self.item_name)
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ty::Predicate::Trait(ref data) => data.user_string(tcx),
-            ty::Predicate::Equate(ref predicate) => predicate.user_string(tcx),
-            ty::Predicate::RegionOutlives(ref predicate) => predicate.user_string(tcx),
-            ty::Predicate::TypeOutlives(ref predicate) => predicate.user_string(tcx),
-            ty::Predicate::Projection(ref predicate) => predicate.user_string(tcx),
+            ty::Predicate::Trait(ref data) => write!(f, "{}", data),
+            ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
         }
     }
 }
-
-impl<'tcx> Repr<'tcx> for ast::Unsafety {
-    fn repr(&self, _: &ctxt<'tcx>) -> String {
-        format!("{:?}", *self)
-    }
-}
index cad1522ee1344b22b81a7382d18fe7104c83be49..c7968db4733a2ace8be070c155a16e5f8ecc6a04 100644 (file)
@@ -11,6 +11,7 @@
 //! A helper class for dealing with static archives
 
 use std::env;
+use std::ffi::OsString;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io;
@@ -30,16 +31,12 @@ pub struct ArchiveConfig<'a> {
     pub lib_search_paths: Vec<PathBuf>,
     pub slib_prefix: String,
     pub slib_suffix: String,
-    pub maybe_ar_prog: Option<String>
+    pub ar_prog: String,
+    pub command_path: OsString,
 }
 
 pub struct Archive<'a> {
-    handler: &'a ErrorHandler,
-    dst: PathBuf,
-    lib_search_paths: Vec<PathBuf>,
-    slib_prefix: String,
-    slib_suffix: String,
-    maybe_ar_prog: Option<String>
+    config: ArchiveConfig<'a>,
 }
 
 /// Helper for adding many files to an archive with a single invocation of
@@ -53,47 +50,10 @@ pub struct ArchiveBuilder<'a> {
     should_update_symbols: bool,
 }
 
-fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
-          args: &str, cwd: Option<&Path>,
-          paths: &[&Path]) -> Output {
-    let ar = match *maybe_ar_prog {
-        Some(ref ar) => &ar[..],
-        None => "ar"
-    };
-    let mut cmd = Command::new(ar);
-
-    cmd.arg(args).args(paths).stdout(Stdio::piped()).stderr(Stdio::piped());
-    debug!("{:?}", cmd);
-
-    match cwd {
-        Some(p) => {
-            cmd.current_dir(p);
-            debug!("inside {:?}", p.display());
-        }
-        None => {}
-    }
-
-    match cmd.spawn() {
-        Ok(prog) => {
-            let o = prog.wait_with_output().unwrap();
-            if !o.status.success() {
-                handler.err(&format!("{:?} failed with: {}", cmd, o.status));
-                handler.note(&format!("stdout ---\n{}",
-                                  str::from_utf8(&o.stdout).unwrap()));
-                handler.note(&format!("stderr ---\n{}",
-                                  str::from_utf8(&o.stderr).unwrap())
-                             );
-                handler.abort_if_errors();
-            }
-            o
-        },
-        Err(e) => {
-            handler.err(&format!("could not exec `{}`: {}", &ar[..],
-                             e));
-            handler.abort_if_errors();
-            panic!("rustc::back::archive::run_ar() should not reach this point");
-        }
-    }
+enum Action<'a> {
+    Remove(&'a Path),
+    AddObjects(&'a [&'a PathBuf], bool),
+    UpdateSymbols,
 }
 
 pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
@@ -120,43 +80,90 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
 
 impl<'a> Archive<'a> {
     fn new(config: ArchiveConfig<'a>) -> Archive<'a> {
-        let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix,
-            maybe_ar_prog } = config;
-        Archive {
-            handler: handler,
-            dst: dst,
-            lib_search_paths: lib_search_paths,
-            slib_prefix: slib_prefix,
-            slib_suffix: slib_suffix,
-            maybe_ar_prog: maybe_ar_prog
-        }
+        Archive { config: config }
     }
 
     /// Opens an existing static archive
     pub fn open(config: ArchiveConfig<'a>) -> Archive<'a> {
         let archive = Archive::new(config);
-        assert!(archive.dst.exists());
+        assert!(archive.config.dst.exists());
         archive
     }
 
     /// Removes a file from this archive
     pub fn remove_file(&mut self, file: &str) {
-        run_ar(self.handler, &self.maybe_ar_prog, "d", None, &[&self.dst, &Path::new(file)]);
+        self.run(None, Action::Remove(Path::new(file)));
     }
 
     /// Lists all files in an archive
     pub fn files(&self) -> Vec<String> {
-        let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]);
-        let output = str::from_utf8(&output.stdout).unwrap();
-        // use lines_any because windows delimits output with `\r\n` instead of
-        // just `\n`
-        output.lines_any().map(|s| s.to_string()).collect()
+        let archive = match ArchiveRO::open(&self.config.dst) {
+            Some(ar) => ar,
+            None => return Vec::new(),
+        };
+        let ret = archive.iter().filter_map(|child| child.name())
+                         .map(|name| name.to_string())
+                         .collect();
+        return ret;
     }
 
     /// Creates an `ArchiveBuilder` for adding files to this archive.
     pub fn extend(self) -> ArchiveBuilder<'a> {
         ArchiveBuilder::new(self)
     }
+
+    fn run(&self, cwd: Option<&Path>, action: Action) -> Output {
+        let abs_dst = env::current_dir().unwrap().join(&self.config.dst);
+        let ar = &self.config.ar_prog;
+        let mut cmd = Command::new(ar);
+        cmd.env("PATH", &self.config.command_path);
+        cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
+        self.prepare_ar_action(&mut cmd, &abs_dst, action);
+        info!("{:?}", cmd);
+
+        if let Some(p) = cwd {
+            cmd.current_dir(p);
+            info!("inside {:?}", p.display());
+        }
+
+        let handler = &self.config.handler;
+        match cmd.spawn() {
+            Ok(prog) => {
+                let o = prog.wait_with_output().unwrap();
+                if !o.status.success() {
+                    handler.err(&format!("{:?} failed with: {}", cmd, o.status));
+                    handler.note(&format!("stdout ---\n{}",
+                                          str::from_utf8(&o.stdout).unwrap()));
+                    handler.note(&format!("stderr ---\n{}",
+                                          str::from_utf8(&o.stderr).unwrap()));
+                    handler.abort_if_errors();
+                }
+                o
+            },
+            Err(e) => {
+                handler.err(&format!("could not exec `{}`: {}",
+                                     self.config.ar_prog, e));
+                handler.abort_if_errors();
+                panic!("rustc::back::archive::run() should not reach this point");
+            }
+        }
+    }
+
+    fn prepare_ar_action(&self, cmd: &mut Command, dst: &Path, action: Action) {
+        match action {
+            Action::Remove(file) => {
+                cmd.arg("d").arg(dst).arg(file);
+            }
+            Action::AddObjects(objs, update_symbols) => {
+                cmd.arg(if update_symbols {"crs"} else {"crS"})
+                   .arg(dst)
+                   .args(objs);
+            }
+            Action::UpdateSymbols => {
+                cmd.arg("s").arg(dst);
+            }
+        }
+    }
 }
 
 impl<'a> ArchiveBuilder<'a> {
@@ -179,10 +186,10 @@ impl<'a> ArchiveBuilder<'a> {
     /// search in the relevant locations for a library named `name`.
     pub fn add_native_library(&mut self, name: &str) -> io::Result<()> {
         let location = find_library(name,
-                                    &self.archive.slib_prefix,
-                                    &self.archive.slib_suffix,
-                                    &self.archive.lib_search_paths,
-                                    self.archive.handler);
+                                    &self.archive.config.slib_prefix,
+                                    &self.archive.config.slib_suffix,
+                                    &self.archive.config.lib_search_paths,
+                                    self.archive.config.handler);
         self.add_archive(&location, name, |_| false)
     }
 
@@ -229,17 +236,13 @@ impl<'a> ArchiveBuilder<'a> {
     pub fn build(self) -> Archive<'a> {
         // Get an absolute path to the destination, so `ar` will work even
         // though we run it from `self.work_dir`.
-        let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
-        assert!(!abs_dst.is_relative());
-        let mut args = vec![&*abs_dst];
-        let mut total_len = abs_dst.to_string_lossy().len();
+        let mut objects = Vec::new();
+        let mut total_len = self.archive.config.dst.to_string_lossy().len();
 
         if self.members.is_empty() {
-            // OSX `ar` does not allow using `r` with no members, but it does
-            // allow running `ar s file.a` to update symbols only.
             if self.should_update_symbols {
-                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
-                       "s", Some(self.work_dir.path()), &args[..]);
+                self.archive.run(Some(self.work_dir.path()),
+                                 Action::UpdateSymbols);
             }
             return self.archive;
         }
@@ -257,24 +260,22 @@ impl<'a> ArchiveBuilder<'a> {
             // string, not an array of strings.)
             if total_len + len + 1 > ARG_LENGTH_LIMIT {
                 // Add the archive members seen so far, without updating the
-                // symbol table (`S`).
-                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
-                       "cruS", Some(self.work_dir.path()), &args[..]);
+                // symbol table.
+                self.archive.run(Some(self.work_dir.path()),
+                                 Action::AddObjects(&objects, false));
 
-                args.clear();
-                args.push(&abs_dst);
-                total_len = abs_dst.to_string_lossy().len();
+                objects.clear();
+                total_len = self.archive.config.dst.to_string_lossy().len();
             }
 
-            args.push(member_name);
+            objects.push(member_name);
             total_len += len + 1;
         }
 
         // Add the remaining archive members, and update the symbol table if
         // necessary.
-        let flags = if self.should_update_symbols { "crus" } else { "cruS" };
-        run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
-               flags, Some(self.work_dir.path()), &args[..]);
+        self.archive.run(Some(self.work_dir.path()),
+                         Action::AddObjects(&objects, self.should_update_symbols));
 
         self.archive
     }
@@ -305,6 +306,8 @@ impl<'a> ArchiveBuilder<'a> {
             };
             if filename.contains(".SYMDEF") { continue }
             if skip(filename) { continue }
+            let filename = Path::new(filename).file_name().unwrap()
+                                              .to_str().unwrap();
 
             // Archives on unix systems typically do not have slashes in
             // filenames as the `ar` utility generally only uses the last
index 3e55f7f8045b59b60ee38723f34655e43f987924..297041a99079072577940109fe7e01c2dded21d3 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(core)]
+#![feature(fs_canonicalize)]
+#![feature(libc)]
+#![feature(path_ext)]
+#![feature(rand)]
 #![feature(rustc_private)]
+#![feature(slice_bytes)]
 #![feature(staged_api)]
-#![feature(rand)]
-#![feature(path_ext)]
 #![feature(step_by)]
-#![feature(libc)]
-#![feature(fs_canonicalize)]
+#![feature(vec_push_all)]
 #![cfg_attr(test, feature(test, rand))]
 
 extern crate syntax;
index 9ed827da8b2e4de2194e8289b282b2b6f6c4e5a0..efbd4c3ef5ec26cc98369cf21e25a037cfc4ef3c 100644 (file)
@@ -482,6 +482,7 @@ pub struct Sha256 {
 
 impl Sha256 {
     /// Construct a new instance of a SHA-256 digest.
+    /// Do not – under any circumstances – use this where timing attacks might be possible!
     pub fn new() -> Sha256 {
         Sha256 {
             engine: Engine256::new(&H256)
index dcf1a12f2c9ad762dd6f1b84cc0227e473d88c9b..3ec6307c72f86420481f59fd9badeac245f2ffbf 100644 (file)
@@ -18,11 +18,6 @@ pub fn opts() -> TargetOptions {
         executables: true,
         morestack: true,
         has_rpath: true,
-        pre_link_args: vec!(
-            "-L/usr/local/lib".to_string(),
-            "-L/usr/local/lib/gcc46".to_string(),
-            "-L/usr/local/lib/gcc44".to_string(),
-        ),
 
         .. Default::default()
     }
index 823a4a81fa4c19f98f1cf04834c7640ad9695530..3ae70ca854bdbf5c6083978bdf41923cd0d5200a 100644 (file)
@@ -13,7 +13,6 @@ use std::default::Default;
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        linker: "cc".to_string(),
         dynamic_linking: true,
         executables: true,
         morestack: true,
index c5f1882fa1dd7d33409db8a850b246e2bbc20efb..402fbcd8d8d8e6ebf74007072b47f546314cb38b 100644 (file)
@@ -59,6 +59,7 @@ mod freebsd_base;
 mod linux_base;
 mod openbsd_base;
 mod windows_base;
+mod windows_msvc_base;
 
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
@@ -92,6 +93,8 @@ pub struct Target {
 pub struct TargetOptions {
     /// Linker to invoke. Defaults to "cc".
     pub linker: String,
+    /// Archive utility to use when managing archives. Defaults to "ar".
+    pub ar: String,
     /// Linker arguments that are unconditionally passed *before* any
     /// user-defined libraries.
     pub pre_link_args: Vec<String>,
@@ -145,6 +148,7 @@ pub struct TargetOptions {
     /// only really used for figuring out how to find libraries, since Windows uses its own
     /// library naming convention. Defaults to false.
     pub is_like_windows: bool,
+    pub is_like_msvc: bool,
     /// Whether the target toolchain is like Android's. Only useful for compiling against Android.
     /// Defaults to false.
     pub is_like_android: bool,
@@ -152,22 +156,24 @@ pub struct TargetOptions {
     pub linker_is_gnu: bool,
     /// Whether the linker support rpaths or not. Defaults to false.
     pub has_rpath: bool,
-    /// Whether to disable linking to compiler-rt. Defaults to false, as LLVM will emit references
-    /// to the functions that compiler-rt provides.
+    /// 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,
-    /// 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 the functions in the executable are not randomized and can
-    /// be used during an exploit of a vulnerability in any code.
+    /// 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
+    /// the functions in the executable are not randomized and can be used
+    /// during an exploit of a vulnerability in any code.
     pub position_independent_executables: bool,
 }
 
 impl Default for TargetOptions {
-    /// Create a set of "sane defaults" for any target. This is still incomplete, and if used for
-    /// compilation, will certainly not work.
+    /// Create a set of "sane defaults" for any target. This is still
+    /// incomplete, and if used for compilation, will certainly not work.
     fn default() -> TargetOptions {
         TargetOptions {
             linker: "cc".to_string(),
+            ar: "ar".to_string(),
             pre_link_args: Vec::new(),
             post_link_args: Vec::new(),
             cpu: "generic".to_string(),
@@ -188,6 +194,7 @@ impl Default for TargetOptions {
             is_like_osx: false,
             is_like_windows: false,
             is_like_android: false,
+            is_like_msvc: false,
             linker_is_gnu: false,
             has_rpath: false,
             no_compiler_rt: false,
@@ -218,7 +225,7 @@ impl Target {
         // this is 1. ugly, 2. error prone.
 
 
-        let handler = diagnostic::default_handler(diagnostic::Auto, None, true);
+        let handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
 
         let get_req_field = |name: &str| {
             match obj.find(name)
@@ -265,6 +272,7 @@ impl Target {
         }
 
         key!(cpu);
+        key!(ar);
         key!(linker);
         key!(relocation_model);
         key!(code_model);
@@ -371,7 +379,9 @@ impl Target {
             armv7s_apple_ios,
 
             x86_64_pc_windows_gnu,
-            i686_pc_windows_gnu
+            i686_pc_windows_gnu,
+
+            x86_64_pc_windows_msvc
         );
 
 
diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs
new file mode 100644 (file)
index 0000000..30d74c8
--- /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.
+
+use target::TargetOptions;
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        function_sections: true,
+        linker: "link.exe".to_string(),
+        // When taking a look at the value of this `ar` field, one might expect
+        // `lib.exe` to be the value here! The `lib.exe` program is the default
+        // tool for managing `.lib` archives on Windows, but unfortunately the
+        // compiler cannot use it.
+        //
+        // To recap, we use `ar` here to manage rlibs (which are just archives).
+        // LLVM does not expose bindings for modifying archives so we have to
+        // invoke this utility for write operations (e.g. deleting files, adding
+        // files, etc). Normally archives only have object files within them,
+        // but the compiler also uses archives for storing metadata and
+        // compressed bytecode, so we don't exactly fall within "normal use
+        // cases".
+        //
+        // MSVC's `lib.exe` tool by default will choke when adding a non-object
+        // file to an archive, which we do on a regular basis, making it
+        // inoperable for us. Luckily, however, LLVM has already rewritten `ar`
+        // in the form of `llvm-ar` which is built by default when we build
+        // LLVM. This tool, unlike `lib.exe`, works just fine with non-object
+        // files, so we use it instead.
+        //
+        // Note that there's a few caveats associated with this:
+        //
+        // * This still requires that the *linker* (the consumer of rlibs) will
+        //   ignore non-object files. Thankfully `link.exe` on Windows does
+        //   indeed ignore non-object files in archives.
+        // * This requires `llvm-ar.exe` to be distributed with the compiler
+        //   itself, but we already make sure of this elsewhere.
+        //
+        // Perhaps one day we won't even need this tool at all and we'll just be
+        // able to make library calls into LLVM!
+        ar: "llvm-ar.exe".to_string(),
+        dynamic_linking: true,
+        executables: true,
+        dll_prefix: "".to_string(),
+        dll_suffix: ".dll".to_string(),
+        exe_suffix: ".exe".to_string(),
+        staticlib_prefix: "".to_string(),
+        staticlib_suffix: ".lib".to_string(),
+        morestack: false,
+        is_like_windows: true,
+        is_like_msvc: true,
+        pre_link_args: vec![
+            "/NOLOGO".to_string(),
+            "/NXCOMPAT".to_string(),
+        ],
+
+        .. Default::default()
+    }
+}
diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
new file mode 100644 (file)
index 0000000..f7c3ca4
--- /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.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::windows_msvc_base::opts();
+    base.cpu = "x86-64".to_string();
+
+    Target {
+        // This is currently in sync with the specification for
+        // x86_64-pc-windows-gnu but there's a comment in that file questioning
+        // whether this is valid or not. Sounds like the two should stay in sync
+        // at least for now.
+        data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
+                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
+        llvm_target: "x86_64-pc-windows-msvc".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "windows".to_string(),
+        target_env: "msvc".to_string(),
+        options: base,
+    }
+}
index 6d23cad26cb37e76d07362fbe3f31b5e1893b1af..b59c24cf12bdb5e4e717443c0b55b8737cb84f8a 100644 (file)
@@ -19,7 +19,7 @@
 #![feature(no_std)]
 #![no_std]
 #![unstable(feature = "rustc_private")]
-#![cfg_attr(test, feature(hash))]
+#![cfg_attr(test, feature(hash_default))]
 
 //! A typesafe bitmask flag generator.
 
index 08f0897e7617e918e320dedd16d3ae3201cdd45b..5cfbd59d3336881ecc0e6d450ae8198e338c3af4 100644 (file)
@@ -170,7 +170,7 @@ overwrite (or freeze) `(*x).f`, and thus invalidate the reference
 that was created. In general it holds that when a path is
 lent, restrictions are issued for all the owning prefixes of that
 path. In this case, the path `*x` owns the path `(*x).f` and,
-because `x` is an owned pointer, the path `x` owns the path `*x`.
+because `x` has ownership, the path `x` owns the path `*x`.
 Therefore, borrowing `(*x).f` yields restrictions on both
 `*x` and `x`.
 
@@ -286,7 +286,7 @@ MUTABILITY(X, imm)                  // M-Var-Imm
 
 ### Checking mutability of owned content
 
-Fields and owned pointers inherit their mutability from
+Fields and boxes inherit their mutability from
 their base expressions, so both of their rules basically
 delegate the check to the base expression `LV`:
 
@@ -387,7 +387,7 @@ LIFETIME(X, LT, MQ)                 // L-Local
 
 ### Checking lifetime for owned content
 
-The lifetime of a field or owned pointer is the same as the lifetime
+The lifetime of a field or box is the same as the lifetime
 of its owner:
 
 ```text
@@ -466,10 +466,10 @@ origin of inherited mutability.
 
 Because the mutability of owned referents is inherited, restricting an
 owned referent is similar to restricting a field, in that it implies
-restrictions on the pointer. However, owned pointers have an important
+restrictions on the pointer. However, boxes have an important
 twist: if the owner `LV` is mutated, that causes the owned referent
 `*LV` to be freed! So whenever an owned referent `*LV` is borrowed, we
-must prevent the owned pointer `LV` from being mutated, which means
+must prevent the box `LV` from being mutated, which means
 that we always add `MUTATE` and `CLAIM` to the restriction set imposed
 on `LV`:
 
@@ -648,7 +648,7 @@ fn main() {
 ```
 
 Clause (2) propagates the restrictions on the referent to the pointer
-itself. This is the same as with an owned pointer, though the
+itself. This is the same as with an box, though the
 reasoning is mildly different. The basic goal in all cases is to
 prevent the user from establishing another route to the same data. To
 see what I mean, let's examine various cases of what can go wrong and
index 839b39a8ca003a304170dc613a38241cbfbae8b4..49933441cf01ec4b1b76160e9ded6c7842b4d812 100644 (file)
@@ -24,7 +24,6 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty;
-use rustc::util::ppaux::Repr;
 use syntax::ast;
 use syntax::codemap::Span;
 
@@ -97,8 +96,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
                consume_span: Span,
                cmt: mc::cmt<'tcx>,
                mode: euv::ConsumeMode) {
-        debug!("consume(consume_id={}, cmt={}, mode={:?})",
-               consume_id, cmt.repr(self.tcx()), mode);
+        debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
+               consume_id, cmt, mode);
 
         self.consume_common(consume_id, consume_span, cmt, mode);
     }
@@ -112,9 +111,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
                    consume_pat: &ast::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode) {
-        debug!("consume_pat(consume_pat={}, cmt={}, mode={:?})",
-               consume_pat.repr(self.tcx()),
-               cmt.repr(self.tcx()),
+        debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
+               consume_pat,
+               cmt,
                mode);
 
         self.consume_common(consume_pat.id, consume_pat.span, cmt, mode);
@@ -128,9 +127,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
               bk: ty::BorrowKind,
               loan_cause: euv::LoanCause)
     {
-        debug!("borrow(borrow_id={}, cmt={}, loan_region={:?}, \
+        debug!("borrow(borrow_id={}, cmt={:?}, loan_region={:?}, \
                bk={:?}, loan_cause={:?})",
-               borrow_id, cmt.repr(self.tcx()), loan_region,
+               borrow_id, cmt, loan_region,
                bk, loan_cause);
 
         match opt_loan_path(&cmt) {
@@ -153,8 +152,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
               assignee_cmt: mc::cmt<'tcx>,
               mode: euv::MutateMode)
     {
-        debug!("mutate(assignment_id={}, assignee_cmt={})",
-               assignment_id, assignee_cmt.repr(self.tcx()));
+        debug!("mutate(assignment_id={}, assignee_cmt={:?})",
+               assignment_id, assignee_cmt);
 
         match opt_loan_path(&assignee_cmt) {
             Some(lp) => {
@@ -384,9 +383,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         //! Checks whether `old_loan` and `new_loan` can safely be issued
         //! simultaneously.
 
-        debug!("report_error_if_loans_conflict(old_loan={}, new_loan={})",
-               old_loan.repr(self.tcx()),
-               new_loan.repr(self.tcx()));
+        debug!("report_error_if_loans_conflict(old_loan={:?}, new_loan={:?})",
+               old_loan,
+               new_loan);
 
         // Should only be called for loans that are in scope at the same time.
         assert!(self.tcx().region_maps.scopes_intersect(old_loan.kill_scope,
@@ -408,9 +407,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         //! prohibit `loan2`. Returns false if an error is reported.
 
         debug!("report_error_if_loan_conflicts_with_restriction(\
-                loan1={}, loan2={})",
-               loan1.repr(self.tcx()),
-               loan2.repr(self.tcx()));
+                loan1={:?}, loan2={:?})",
+               loan1,
+               loan2);
 
         if compatible_borrow_kinds(loan1.kind, loan2.kind) {
             return true;
@@ -672,9 +671,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                                        use_path: &LoanPath<'tcx>,
                                        borrow_kind: ty::BorrowKind)
                                        -> UseError<'tcx> {
-        debug!("analyze_restrictions_on_use(expr_id={}, use_path={})",
+        debug!("analyze_restrictions_on_use(expr_id={}, use_path={:?})",
                self.tcx().map.node_to_string(expr_id),
-               use_path.repr(self.tcx()));
+               use_path);
 
         let mut ret = UseOk;
 
@@ -698,8 +697,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                               span: Span,
                               use_kind: MovedValueUseKind,
                               lp: &Rc<LoanPath<'tcx>>) {
-        debug!("check_if_path_is_moved(id={}, use_kind={:?}, lp={})",
-               id, use_kind, lp.repr(self.bccx.tcx));
+        debug!("check_if_path_is_moved(id={}, use_kind={:?}, lp={:?})",
+               id, use_kind, lp);
 
         // FIXME (22079): if you find yourself tempted to cut and paste
         // the body below and then specializing the error reporting,
@@ -752,7 +751,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             }
             LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
                 match lp_base.to_type().sty {
-                    ty::ty_struct(def_id, _) | ty::ty_enum(def_id, _) => {
+                    ty::TyStruct(def_id, _) | ty::TyEnum(def_id, _) => {
                         if ty::has_dtor(self.tcx(), def_id) {
                             // In the case where the owner implements drop, then
                             // the path must be initialized to prevent a case of
@@ -792,7 +791,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                         assignment_span: Span,
                         assignee_cmt: mc::cmt<'tcx>,
                         mode: euv::MutateMode) {
-        debug!("check_assignment(assignee_cmt={})", assignee_cmt.repr(self.tcx()));
+        debug!("check_assignment(assignee_cmt={:?})", assignee_cmt);
 
         // Mutable values can be assigned, as long as they obey loans
         // and aliasing restrictions:
@@ -884,7 +883,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             //! `used_mut_nodes` table here.
 
             loop {
-                debug!("mark_variable_as_used_mut(cmt={})", cmt.repr(this.tcx()));
+                debug!("mark_variable_as_used_mut(cmt={:?})", cmt);
                 match cmt.cat.clone() {
                     mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: id, .. }, .. }) |
                     mc::cat_local(id) => {
@@ -929,8 +928,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             //! Safety checks related to writes to aliasable, mutable locations
 
             let guarantor = cmt.guarantor();
-            debug!("check_for_aliasable_mutable_writes(cmt={}, guarantor={})",
-                   cmt.repr(this.tcx()), guarantor.repr(this.tcx()));
+            debug!("check_for_aliasable_mutable_writes(cmt={:?}, guarantor={:?})",
+                   cmt, guarantor);
             if let mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) = guarantor.cat {
                 // Statically prohibit writes to `&mut` when aliasable
                 check_for_aliasability_violation(this, span, b.clone());
index fa2ff43ecfe9371d356bb32608da490d82c6276a..93f5ac529d3fd2032ddea1b425e00fc7f3dbc9b3 100644 (file)
@@ -22,7 +22,7 @@ use borrowck::move_data::InvalidMovePathIndex;
 use borrowck::move_data::{MoveData, MovePathIndex};
 use rustc::middle::ty;
 use rustc::middle::mem_categorization as mc;
-use rustc::util::ppaux::{Repr, UserString};
+
 use std::mem;
 use std::rc::Rc;
 use syntax::ast;
@@ -42,21 +42,19 @@ enum Fragment {
 }
 
 impl Fragment {
-    fn loan_path_repr<'tcx>(&self, move_data: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) -> String {
-        let repr = |mpi| move_data.path_loan_path(mpi).repr(tcx);
+    fn loan_path_repr(&self, move_data: &MoveData) -> String {
+        let lp = |mpi| move_data.path_loan_path(mpi);
         match *self {
-            Just(mpi) => repr(mpi),
-            AllButOneFrom(mpi) => format!("$(allbutone {})", repr(mpi)),
+            Just(mpi) => format!("{:?}", lp(mpi)),
+            AllButOneFrom(mpi) => format!("$(allbutone {:?})", lp(mpi)),
         }
     }
 
-    fn loan_path_user_string<'tcx>(&self,
-                                   move_data: &MoveData<'tcx>,
-                                   tcx: &ty::ctxt<'tcx>) -> String {
-        let user_string = |mpi| move_data.path_loan_path(mpi).user_string(tcx);
+    fn loan_path_user_string(&self, move_data: &MoveData) -> String {
+        let lp = |mpi| move_data.path_loan_path(mpi);
         match *self {
-            Just(mpi) => user_string(mpi),
-            AllButOneFrom(mpi) => format!("$(allbutone {})", user_string(mpi)),
+            Just(mpi) => lp(mpi).to_string(),
+            AllButOneFrom(mpi) => format!("$(allbutone {})", lp(mpi)),
         }
     }
 }
@@ -126,19 +124,19 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
 
     let instrument_all_paths = |kind, vec_rc: &Vec<MovePathIndex>| {
         for (i, mpi) in vec_rc.iter().enumerate() {
-            let render = || this.path_loan_path(*mpi).user_string(tcx);
+            let lp = || this.path_loan_path(*mpi);
             if span_err {
-                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render()));
+                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, lp()));
             }
             if print {
-                println!("id:{} {}[{}] `{}`", id, kind, i, render());
+                println!("id:{} {}[{}] `{}`", id, kind, i, lp());
             }
         }
     };
 
     let instrument_all_fragments = |kind, vec_rc: &Vec<Fragment>| {
         for (i, f) in vec_rc.iter().enumerate() {
-            let render = || f.loan_path_user_string(this, tcx);
+            let render = || f.loan_path_user_string(this);
             if span_err {
                 tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render()));
             }
@@ -172,11 +170,11 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) {
     let mut assigned = mem::replace(&mut fragments.assigned_leaf_paths, vec![]);
 
     let path_lps = |mpis: &[MovePathIndex]| -> Vec<String> {
-        mpis.iter().map(|mpi| this.path_loan_path(*mpi).repr(tcx)).collect()
+        mpis.iter().map(|mpi| format!("{:?}", this.path_loan_path(*mpi))).collect()
     };
 
     let frag_lps = |fs: &[Fragment]| -> Vec<String> {
-        fs.iter().map(|f| f.loan_path_repr(this, tcx)).collect()
+        fs.iter().map(|f| f.loan_path_repr(this)).collect()
     };
 
     // First, filter out duplicates
@@ -339,12 +337,12 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
     };
 
     match (&parent_ty.sty, enum_variant_info) {
-        (&ty::ty_tup(ref v), None) => {
+        (&ty::TyTuple(ref v), None) => {
             let tuple_idx = match *origin_field_name {
                 mc::PositionalField(tuple_idx) => tuple_idx,
                 mc::NamedField(_) =>
-                    panic!("tuple type {} should not have named fields.",
-                           parent_ty.repr(tcx)),
+                    panic!("tuple type {:?} should not have named fields.",
+                           parent_ty),
             };
             let tuple_len = v.len();
             for i in 0..tuple_len {
@@ -354,7 +352,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
             }
         }
 
-        (&ty::ty_struct(def_id, ref _substs), None) => {
+        (&ty::TyStruct(def_id, ref _substs), None) => {
             let fields = ty::lookup_struct_fields(tcx, def_id);
             match *origin_field_name {
                 mc::NamedField(ast_name) => {
@@ -378,7 +376,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
             }
         }
 
-        (&ty::ty_enum(enum_def_id, substs), ref enum_variant_info) => {
+        (&ty::TyEnum(enum_def_id, substs), ref enum_variant_info) => {
             let variant_info = {
                 let mut variants = ty::substd_enum_variants(tcx, enum_def_id, substs);
                 match *enum_variant_info {
@@ -418,8 +416,8 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
         }
 
         ref sty_and_variant_info => {
-            let msg = format!("type {} ({:?}) is not fragmentable",
-                              parent_ty.repr(tcx), sty_and_variant_info);
+            let msg = format!("type {:?} ({:?}) is not fragmentable",
+                              parent_ty, sty_and_variant_info);
             let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
             tcx.sess.opt_span_bug(opt_span, &msg[..])
         }
@@ -450,8 +448,8 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>,
     };
     let new_lp_variant = LpExtend(parent, mc, loan_path_elem);
     let new_lp = LoanPath::new(new_lp_variant, new_lp_type.unwrap());
-    debug!("add_fragment_sibling_core(new_lp={}, origin_lp={})",
-           new_lp.repr(tcx), origin_lp.repr(tcx));
+    debug!("add_fragment_sibling_core(new_lp={:?}, origin_lp={:?})",
+           new_lp, origin_lp);
     let mp = this.move_path(tcx, Rc::new(new_lp));
 
     // Do not worry about checking for duplicates here; we will sort
index d0f5aa8cf003b5e36f8996913723cbb6cfeaffeb..7b6c54dbaca44945fa2ba02cc411743836e34e4f 100644 (file)
@@ -18,7 +18,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
 use rustc::middle::ty;
-use rustc::util::ppaux::Repr;
+
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
@@ -66,8 +66,8 @@ pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       cmt: mc::cmt<'tcx>,
                                       mode: euv::MatchMode) {
     let tcx = bccx.tcx;
-    debug!("gather_match_variant(move_pat={}, cmt={}, mode={:?})",
-           move_pat.id, cmt.repr(tcx), mode);
+    debug!("gather_match_variant(move_pat={}, cmt={:?}, mode={:?})",
+           move_pat.id, cmt, mode);
 
     let opt_lp = opt_loan_path(&cmt);
     match opt_lp {
@@ -115,14 +115,14 @@ fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                          move_data: &MoveData<'tcx>,
                          move_error_collector: &MoveErrorCollector<'tcx>,
                          move_info: GatherMoveInfo<'tcx>) {
-    debug!("gather_move(move_id={}, cmt={})",
-           move_info.id, move_info.cmt.repr(bccx.tcx));
+    debug!("gather_move(move_id={}, cmt={:?})",
+           move_info.id, move_info.cmt);
 
     let potentially_illegal_move =
                 check_and_get_illegal_move_origin(bccx, &move_info.cmt);
     match potentially_illegal_move {
         Some(illegal_move_origin) => {
-            debug!("illegal_move_origin={}", illegal_move_origin.repr(bccx.tcx));
+            debug!("illegal_move_origin={:?}", illegal_move_origin);
             let error = MoveError::with_move_info(illegal_move_origin,
                                                   move_info.span_path_opt);
             move_error_collector.add_error(error);
@@ -137,7 +137,7 @@ fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                move_info.id, move_info.kind);
         }
         None => {
-            // move from rvalue or unsafe pointer, hence ok
+            // move from rvalue or raw pointer, hence ok
         }
     }
 }
@@ -179,7 +179,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         mc::cat_interior(ref b, mc::InteriorField(_)) |
         mc::cat_interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
             match b.ty.sty {
-                ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
+                ty::TyStruct(did, _) | ty::TyEnum(did, _) => {
                     if ty::has_dtor(bccx.tcx, did) {
                         Some(cmt.clone())
                     } else {
index 9f7b4cf26e1c47fa60dabc40b6bdc37abb10c293..427d78e89b3e2dbe11a787298ac418e45c1f7d5d 100644 (file)
@@ -16,7 +16,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty;
-use rustc::util::ppaux::Repr;
+
 use syntax::ast;
 use syntax::codemap::Span;
 
@@ -33,8 +33,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     //! Reports error if `loan_region` is larger than S
     //! where S is `item_scope` if `cmt` is an upvar,
     //! and is scope of `cmt` otherwise.
-    debug!("guarantee_lifetime(cmt={}, loan_region={})",
-           cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
+    debug!("guarantee_lifetime(cmt={:?}, loan_region={:?})",
+           cmt, loan_region);
     let ctxt = GuaranteeLifetimeContext {bccx: bccx,
                                          item_scope: item_scope,
                                          span: span,
@@ -65,9 +65,9 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
         //! Main routine. Walks down `cmt` until we find the
         //! "guarantor".  Reports an error if `self.loan_region` is
         //! larger than scope of `cmt`.
-        debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
-               cmt.repr(self.bccx.tcx),
-               self.loan_region.repr(self.bccx.tcx));
+        debug!("guarantee_lifetime.check(cmt={:?}, loan_region={:?})",
+               cmt,
+               self.loan_region);
 
         match cmt.cat {
             mc::cat_rvalue(..) |
index 733d486d2d22d3ae495b10f2ddc233b423a1de4a..f00eb872642f4e5173c447878e7f23caf7b108d2 100644 (file)
@@ -22,7 +22,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty;
-use rustc::util::ppaux::Repr;
+
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::visit;
@@ -76,8 +76,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
                _consume_span: Span,
                cmt: mc::cmt<'tcx>,
                mode: euv::ConsumeMode) {
-        debug!("consume(consume_id={}, cmt={}, mode={:?})",
-               consume_id, cmt.repr(self.tcx()), mode);
+        debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
+               consume_id, cmt, mode);
 
         match mode {
             euv::Move(move_reason) => {
@@ -93,9 +93,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
                    matched_pat: &ast::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::MatchMode) {
-        debug!("matched_pat(matched_pat={}, cmt={}, mode={:?})",
-               matched_pat.repr(self.tcx()),
-               cmt.repr(self.tcx()),
+        debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})",
+               matched_pat,
+               cmt,
                mode);
 
         if let mc::cat_downcast(..) = cmt.cat {
@@ -109,9 +109,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
                    consume_pat: &ast::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode) {
-        debug!("consume_pat(consume_pat={}, cmt={}, mode={:?})",
-               consume_pat.repr(self.tcx()),
-               cmt.repr(self.tcx()),
+        debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
+               consume_pat,
+               cmt,
                mode);
 
         match mode {
@@ -132,9 +132,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
               bk: ty::BorrowKind,
               loan_cause: euv::LoanCause)
     {
-        debug!("borrow(borrow_id={}, cmt={}, loan_region={:?}, \
+        debug!("borrow(borrow_id={}, cmt={:?}, loan_region={:?}, \
                bk={:?}, loan_cause={:?})",
-               borrow_id, cmt.repr(self.tcx()), loan_region,
+               borrow_id, cmt, loan_region,
                bk, loan_cause);
 
         self.guarantee_valid(borrow_id,
@@ -152,8 +152,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
               mode: euv::MutateMode)
     {
         let opt_lp = opt_loan_path(&assignee_cmt);
-        debug!("mutate(assignment_id={}, assignee_cmt={}) opt_lp={:?}",
-               assignment_id, assignee_cmt.repr(self.tcx()), opt_lp);
+        debug!("mutate(assignment_id={}, assignee_cmt={:?}) opt_lp={:?}",
+               assignment_id, assignee_cmt, opt_lp);
 
         match opt_lp {
             Some(lp) => {
@@ -191,23 +191,11 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
             /* Uniquely accessible path -- OK for `&` and `&mut` */
             Ok(())
         }
-        (mc::Aliasability::FreelyAliasable(mc::AliasableStatic(safety)), ty::ImmBorrow) => {
-            // Borrow of an immutable static item:
-            match safety {
-                mc::InteriorUnsafe => {
-                    // If the static item contains an Unsafe<T>, it has interior
-                    // mutability.  In such cases, another phase of the compiler
-                    // will ensure that the type is `Sync` and then trans will
-                    // not put it in rodata, so this is ok to allow.
-                    Ok(())
-                }
-                mc::InteriorSafe => {
-                    // Immutable static can be borrowed, no problem.
-                    Ok(())
-                }
-            }
+        (mc::Aliasability::FreelyAliasable(mc::AliasableStatic), ty::ImmBorrow) => {
+            // Borrow of an immutable static item.
+            Ok(())
         }
-        (mc::Aliasability::FreelyAliasable(mc::AliasableStaticMut(..)), _) => {
+        (mc::Aliasability::FreelyAliasable(mc::AliasableStaticMut), _) => {
             // Even touching a static mut is considered unsafe. We assume the
             // user knows what they're doing in these cases.
             Ok(())
@@ -246,10 +234,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
                        req_kind: ty::BorrowKind,
                        loan_region: ty::Region,
                        cause: euv::LoanCause) {
-        debug!("guarantee_valid(borrow_id={}, cmt={}, \
+        debug!("guarantee_valid(borrow_id={}, cmt={:?}, \
                 req_mutbl={:?}, loan_region={:?})",
                borrow_id,
-               cmt.repr(self.tcx()),
+               cmt,
                req_kind,
                loan_region);
 
@@ -348,8 +336,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
             }
         };
 
-        debug!("guarantee_valid(borrow_id={}), loan={}",
-               borrow_id, loan.repr(self.tcx()));
+        debug!("guarantee_valid(borrow_id={}), loan={:?}",
+               borrow_id, loan);
 
         // let loan_path = loan.loan_path;
         // let loan_gen_scope = loan.gen_scope;
@@ -388,8 +376,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
                                       req_kind: ty::BorrowKind)
                                       -> Result<(),()> {
             //! Implements the M-* rules in README.md.
-            debug!("check_mutability(cause={:?} cmt={} req_kind={:?}",
-                   cause, cmt.repr(bccx.tcx), req_kind);
+            debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}",
+                   cause, cmt, req_kind);
             match req_kind {
                 ty::UniqueImmBorrow | ty::ImmBorrow => {
                     match cmt.mutbl {
@@ -519,7 +507,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
 
 pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &ast::Expr) {
 
-    debug!("gather_loans_in_static_initializer(expr={})", expr.repr(bccx.tcx));
+    debug!("gather_loans_in_static_initializer(expr={:?})", expr);
 
     let mut sicx = StaticInitializerCtxt {
         bccx: bccx
index 84636ebaae42b608d7ce09f161bfbb5574d7e075..9a29ed91339e2468646da1c59d408dc1b7b35870 100644 (file)
@@ -12,7 +12,6 @@ use borrowck::BorrowckCtxt;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
 use rustc::middle::ty;
-use rustc::util::ppaux::UserString;
 use std::cell::RefCell;
 use syntax::ast;
 use syntax::codemap;
@@ -99,7 +98,7 @@ fn group_errors_with_same_origin<'tcx>(errors: &Vec<MoveError<'tcx>>)
         for ge in &mut *grouped_errors {
             if move_from_id == ge.move_from.id && error.move_to.is_some() {
                 debug!("appending move_to to list");
-                ge.move_to_places.extend(move_to.into_iter());
+                ge.move_to_places.extend(move_to);
                 return
             }
         }
@@ -130,20 +129,20 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                 bccx.span_err(move_from.span,
                               &format!("cannot move out of type `{}`, \
                                         a non-copy fixed-size array",
-                                       b.ty.user_string(bccx.tcx)));
+                                       b.ty));
             }
         }
 
         mc::cat_downcast(ref b, _) |
         mc::cat_interior(ref b, mc::InteriorField(_)) => {
             match b.ty.sty {
-                ty::ty_struct(did, _) |
-                ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
+                ty::TyStruct(did, _) |
+                ty::TyEnum(did, _) if ty::has_dtor(bccx.tcx, did) => {
                     bccx.span_err(
                         move_from.span,
                         &format!("cannot move out of type `{}`, \
                                  which defines the `Drop` trait",
-                                b.ty.user_string(bccx.tcx)));
+                                b.ty));
                 },
                 _ => {
                     bccx.span_bug(move_from.span, "this path should not cause illegal move")
index 7078b2b5f1797c5ccd2d98c26ed0ba014445ce28..345f5378f69e106c0fd3142f66d31f94229f3de1 100644 (file)
@@ -16,7 +16,6 @@ use borrowck::*;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::ty;
-use rustc::util::ppaux::Repr;
 use syntax::codemap::Span;
 
 use borrowck::ToInteriorKind;
@@ -58,7 +57,7 @@ struct RestrictionsContext<'a, 'tcx: 'a> {
 impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
     fn restrict(&self,
                 cmt: mc::cmt<'tcx>) -> RestrictionResult<'tcx> {
-        debug!("restrict(cmt={})", cmt.repr(self.bccx.tcx));
+        debug!("restrict(cmt={:?})", cmt);
 
         let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
 
@@ -110,7 +109,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                     mc::Unique => {
                         // R-Deref-Send-Pointer
                         //
-                        // When we borrow the interior of an owned pointer, we
+                        // When we borrow the interior of a box, we
                         // cannot permit the base to be mutated, because that
                         // would cause the unique pointer to be freed.
                         //
@@ -145,7 +144,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                             }
                         }
                     }
-                    // Borrowck is not relevant for unsafe pointers
+                    // Borrowck is not relevant for raw pointers
                     mc::UnsafePtr(..) => Safe
                 }
             }
index 27adf5bf21b63297a5491ba94efd3bea8f50867d..6369621779cbd5ed3e99eb557328e1c9ff8de881 100644 (file)
@@ -20,23 +20,24 @@ pub use self::MovedValueUseKind::*;
 
 use self::InteriorKind::*;
 
+use rustc::ast_map;
+use rustc::ast_map::blocks::{FnLikeNode, FnParts};
 use rustc::middle::cfg;
 use rustc::middle::dataflow::DataFlowContext;
 use rustc::middle::dataflow::BitwiseOperator;
 use rustc::middle::dataflow::DataFlowOperator;
 use rustc::middle::dataflow::KillFrom;
 use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::mem_categorization as mc;
 use rustc::middle::free_region::FreeRegionMap;
+use rustc::middle::infer::error_reporting::note_and_explain_region;
+use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty::{self, Ty};
-use rustc::util::ppaux::{note_and_explain_region, Repr, UserString};
+
+use std::fmt;
 use std::mem;
 use std::rc::Rc;
-use std::string::String;
 use syntax::ast;
-use syntax::ast_map;
-use syntax::ast_map::blocks::{FnLikeNode, FnParts};
 use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -328,7 +329,7 @@ impl<'tcx> Loan<'tcx> {
     }
 }
 
-#[derive(Eq, Hash, Debug)]
+#[derive(Eq, Hash)]
 pub struct LoanPath<'tcx> {
     kind: LoanPathKind<'tcx>,
     ty: ty::Ty<'tcx>,
@@ -368,7 +369,7 @@ const DOWNCAST_PRINTED_OPERATOR: &'static str = " as ";
 // information that is not relevant to loan-path analysis. (In
 // particular, the distinction between how precisely a array-element
 // is tracked is irrelevant here.)
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum InteriorKind {
     InteriorField(mc::FieldName),
     InteriorElement(mc::ElementKind),
@@ -603,11 +604,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
 
         let (ol, moved_lp_msg) = match the_move.kind {
             move_data::Declared => {
-                self.tcx.sess.span_err(
-                    use_span,
-                    &format!("{} of possibly uninitialized variable: `{}`",
-                            verb,
-                            self.loan_path_to_string(lp)));
+                span_err!(
+                    self.tcx.sess, use_span, E0381,
+                    "{} of possibly uninitialized variable: `{}`",
+                    verb,
+                    self.loan_path_to_string(lp));
+
                 (self.loan_path_to_string(moved_lp),
                  String::new())
             }
@@ -644,12 +646,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 let msg = if !has_fork && partial { "partially " }
                           else if has_fork && !has_common { "collaterally "}
                           else { "" };
-                self.tcx.sess.span_err(
-                    use_span,
-                    &format!("{} of {}moved value: `{}`",
-                            verb,
-                            msg,
-                            nl));
+                span_err!(
+                    self.tcx.sess, use_span, E0382,
+                    "{} of {}moved value: `{}`",
+                    verb, msg, nl);
                 (ol, moved_lp_msg)
             }
         };
@@ -682,7 +682,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                   which is {}",
                                  ol,
                                  moved_lp_msg,
-                                 expr_ty.user_string(self.tcx),
+                                 expr_ty,
                                  suggestion));
                 } else {
                     self.tcx.sess.span_note(
@@ -690,7 +690,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         &format!("`{}` moved here{} because it has type `{}`, which is {}",
                                  ol,
                                  moved_lp_msg,
-                                 expr_ty.user_string(self.tcx),
+                                 expr_ty,
                                  suggestion));
                 }
             }
@@ -703,7 +703,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                              which is moved by default",
                             ol,
                             moved_lp_msg,
-                            pat_ty.user_string(self.tcx)));
+                            pat_ty));
                 self.tcx.sess.fileline_help(span,
                     "use `ref` to override");
             }
@@ -734,7 +734,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                             has type `{}`, which is {}",
                             ol,
                             moved_lp_msg,
-                            expr_ty.user_string(self.tcx),
+                            expr_ty,
                             suggestion));
                 self.tcx.sess.fileline_help(expr_span, help);
             }
@@ -762,12 +762,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             &self,
             span: Span,
             lp: &LoanPath<'tcx>) {
-        self.tcx
-            .sess
-            .span_err(span,
-                      &format!("partial reinitialization of uninitialized \
-                               structure `{}`",
-                               self.loan_path_to_string(lp)));
+        span_err!(
+            self.tcx.sess, span, E0383,
+            "partial reinitialization of uninitialized structure `{}`",
+            self.loan_path_to_string(lp));
     }
 
     pub fn report_reassigned_immutable_variable(&self,
@@ -775,10 +773,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                 lp: &LoanPath<'tcx>,
                                                 assign:
                                                 &move_data::Assignment) {
-        self.tcx.sess.span_err(
-            span,
-            &format!("re-assignment of immutable variable `{}`",
-                    self.loan_path_to_string(lp)));
+        span_err!(
+            self.tcx.sess, span, E0384,
+            "re-assignment of immutable variable `{}`",
+            self.loan_path_to_string(lp));
         self.tcx.sess.span_note(assign.span, "prior assignment occurs here");
     }
 
@@ -896,21 +894,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
 
         match cause {
             mc::AliasableOther => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("{} in an aliasable location",
-                             prefix));
+                span_err!(
+                    self.tcx.sess, span, E0385,
+                    "{} in an aliasable location", prefix);
             }
             mc::AliasableReason::UnaliasableImmutable => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("{} in an immutable container",
-                             prefix));
+                span_err!(
+                    self.tcx.sess, span, E0386,
+                    "{} in an immutable container", prefix);
             }
             mc::AliasableClosure(id) => {
-                self.tcx.sess.span_err(span,
-                                       &format!("{} in a captured outer \
-                                                variable in an `Fn` closure", prefix));
+                span_err!(
+                    self.tcx.sess, span, E0387,
+                    "{} in a captured outer variable in an `Fn` closure", prefix);
                 if let BorrowViolation(euv::ClosureCapture(_)) = kind {
                     // The aliasability violation with closure captures can
                     // happen for nested closures, so we know the enclosing
@@ -925,14 +921,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             }
             mc::AliasableStatic(..) |
             mc::AliasableStaticMut(..) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("{} in a static location", prefix));
+                span_err!(
+                    self.tcx.sess, span, E0388,
+                    "{} in a static location", prefix);
             }
             mc::AliasableBorrowed => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("{} in a `&` reference", prefix));
+                span_err!(
+                    self.tcx.sess, span, E0389,
+                    "{} in a `&` reference", prefix);
             }
         }
 
@@ -1006,20 +1002,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                     "reference must be valid for ",
                     sub_scope,
                     "...");
-                let suggestion = if is_statement_scope(self.tcx, super_scope) {
-                    Some("consider using a `let` binding to increase its lifetime")
-                } else {
-                    None
-                };
-                let span = note_and_explain_region(
+                note_and_explain_region(
                     self.tcx,
                     "...but borrowed value is only valid for ",
                     super_scope,
                     "");
-                match (span, suggestion) {
-                    (_, None) => {},
-                    (Some(span), Some(msg)) => self.tcx.sess.span_help(span, msg),
-                    (None, Some(msg)) => self.tcx.sess.help(msg),
+                if let Some(span) = statement_scope_span(self.tcx, super_scope) {
+                    self.tcx.sess.span_help(span,
+                        "consider using a `let` binding to increase its lifetime");
                 }
             }
 
@@ -1132,16 +1122,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
     }
 }
 
-fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool {
-     match region {
-         ty::ReScope(scope) => {
-             match tcx.map.find(scope.node_id()) {
-                 Some(ast_map::NodeStmt(_)) => true,
-                 _ => false
-             }
-         }
-         _ => false
-     }
+fn statement_scope_span(tcx: &ty::ctxt, region: ty::Region) -> Option<Span> {
+    match region {
+        ty::ReScope(scope) => {
+            match tcx.map.find(scope.node_id()) {
+                Some(ast_map::NodeStmt(stmt)) => Some(stmt.span),
+                _ => None
+            }
+        }
+        _ => None
+    }
 }
 
 impl BitwiseOperator for LoanDataFlowOperator {
@@ -1158,88 +1148,87 @@ impl DataFlowOperator for LoanDataFlowOperator {
     }
 }
 
-impl<'tcx> Repr<'tcx> for InteriorKind {
-    fn repr(&self, _tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for InteriorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            InteriorField(mc::NamedField(fld)) =>
-                format!("{}", token::get_name(fld)),
-            InteriorField(mc::PositionalField(i)) => format!("#{}", i),
-            InteriorElement(..) => "[]".to_string(),
+            InteriorField(mc::NamedField(fld)) => write!(f, "{}", fld),
+            InteriorField(mc::PositionalField(i)) => write!(f, "#{}", i),
+            InteriorElement(..) => write!(f, "[]"),
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for Loan<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Loan_{}({}, {:?}, {:?}-{:?}, {})",
-                 self.index,
-                 self.loan_path.repr(tcx),
-                 self.kind,
-                 self.gen_scope,
-                 self.kill_scope,
-                 self.restricted_paths.repr(tcx))
+impl<'tcx> fmt::Debug for Loan<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Loan_{}({:?}, {:?}, {:?}-{:?}, {:?})",
+               self.index,
+               self.loan_path,
+               self.kind,
+               self.gen_scope,
+               self.kill_scope,
+               self.restricted_paths)
     }
 }
 
-impl<'tcx> Repr<'tcx> for LoanPath<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Debug for LoanPath<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.kind {
             LpVar(id) => {
-                format!("$({})", tcx.map.node_to_string(id))
+                write!(f, "$({})", ty::tls::with(|tcx| tcx.map.node_to_string(id)))
             }
 
             LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => {
-                let s = tcx.map.node_to_string(var_id);
-                format!("$({} captured by id={})", s, closure_expr_id)
+                let s = ty::tls::with(|tcx| tcx.map.node_to_string(var_id));
+                write!(f, "$({} captured by id={})", s, closure_expr_id)
             }
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.krate == ast::LOCAL_CRATE {
-                    ty::item_path_str(tcx, variant_def_id)
+                    ty::tls::with(|tcx| ty::item_path_str(tcx, variant_def_id))
                 } else {
-                    variant_def_id.repr(tcx)
+                    format!("{:?}", variant_def_id)
                 };
-                format!("({}{}{})", lp.repr(tcx), DOWNCAST_PRINTED_OPERATOR, variant_str)
+                write!(f, "({:?}{}{})", lp, DOWNCAST_PRINTED_OPERATOR, variant_str)
             }
 
             LpExtend(ref lp, _, LpDeref(_)) => {
-                format!("{}.*", lp.repr(tcx))
+                write!(f, "{:?}.*", lp)
             }
 
             LpExtend(ref lp, _, LpInterior(ref interior)) => {
-                format!("{}.{}", lp.repr(tcx), interior.repr(tcx))
+                write!(f, "{:?}.{:?}", lp, interior)
             }
         }
     }
 }
 
-impl<'tcx> UserString<'tcx> for LoanPath<'tcx> {
-    fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String {
+impl<'tcx> fmt::Display for LoanPath<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.kind {
             LpVar(id) => {
-                format!("$({})", tcx.map.node_to_user_string(id))
+                write!(f, "$({})", ty::tls::with(|tcx| tcx.map.node_to_user_string(id)))
             }
 
             LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => {
-                let s = tcx.map.node_to_user_string(var_id);
-                format!("$({} captured by closure)", s)
+                let s = ty::tls::with(|tcx| tcx.map.node_to_user_string(var_id));
+                write!(f, "$({} captured by closure)", s)
             }
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.krate == ast::LOCAL_CRATE {
-                    ty::item_path_str(tcx, variant_def_id)
+                    ty::tls::with(|tcx| ty::item_path_str(tcx, variant_def_id))
                 } else {
-                    variant_def_id.repr(tcx)
+                    format!("{:?}", variant_def_id)
                 };
-                format!("({}{}{})", lp.user_string(tcx), DOWNCAST_PRINTED_OPERATOR, variant_str)
+                write!(f, "({}{}{})", lp, DOWNCAST_PRINTED_OPERATOR, variant_str)
             }
 
             LpExtend(ref lp, _, LpDeref(_)) => {
-                format!("{}.*", lp.user_string(tcx))
+                write!(f, "{}.*", lp)
             }
 
             LpExtend(ref lp, _, LpInterior(ref interior)) => {
-                format!("{}.{}", lp.user_string(tcx), interior.repr(tcx))
+                write!(f, "{}.{:?}", lp, interior)
             }
         }
     }
index 1180717140e6d467af01ae4e4e21999f5ce62db7..b38915612c5b0c453d83b30148a024e473acd553 100644 (file)
@@ -22,7 +22,7 @@ use rustc::middle::dataflow::KillFrom;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::ty;
 use rustc::util::nodemap::{FnvHashMap, NodeSet};
-use rustc::util::ppaux::Repr;
+
 use std::cell::RefCell;
 use std::rc::Rc;
 use std::usize;
@@ -313,8 +313,8 @@ impl<'tcx> MoveData<'tcx> {
             }
         };
 
-        debug!("move_path(lp={}, index={:?})",
-               lp.repr(tcx),
+        debug!("move_path(lp={:?}, index={:?})",
+               lp,
                index);
 
         assert_eq!(index.get(), self.paths.borrow().len() - 1);
@@ -364,8 +364,8 @@ impl<'tcx> MoveData<'tcx> {
                     lp: Rc<LoanPath<'tcx>>,
                     id: ast::NodeId,
                     kind: MoveKind) {
-        debug!("add_move(lp={}, id={}, kind={:?})",
-               lp.repr(tcx),
+        debug!("add_move(lp={:?}, id={}, kind={:?})",
+               lp,
                id,
                kind);
 
@@ -394,8 +394,8 @@ impl<'tcx> MoveData<'tcx> {
                           span: Span,
                           assignee_id: ast::NodeId,
                           mode: euv::MutateMode) {
-        debug!("add_assignment(lp={}, assign_id={}, assignee_id={}",
-               lp.repr(tcx), assign_id, assignee_id);
+        debug!("add_assignment(lp={:?}, assign_id={}, assignee_id={}",
+               lp, assign_id, assignee_id);
 
         let path_index = self.move_path(tcx, lp.clone());
 
@@ -415,13 +415,13 @@ impl<'tcx> MoveData<'tcx> {
         };
 
         if self.is_var_path(path_index) {
-            debug!("add_assignment[var](lp={}, assignment={}, path_index={:?})",
-                   lp.repr(tcx), self.var_assignments.borrow().len(), path_index);
+            debug!("add_assignment[var](lp={:?}, assignment={}, path_index={:?})",
+                   lp, self.var_assignments.borrow().len(), path_index);
 
             self.var_assignments.borrow_mut().push(assignment);
         } else {
-            debug!("add_assignment[path](lp={}, path_index={:?})",
-                   lp.repr(tcx), path_index);
+            debug!("add_assignment[path](lp={:?}, path_index={:?})",
+                   lp, path_index);
 
             self.path_assignments.borrow_mut().push(assignment);
         }
@@ -437,8 +437,8 @@ impl<'tcx> MoveData<'tcx> {
                              pattern_id: ast::NodeId,
                              base_lp: Rc<LoanPath<'tcx>>,
                              mode: euv::MatchMode) {
-        debug!("add_variant_match(lp={}, pattern_id={})",
-               lp.repr(tcx), pattern_id);
+        debug!("add_variant_match(lp={:?}, pattern_id={})",
+               lp, pattern_id);
 
         let path_index = self.move_path(tcx, lp.clone());
         let base_path_index = self.move_path(tcx, base_lp.clone());
@@ -478,14 +478,14 @@ impl<'tcx> MoveData<'tcx> {
                             KillFrom::Execution, dfcx_moves);
         }
 
-        for assignment in &*self.path_assignments.borrow() {
+        for assignment in self.path_assignments.borrow().iter() {
             self.kill_moves(assignment.path, assignment.id,
                             KillFrom::Execution, dfcx_moves);
         }
 
         // Kill all moves related to a variable `x` when
         // it goes out of scope:
-        for path in &*self.paths.borrow() {
+        for path in self.paths.borrow().iter() {
             match path.loan_path.kind {
                 LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
                     let kill_scope = path.loan_path.kill_scope(tcx);
index a43268ff1a8827c1cad97eef5a5f66c481467bb8..3e7cfe3ee7f88aaa8bacbaf24992108d36bdc108 100644 (file)
 
 #![allow(non_snake_case)]
 
+register_long_diagnostics! {
+
+E0381: r##"
+It is not allowed to use or capture an uninitialized variable. For example:
+
+```
+fn main() {
+    let x: i32;
+    let y = x; // error, use of possibly uninitialized variable
+```
+
+To fix this, ensure that any declared variables are initialized before being
+used.
+"##
+
+}
+
 register_diagnostics! {
-    E0373 // closure may outlive current fn, but it borrows {}, which is owned by current fn
+    E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
+    E0382, // use of partially/collaterally moved value
+    E0383, // partial reinitialization of uninitialized structure
+    E0384, // reassignment of immutable variable
+    E0385, // {} in an aliasable location
+    E0386, // {} in an immutable container
+    E0387, // {} in a captured outer variable in an `Fn` closure
+    E0388, // {} in a static location
+    E0389  // {} in a `&` reference
 }
index 50dc08e299a822701eaf28c5fc87b0d223b0861a..a8457d3bf94cdf93c3fa622bc927d634d16fb8eb 100644 (file)
@@ -16,7 +16,7 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![allow(non_camel_case_types)]
@@ -47,7 +47,4 @@ mod borrowck;
 
 pub mod graphviz;
 
-#[cfg(stage0)]
-__build_diagnostic_array! { DIAGNOSTICS }
-#[cfg(not(stage0))]
 __build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS }
index 17fd0b81536258d5c229c229c34533bc1789558e..d73043c043069fc9afd029c8547c485e119ec6ea 100644 (file)
@@ -358,9 +358,9 @@ pub struct DepthFirstTraversal<'g, N:'g, E:'g> {
 }
 
 impl<'g, N:Debug, E:Debug> Iterator for DepthFirstTraversal<'g, N, E> {
-    type Item = &'g N;
+    type Item = NodeIndex;
 
-    fn next(&mut self) -> Option<&'g N> {
+    fn next(&mut self) -> Option<NodeIndex> {
         while let Some(idx) = self.stack.pop() {
             if !self.visited.insert(idx.node_id()) {
                 continue;
@@ -372,7 +372,7 @@ impl<'g, N:Debug, E:Debug> Iterator for DepthFirstTraversal<'g, N, E> {
                 }
             }
 
-            return Some(self.graph.node_data(idx));
+            return Some(idx);
         }
 
         return None;
index 9c78c5aec00b44cae4399a300d1d31540a7a56c1..d3297562aef162cd495a68ab856ac20e0f40ba55 100644 (file)
@@ -11,6 +11,7 @@
 use rustc::session::Session;
 use rustc::session::config::{self, Input, OutputFilenames};
 use rustc::session::search_paths::PathKind;
+use rustc::ast_map;
 use rustc::lint;
 use rustc::metadata;
 use rustc::metadata::creader::CrateReader;
@@ -32,12 +33,11 @@ use super::Compilation;
 use serialize::json;
 
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsString, OsStr};
 use std::fs;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 use syntax::ast;
-use syntax::ast_map;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::diagnostics;
@@ -65,7 +65,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 (outputs, trans, sess) = {
+    let (sess, result) = {
         let (outputs, expanded_crate, id) = {
             let krate = phase_1_parse_input(&sess, cfg, input);
 
@@ -119,37 +119,52 @@ pub fn compile_input(sess: Session,
                                                                      &ast_map.krate(),
                                                                      &id[..]));
 
-        let analysis = phase_3_run_analysis_passes(sess,
-                                                   ast_map,
-                                                   &arenas,
-                                                   id,
-                                                   control.make_glob_map);
-
-        controller_entry_point!(after_analysis,
-                                analysis.ty_cx.sess,
-                                CompileState::state_after_analysis(input,
-                                                                   &analysis.ty_cx.sess,
-                                                                   outdir,
-                                                                   analysis.ty_cx.map.krate(),
-                                                                   &analysis,
-                                                                   &analysis.ty_cx));
-
-        if log_enabled!(::log::INFO) {
-            println!("Pre-trans");
-            analysis.ty_cx.print_debug_stats();
-        }
-        let (tcx, trans) = phase_4_translate_to_llvm(analysis);
+        phase_3_run_analysis_passes(sess,
+                                    ast_map,
+                                    &arenas,
+                                    id,
+                                    control.make_glob_map,
+                                    |tcx, analysis| {
+
+            {
+                let state = CompileState::state_after_analysis(input,
+                                                               &tcx.sess,
+                                                               outdir,
+                                                               tcx.map.krate(),
+                                                               &analysis,
+                                                               tcx);
+                (control.after_analysis.callback)(state);
+
+                tcx.sess.abort_if_errors();
+                if control.after_analysis.stop == Compilation::Stop {
+                    return Err(());
+                }
+            }
 
-        if log_enabled!(::log::INFO) {
-            println!("Post-trans");
-            tcx.print_debug_stats();
-        }
+            if log_enabled!(::log::INFO) {
+                println!("Pre-trans");
+                tcx.print_debug_stats();
+            }
+            let trans = phase_4_translate_to_llvm(tcx, analysis);
 
-        // Discard interned strings as they are no longer required.
-        token::get_ident_interner().clear();
+            if log_enabled!(::log::INFO) {
+                println!("Post-trans");
+                tcx.print_debug_stats();
+            }
+
+            // Discard interned strings as they are no longer required.
+            token::get_ident_interner().clear();
 
-        (outputs, trans, tcx.sess)
+            Ok((outputs, trans))
+        })
     };
+
+    let (outputs, trans) = if let Ok(out) = result {
+        out
+    } else {
+        return;
+    };
+
     phase_5_run_llvm_passes(&sess, &trans, &outputs);
 
     controller_entry_point!(after_llvm,
@@ -240,7 +255,7 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
     pub out_dir: Option<&'a Path>,
     pub expanded_crate: Option<&'a ast::Crate>,
     pub ast_map: Option<&'a ast_map::Map<'ast>>,
-    pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>,
+    pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<&'a ty::ctxt<'tcx>>,
     pub trans: Option<&'a trans::CrateTranslation>,
 }
@@ -309,7 +324,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
                             session: &'a Session,
                             out_dir: &'a Option<PathBuf>,
                             expanded_crate: &'a ast::Crate,
-                            analysis: &'a ty::CrateAnalysis<'tcx>,
+                            analysis: &'a ty::CrateAnalysis,
                             tcx: &'a ty::ctxt<'tcx>)
                             -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
@@ -444,7 +459,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     });
 
-    let Registry { syntax_exts, lint_passes, lint_groups, llvm_passes, .. } = registry;
+    let Registry { syntax_exts, lint_passes, lint_groups,
+                   llvm_passes, attributes, .. } = registry;
 
     {
         let mut ls = sess.lint_store.borrow_mut();
@@ -457,6 +473,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
+        *sess.plugin_attributes.borrow_mut() = attributes.clone();
     }
 
     // Lint plugins are registered; now we can process command line flags.
@@ -482,7 +499,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
                 let mut new_path = sess.host_filesearch(PathKind::All)
                                        .get_dylib_search_paths();
                 new_path.extend(env::split_paths(&_old_path));
-                env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
+                env::set_var("PATH", &env::join_paths(new_path).unwrap());
             }
             let features = sess.features.borrow();
             let cfg = syntax::ext::expand::ExpansionConfig {
@@ -511,7 +528,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         let features =
             syntax::feature_gate::check_crate(sess.codemap(),
                                               &sess.parse_sess.span_diagnostic,
-                                              &krate);
+                                              &krate, &attributes,
+                                              sess.opts.unstable_features);
         *sess.features.borrow_mut() = features;
         sess.abort_if_errors();
     });
@@ -541,7 +559,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         let features =
             syntax::feature_gate::check_crate(sess.codemap(),
                                               &sess.parse_sess.span_diagnostic,
-                                              &krate);
+                                              &krate, &attributes,
+                                              sess.opts.unstable_features);
         *sess.features.borrow_mut() = features;
         sess.abort_if_errors();
     });
@@ -576,12 +595,16 @@ pub fn assign_node_ids_and_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>(sess: Session,
-                                         ast_map: ast_map::Map<'tcx>,
-                                         arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                         name: String,
-                                         make_glob_map: resolve::MakeGlobMap)
-                                         -> ty::CrateAnalysis<'tcx> {
+pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
+                                               ast_map: ast_map::Map<'tcx>,
+                                               arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                               name: String,
+                                               make_glob_map: resolve::MakeGlobMap,
+                                               f: F)
+                                               -> (Session, R)
+                                               where F: FnOnce(&ty::ctxt<'tcx>,
+                                                               ty::CrateAnalysis) -> R
+{
     let time_passes = sess.time_passes();
     let krate = ast_map.krate();
 
@@ -600,11 +623,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
         glob_map,
     } =
         time(time_passes, "resolution", (),
-             |_| resolve::resolve_crate(&sess,
-                                        &ast_map,
-                                        &lang_items,
-                                        krate,
-                                        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();
@@ -629,102 +648,103 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     time(time_passes, "static item recursion checking", (), |_|
          middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
 
-    let ty_cx = ty::mk_ctxt(sess,
-                            arenas,
-                            def_map,
-                            named_region_map,
-                            ast_map,
-                            freevars,
-                            region_map,
-                            lang_items,
-                            stability::Index::new(krate));
-
-    // passes are timed inside typeck
-    typeck::check_crate(&ty_cx, trait_map);
-
-    time(time_passes, "const checking", (), |_|
-         middle::check_const::check_crate(&ty_cx));
-
-    let (exported_items, public_items) =
-            time(time_passes, "privacy checking", (), |_|
-                 rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
-
-    // Do not move this check past lint
-    time(time_passes, "stability index", (), |_|
-         ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items));
-
-    time(time_passes, "intrinsic checking", (), |_|
-         middle::intrinsicck::check_crate(&ty_cx));
-
-    time(time_passes, "effect checking", (), |_|
-         middle::effect::check_crate(&ty_cx));
-
-    time(time_passes, "match checking", (), |_|
-         middle::check_match::check_crate(&ty_cx));
-
-    time(time_passes, "liveness checking", (), |_|
-         middle::liveness::check_crate(&ty_cx));
-
-    time(time_passes, "borrow checking", (), |_|
-         borrowck::check_crate(&ty_cx));
-
-    time(time_passes, "rvalue checking", (), |_|
-         middle::check_rvalues::check_crate(&ty_cx, krate));
-
-    // Avoid overwhelming user with errors if type checking failed.
-    // I'm not sure how helpful this is, to be honest, but it avoids a
-    // lot of annoying errors in the compile-fail tests (basically,
-    // lint warnings and so on -- kindck used to do this abort, but
-    // kindck is gone now). -nmatsakis
-    ty_cx.sess.abort_if_errors();
-
-    let reachable_map =
-        time(time_passes, "reachability checking", (), |_|
-             reachable::find_reachable(&ty_cx, &exported_items));
-
-    time(time_passes, "death checking", (), |_| {
-        middle::dead::check_crate(&ty_cx,
-                                  &exported_items,
-                                  &reachable_map)
-    });
-
-    let ref lib_features_used =
-        time(time_passes, "stability checking", (), |_|
-             stability::check_unstable_api_usage(&ty_cx));
-
-    time(time_passes, "unused lib feature checking", (), |_|
-         stability::check_unused_or_stable_features(
-             &ty_cx.sess, lib_features_used));
-
-    time(time_passes, "lint checking", (), |_|
-         lint::check_crate(&ty_cx, &exported_items));
-
-    // The above three passes generate errors w/o aborting
-    ty_cx.sess.abort_if_errors();
-
-    ty::CrateAnalysis {
-        export_map: export_map,
-        ty_cx: ty_cx,
-        exported_items: exported_items,
-        public_items: public_items,
-        reachable: reachable_map,
-        name: name,
-        glob_map: glob_map,
-    }
+    ty::with_ctxt(sess,
+                  arenas,
+                  def_map,
+                  named_region_map,
+                  ast_map,
+                  freevars,
+                  region_map,
+                  lang_items,
+                  stability::Index::new(krate),
+                  |tcx| {
+
+        // passes are timed inside typeck
+        typeck::check_crate(tcx, trait_map);
+
+        time(time_passes, "const checking", (), |_|
+            middle::check_const::check_crate(tcx));
+
+        let (exported_items, public_items) =
+                time(time_passes, "privacy checking", (), |_|
+                    rustc_privacy::check_crate(tcx, &export_map, external_exports));
+
+        // Do not move this check past lint
+        time(time_passes, "stability index", (), |_|
+            tcx.stability.borrow_mut().build(tcx, krate, &public_items));
+
+        time(time_passes, "intrinsic checking", (), |_|
+            middle::intrinsicck::check_crate(tcx));
+
+        time(time_passes, "effect checking", (), |_|
+            middle::effect::check_crate(tcx));
+
+        time(time_passes, "match checking", (), |_|
+            middle::check_match::check_crate(tcx));
+
+        time(time_passes, "liveness checking", (), |_|
+            middle::liveness::check_crate(tcx));
+
+        time(time_passes, "borrow checking", (), |_|
+            borrowck::check_crate(tcx));
+
+        time(time_passes, "rvalue checking", (), |_|
+            middle::check_rvalues::check_crate(tcx, krate));
+
+        // Avoid overwhelming user with errors if type checking failed.
+        // I'm not sure how helpful this is, to be honest, but it avoids a
+        // lot of annoying errors in the compile-fail tests (basically,
+        // lint warnings and so on -- kindck used to do this abort, but
+        // kindck is gone now). -nmatsakis
+        tcx.sess.abort_if_errors();
+
+        let reachable_map =
+            time(time_passes, "reachability checking", (), |_|
+                reachable::find_reachable(tcx, &exported_items));
+
+        time(time_passes, "death checking", (), |_| {
+            middle::dead::check_crate(tcx,
+                                      &exported_items,
+                                      &reachable_map)
+        });
+
+        let ref lib_features_used =
+            time(time_passes, "stability checking", (), |_|
+                stability::check_unstable_api_usage(tcx));
+
+        time(time_passes, "unused lib feature checking", (), |_|
+            stability::check_unused_or_stable_features(
+                &tcx.sess, lib_features_used));
+
+        time(time_passes, "lint checking", (), |_|
+            lint::check_crate(tcx, &exported_items));
+
+        // The above three passes generate errors w/o aborting
+        tcx.sess.abort_if_errors();
+
+        f(tcx, ty::CrateAnalysis {
+            export_map: export_map,
+            exported_items: exported_items,
+            public_items: public_items,
+            reachable: reachable_map,
+            name: name,
+            glob_map: glob_map,
+        })
+    })
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
-                                       -> (ty::ctxt<'tcx>, trans::CrateTranslation) {
-    let time_passes = analysis.ty_cx.sess.time_passes();
+pub fn phase_4_translate_to_llvm(tcx: &ty::ctxt, analysis: ty::CrateAnalysis)
+                                 -> trans::CrateTranslation {
+    let time_passes = tcx.sess.time_passes();
 
     time(time_passes, "resolving dependency formats", (), |_|
-         dependency_format::calculate(&analysis.ty_cx));
+         dependency_format::calculate(tcx));
 
     // Option dance to work around the lack of stack once closures.
     time(time_passes, "translation", analysis, |analysis|
-         trans::trans_crate(analysis))
+         trans::trans_crate(tcx, analysis))
 }
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
@@ -760,18 +780,11 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
 pub fn phase_6_link_output(sess: &Session,
                            trans: &trans::CrateTranslation,
                            outputs: &OutputFilenames) {
-    let old_path = env::var_os("PATH").unwrap_or(OsString::new());
-    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
-    new_path.extend(env::split_paths(&old_path));
-    env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
-
     time(sess.time_passes(), "linking", (), |_|
          link::link_binary(sess,
                            trans,
                            outputs,
                            &trans.link.crate_name));
-
-    env::set_var("PATH", &old_path);
 }
 
 fn escape_dep_filename(filename: &str) -> String {
@@ -790,7 +803,7 @@ fn write_out_deps(sess: &Session,
         let file = outputs.path(*output_type);
         match *output_type {
             config::OutputTypeExe => {
-                for output in &*sess.crate_types.borrow() {
+                for output in sess.crate_types.borrow().iter() {
                     let p = link::filename_for_input(sess, *output,
                                                      id, &file);
                     out_filenames.push(p);
@@ -893,7 +906,7 @@ pub fn collect_crate_types(session: &Session,
     // will be found in crate attributes.
     let mut base = session.opts.crate_types.clone();
     if base.is_empty() {
-        base.extend(attr_types.into_iter());
+        base.extend(attr_types);
         if base.is_empty() {
             base.push(link::default_output_for_target(session));
         }
@@ -964,7 +977,7 @@ pub fn build_output_filenames(input: &Input,
 
             OutputFilenames {
                 out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(),
-                out_filestem: out_file.file_stem().unwrap()
+                out_filestem: out_file.file_stem().unwrap_or(OsStr::new(""))
                                       .to_str().unwrap().to_string(),
                 single_output_file: ofile,
                 extra: sess.opts.cg.extra_filename.clone(),
index 1bdfa532beb3d6bd204d007b746c4fdf3121ef04..96d1ab23ad5239983e9701171be469b9c331a7cd 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(collections)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(staged_api)]
-#![feature(exit_status)]
 #![feature(set_stdio)]
+#![feature(staged_api)]
+#![feature(vec_push_all)]
 
 extern crate arena;
 extern crate flate;
@@ -73,6 +72,7 @@ use std::env;
 use std::io::{self, Read, Write};
 use std::iter::repeat;
 use std::path::PathBuf;
+use std::process;
 use std::str;
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -377,12 +377,10 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
         if sess.opts.debugging_opts.save_analysis {
             control.after_analysis.callback = box |state| {
                 time(state.session.time_passes(),
-                     "save analysis",
-                     state.expanded_crate.unwrap(),
-                     |krate| save::process_crate(state.session,
-                                                 krate,
-                                                 state.analysis.unwrap(),
-                                                 state.out_dir));
+                     "save analysis", (),
+                     |_| save::process_crate(state.tcx.unwrap(),
+                                             state.analysis.unwrap(),
+                                             state.out_dir));
             };
             control.make_glob_map = resolve::MakeGlobMap::Yes;
         }
@@ -402,7 +400,7 @@ impl RustcDefaultCalls {
                 &Input::File(ref ifile) => {
                     let path = &(*ifile);
                     let mut v = Vec::new();
-                    metadata::loader::list_file_metadata(sess.target.target.options.is_like_osx,
+                    metadata::loader::list_file_metadata(&sess.target.target,
                                                          path,
                                                          &mut v).unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
@@ -566,7 +564,7 @@ Available lint options:
     let plugin_groups = sort_lint_groups(plugin_groups);
     let builtin_groups = sort_lint_groups(builtin_groups);
 
-    let max_name_len = plugin.iter().chain(builtin.iter())
+    let max_name_len = plugin.iter().chain(&builtin)
         .map(|&s| s.name.chars().count())
         .max().unwrap_or(0);
     let padded = |x: &str| {
@@ -593,7 +591,7 @@ Available lint options:
 
 
 
-    let max_name_len = plugin_groups.iter().chain(builtin_groups.iter())
+    let max_name_len = plugin_groups.iter().chain(&builtin_groups)
         .map(|&(s, _)| s.chars().count())
         .max().unwrap_or(0);
     let padded = |x: &str| {
@@ -826,11 +824,14 @@ pub fn monitor<F:FnOnce()+Send+'static>(f: F) {
                     "the compiler unexpectedly panicked. this is a bug.".to_string(),
                     format!("we would appreciate a bug report: {}",
                             BUG_REPORT_URL),
-                    "run with `RUST_BACKTRACE=1` for a backtrace".to_string(),
                 ];
                 for note in &xs {
                     emitter.emit(None, &note[..], None, diagnostic::Note)
                 }
+                if let None = env::var_os("RUST_BACKTRACE") {
+                    emitter.emit(None, "run with `RUST_BACKTRACE=1` for a backtrace",
+                                 None, diagnostic::Note);
+                }
 
                 println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap());
             }
@@ -858,5 +859,5 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry {
 
 pub fn main() {
     let result = run(env::args().collect());
-    std::env::set_exit_status(result as i32);
+    process::exit(result as i32);
 }
index b8032bda8d070ede99791322e5f2ba00c49abc14..a40cb94204d9c82b34fb14eff8b409adf69d4bac 100644 (file)
@@ -19,18 +19,17 @@ use rustc_trans::back::link;
 
 use driver;
 
+use rustc::ast_map::{self, blocks, NodePrinter};
 use rustc::middle::ty;
 use rustc::middle::cfg;
 use rustc::middle::cfg::graphviz::LabelledCFG;
 use rustc::session::Session;
 use rustc::session::config::Input;
-use rustc::util::ppaux;
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
 use rustc_resolve as resolve;
 
 use syntax::ast;
-use syntax::ast_map::{self, blocks, NodePrinter};
 use syntax::codemap;
 use syntax::fold::{self, Folder};
 use syntax::print::{pp, pprust};
@@ -148,13 +147,15 @@ impl PpSourceMode {
             }
             PpmTyped => {
                 let ast_map = ast_map.expect("--pretty=typed missing ast_map");
-                let analysis = driver::phase_3_run_analysis_passes(sess,
-                                                                   ast_map,
-                                                                   arenas,
-                                                                   id,
-                                                                   resolve::MakeGlobMap::No);
-                let annotation = TypedAnnotation { analysis: analysis };
-                f(&annotation, payload)
+                driver::phase_3_run_analysis_passes(sess,
+                                                    ast_map,
+                                                    arenas,
+                                                    id,
+                                                    resolve::MakeGlobMap::No,
+                                                    |tcx, _| {
+                    let annotation = TypedAnnotation { tcx: tcx };
+                    f(&annotation, payload)
+                }).1
             }
         }
     }
@@ -284,21 +285,21 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
 }
 
 
-struct TypedAnnotation<'tcx> {
-    analysis: ty::CrateAnalysis<'tcx>,
+struct TypedAnnotation<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
 }
 
-impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.analysis.ty_cx.sess }
+impl<'b, 'tcx> PrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
+    fn sess<'a>(&'a self) -> &'a Session { &self.tcx.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> {
-        Some(&self.analysis.ty_cx.map)
+        Some(&self.tcx.map)
     }
 
     fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
-impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> {
+impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> {
     fn pre(&self,
            s: &mut pprust::State,
            node: pprust::AnnNode) -> io::Result<()> {
@@ -310,16 +311,13 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> {
     fn post(&self,
             s: &mut pprust::State,
             node: pprust::AnnNode) -> io::Result<()> {
-        let tcx = &self.analysis.ty_cx;
         match node {
             pprust::NodeExpr(expr) => {
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s, "as"));
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s,
-                              &ppaux::ty_to_string(
-                                  tcx,
-                                  ty::expr_ty(tcx, expr))));
+                              &ty::expr_ty(self.tcx, expr).to_string()));
                 s.pclose()
             }
             _ => Ok(())
@@ -646,12 +644,14 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    let analysis = driver::phase_3_run_analysis_passes(sess,
-                                                                       ast_map,
-                                                                       &arenas,
-                                                                       id,
-                                                                       resolve::MakeGlobMap::No);
-                    print_flowgraph(variants, analysis, code, mode, out)
+                    driver::phase_3_run_analysis_passes(sess,
+                                                        ast_map,
+                                                        &arenas,
+                                                        id,
+                                                        resolve::MakeGlobMap::No,
+                                                        |tcx, _| {
+                        print_flowgraph(variants, tcx, code, mode, out)
+                    }).1
                 }
                 None => {
                     let message = format!("--pretty=flowgraph needs \
@@ -682,18 +682,17 @@ pub fn pretty_print_input(sess: Session,
 }
 
 fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
-                             analysis: ty::CrateAnalysis,
+                             tcx: &ty::ctxt,
                              code: blocks::Code,
                              mode: PpFlowGraphMode,
                              mut out: W) -> io::Result<()> {
-    let ty_cx = &analysis.ty_cx;
     let cfg = match code {
-        blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block),
-        blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()),
+        blocks::BlockCode(block) => cfg::CFG::new(tcx, &*block),
+        blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &*fn_like.body()),
     };
     let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
     let lcfg = LabelledCFG {
-        ast_map: &ty_cx.map,
+        ast_map: &tcx.map,
         cfg: &cfg,
         name: format!("node_{}", code.id()),
         labelled_edges: labelled_edges,
@@ -705,14 +704,14 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
             return expand_err_details(r);
         }
         blocks::BlockCode(_) => {
-            ty_cx.sess.err("--pretty flowgraph with -Z flowgraph-print \
-                            annotations requires fn-like node id.");
+            tcx.sess.err("--pretty flowgraph with -Z flowgraph-print \
+                          annotations requires fn-like node id.");
             return Ok(())
         }
         blocks::FnLikeCode(fn_like) => {
             let fn_parts = borrowck::FnPartsWithCFG::from_fn_like(&fn_like, &cfg);
             let (bccx, analysis_data) =
-                borrowck::build_borrowck_dataflow_data_for_fn(ty_cx, fn_parts);
+                borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_parts);
 
             let lcfg = borrowck_dot::DataflowLabeller {
                 inner: lcfg,
index a8cf75331799646679480a8a4499ff7b5cceb21a..62c8e0368d906f6f9b4d4c92591e79511daf1135 100644 (file)
@@ -28,13 +28,14 @@ use rustc_typeck::middle::infer;
 use rustc_typeck::middle::infer::lub::Lub;
 use rustc_typeck::middle::infer::glb::Glb;
 use rustc_typeck::middle::infer::sub::Sub;
-use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString};
+use rustc::ast_map;
 use rustc::session::{self,config};
-use syntax::{abi, ast, ast_map};
+use syntax::{abi, ast};
 use syntax::codemap;
 use syntax::codemap::{Span, CodeMap, DUMMY_SP};
 use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help};
 use syntax::parse::token;
+use syntax::feature_gate::UnstableFeatures;
 
 struct Env<'a, 'tcx: 'a> {
     infcx: &'a infer::InferCtxt<'a, 'tcx>,
@@ -102,12 +103,13 @@ fn test_env<F>(source_string: &str,
     let mut options =
         config::basic_options();
     options.debugging_opts.verbose = true;
+    options.unstable_features = UnstableFeatures::Allow;
     let codemap =
         CodeMap::new();
     let diagnostic_handler =
-        diagnostic::mk_handler(true, emitter);
+        diagnostic::Handler::with_emitter(true, emitter);
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, codemap);
+        diagnostic::SpanHandler::new(diagnostic_handler, codemap);
 
     let sess = session::build_session_(options, None, span_diagnostic_handler);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -125,23 +127,25 @@ fn test_env<F>(source_string: &str,
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(krate, &sess);
     let resolve::CrateMap { def_map, freevars, .. } =
-        resolve::resolve_crate(&sess, &ast_map, &lang_items, krate, resolve::MakeGlobMap::No);
+        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);
-    let tcx = ty::mk_ctxt(sess,
-                          &arenas,
-                          def_map,
-                          named_region_map,
-                          ast_map,
-                          freevars,
-                          region_map,
-                          lang_items,
-                          stability::Index::new(krate));
-    let infcx = infer::new_infer_ctxt(&tcx);
-    body(Env { infcx: &infcx });
-    let free_regions = FreeRegionMap::new();
-    infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
-    assert_eq!(tcx.sess.err_count(), expected_err_count);
+    ty::with_ctxt(sess,
+                  &arenas,
+                  def_map,
+                  named_region_map,
+                  ast_map,
+                  freevars,
+                  region_map,
+                  lang_items,
+                  stability::Index::new(krate),
+                  |tcx| {
+        let infcx = infer::new_infer_ctxt(tcx);
+        body(Env { infcx: &infcx });
+        let free_regions = FreeRegionMap::new();
+        infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
+        assert_eq!(tcx.sess.err_count(), expected_err_count);
+    });
 }
 
 impl<'a, 'tcx> Env<'a, 'tcx> {
@@ -185,7 +189,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                       -> Option<ast::NodeId> {
             assert!(idx < names.len());
             for item in &m.items {
-                if item.ident.user_string(this.infcx.tcx) == names[idx] {
+                if item.ident.to_string() == names[idx] {
                     return search(this, &**item, idx+1, names);
                 }
             }
@@ -224,8 +228,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     pub fn make_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         match infer::mk_subty(self.infcx, true, infer::Misc(DUMMY_SP), a, b) {
             Ok(_) => true,
-            Err(ref e) => panic!("Encountered error: {}",
-                                ty::type_err_to_str(self.infcx.tcx, e))
+            Err(ref e) => panic!("Encountered error: {}", e)
         }
     }
 
@@ -238,9 +241,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
 
     pub fn assert_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) {
         if !self.is_subtype(a, b) {
-            panic!("{} is not a subtype of {}, but it should be",
-                  self.ty_to_string(a),
-                  self.ty_to_string(b));
+            panic!("{} is not a subtype of {}, but it should be", a, b);
         }
     }
 
@@ -249,10 +250,6 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         self.assert_subtype(b, a);
     }
 
-    pub fn ty_to_string(&self, a: Ty<'tcx>) -> String {
-        ty_to_string(self.infcx.tcx, a)
-    }
-
     pub fn t_fn(&self,
                 input_tys: &[Ty<'tcx>],
                 output_ty: Ty<'tcx>)
@@ -373,8 +370,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> {
         match self.lub().relate(&t1, &t2) {
             Ok(t) => t,
-            Err(ref e) => panic!("unexpected error computing LUB: {}",
-                                ty::type_err_to_str(self.infcx.tcx, e))
+            Err(ref e) => panic!("unexpected error computing LUB: {}", e)
         }
     }
 
@@ -384,10 +380,10 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         match self.sub().relate(&t1, &t2) {
             Ok(_) => { }
             Err(ref e) => {
-                panic!("unexpected error computing sub({},{}): {}",
-                       t1.repr(self.infcx.tcx),
-                       t2.repr(self.infcx.tcx),
-                       ty::type_err_to_str(self.infcx.tcx, e));
+                panic!("unexpected error computing sub({:?},{:?}): {}",
+                       t1,
+                       t2,
+                       e);
             }
         }
     }
@@ -398,9 +394,9 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         match self.sub().relate(&t1, &t2) {
             Err(_) => { }
             Ok(_) => {
-                panic!("unexpected success computing sub({},{})",
-                       t1.repr(self.infcx.tcx),
-                       t2.repr(self.infcx.tcx));
+                panic!("unexpected success computing sub({:?},{:?})",
+                       t1,
+                       t2);
             }
         }
     }
@@ -412,18 +408,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                 self.assert_eq(t, t_lub);
             }
             Err(ref e) => {
-                panic!("unexpected error in LUB: {}",
-                      ty::type_err_to_str(self.infcx.tcx, e))
+                panic!("unexpected error in LUB: {}", e)
             }
         }
     }
 
     /// Checks that `GLB(t1,t2) == t_glb`
     pub fn check_glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_glb: Ty<'tcx>) {
-        debug!("check_glb(t1={}, t2={}, t_glb={})",
-               self.ty_to_string(t1),
-               self.ty_to_string(t2),
-               self.ty_to_string(t_glb));
+        debug!("check_glb(t1={}, t2={}, t_glb={})", t1, t2, t_glb);
         match self.glb().relate(&t1, &t2) {
             Err(e) => {
                 panic!("unexpected error computing LUB: {:?}", e)
@@ -655,8 +647,8 @@ fn glb_bound_free_infer() {
         // `&'_ isize`
         let t_resolve1 = env.infcx.shallow_resolve(t_infer1);
         match t_resolve1.sty {
-            ty::ty_rptr(..) => { }
-            _ => { panic!("t_resolve1={}", t_resolve1.repr(env.infcx.tcx)); }
+            ty::TyRef(..) => { }
+            _ => { panic!("t_resolve1={:?}", t_resolve1); }
         }
     })
 }
@@ -698,11 +690,11 @@ fn subst_ty_renumber_bound() {
             env.t_fn(&[t_ptr_bound2], env.t_nil())
         };
 
-        debug!("subst_bound: t_source={} substs={} t_substituted={} t_expected={}",
-               t_source.repr(env.infcx.tcx),
-               substs.repr(env.infcx.tcx),
-               t_substituted.repr(env.infcx.tcx),
-               t_expected.repr(env.infcx.tcx));
+        debug!("subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
+               t_source,
+               substs,
+               t_substituted,
+               t_expected);
 
         assert_eq!(t_substituted, t_expected);
     })
@@ -735,11 +727,11 @@ fn subst_ty_renumber_some_bounds() {
             env.t_pair(t_rptr_bound1, env.t_fn(&[t_rptr_bound2], env.t_nil()))
         };
 
-        debug!("subst_bound: t_source={} substs={} t_substituted={} t_expected={}",
-               t_source.repr(env.infcx.tcx),
-               substs.repr(env.infcx.tcx),
-               t_substituted.repr(env.infcx.tcx),
-               t_expected.repr(env.infcx.tcx));
+        debug!("subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
+               t_source,
+               substs,
+               t_substituted,
+               t_expected);
 
         assert_eq!(t_substituted, t_expected);
     })
@@ -796,11 +788,11 @@ fn subst_region_renumber_region() {
             env.t_fn(&[t_rptr_bound2], env.t_nil())
         };
 
-        debug!("subst_bound: t_source={} substs={} t_substituted={} t_expected={}",
-               t_source.repr(env.infcx.tcx),
-               substs.repr(env.infcx.tcx),
-               t_substituted.repr(env.infcx.tcx),
-               t_expected.repr(env.infcx.tcx));
+        debug!("subst_bound: t_source={:?} substs={:?} t_substituted={:?} t_expected={:?}",
+               t_source,
+               substs,
+               t_substituted,
+               t_expected);
 
         assert_eq!(t_substituted, t_expected);
     })
index 8d555240e707b31751facd1d4c5f8fbca1e010eb..ffb860283dd7e01b85aa511561889138c06eef2e 100644 (file)
@@ -33,9 +33,9 @@ use middle::def::*;
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use middle::{def, pat_util, stability};
-use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
+use middle::const_eval::{eval_const_expr_partial, ConstVal};
 use middle::cfg;
-use util::ppaux::ty_to_string;
+use rustc::ast_map;
 use util::nodemap::{FnvHashMap, NodeSet};
 use lint::{Level, Context, LintPass, LintArray, Lint};
 
@@ -44,7 +44,7 @@ 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, ast_map};
+use syntax::{abi, ast};
 use syntax::ast_util::{self, is_shift_binop, local_def};
 use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::{self, Span};
@@ -144,7 +144,7 @@ impl LintPass for TypeLimits {
                     _ => {
                         let t = ty::expr_ty(cx.tcx, &**expr);
                         match t.sty {
-                            ty::ty_uint(_) => {
+                            ty::TyUint(_) => {
                                 cx.span_lint(UNSIGNED_NEGATION, e.span,
                                              "negation of unsigned int variable may \
                                              be unintentional");
@@ -169,8 +169,8 @@ impl LintPass for TypeLimits {
 
                 if is_shift_binop(binop.node) {
                     let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
-                        ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
-                        ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
+                        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
                     };
 
@@ -180,8 +180,8 @@ impl LintPass for TypeLimits {
                             else { false }
                         } else {
                             match eval_const_expr_partial(cx.tcx, &**r, Some(cx.tcx.types.usize)) {
-                                Ok(const_int(shift)) => { shift as u64 >= bits },
-                                Ok(const_uint(shift)) => { shift >= bits },
+                                Ok(ConstVal::Int(shift)) => { shift as u64 >= bits },
+                                Ok(ConstVal::Uint(shift)) => { shift >= bits },
                                 _ => { false }
                             }
                         };
@@ -194,7 +194,7 @@ impl LintPass for TypeLimits {
             },
             ast::ExprLit(ref lit) => {
                 match ty::expr_ty(cx.tcx, e).sty {
-                    ty::ty_int(t) => {
+                    ty::TyInt(t) => {
                         match lit.node {
                             ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
                             ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
@@ -203,11 +203,13 @@ impl LintPass for TypeLimits {
                                 } else {
                                     t
                                 };
-                                let (min, max) = int_ty_range(int_type);
+                                let (_, max) = int_ty_range(int_type);
                                 let negative = self.negated_expr_id == e.id;
 
-                                if (negative && v > (min.abs() as u64)) ||
-                                   (!negative && v > (max.abs() as u64)) {
+                                // 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;
@@ -216,7 +218,7 @@ impl LintPass for TypeLimits {
                             _ => panic!()
                         };
                     },
-                    ty::ty_uint(t) => {
+                    ty::TyUint(t) => {
                         let uint_type = if let ast::TyUs = t {
                             cx.sess().target.uint_type
                         } else {
@@ -233,7 +235,7 @@ impl LintPass for TypeLimits {
                                          &*format!("literal out of range for {:?}", t));
                         }
                     },
-                    ty::ty_float(t) => {
+                    ty::TyFloat(t) => {
                         let (min, max) = float_ty_range(t);
                         let lit_val: f64 = match lit.node {
                             ast::LitFloat(ref v, _) |
@@ -342,7 +344,7 @@ impl LintPass for TypeLimits {
                 binop
             };
             match ty::expr_ty(tcx, expr).sty {
-                ty::ty_int(int_ty) => {
+                ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i64 = match lit.node {
                         ast::ExprLit(ref li) => match li.node {
@@ -356,7 +358,7 @@ impl LintPass for TypeLimits {
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
-                ty::ty_uint(uint_ty) => {
+                ty::TyUint(uint_ty) => {
                     let (min, max): (u64, u64) = uint_ty_range(uint_ty);
                     let lit_val: u64 = match lit.node {
                         ast::ExprLit(ref li) => match li.node {
@@ -483,7 +485,7 @@ impl BoxPointers {
         let mut n_uniq: usize = 0;
         ty::fold_ty(cx.tcx, ty, |t| {
             match t.sty {
-                ty::ty_uniq(_) => {
+                ty::TyBox(_) => {
                     n_uniq += 1;
                 }
                 _ => ()
@@ -492,8 +494,7 @@ impl BoxPointers {
         });
 
         if n_uniq > 0 {
-            let s = ty_to_string(cx.tcx, ty);
-            let m = format!("type uses owned (Box type) pointers: {}", s);
+            let m = format!("type uses owned (Box type) pointers: {}", ty);
             cx.span_lint(BOX_POINTERS, span, &m[..]);
         }
     }
@@ -588,8 +589,8 @@ impl LintPass for RawPointerDerive {
                 }
 
                 match ty::node_id_to_type(cx.tcx, item.id).sty {
-                    ty::ty_enum(did, _) => did,
-                    ty::ty_struct(did, _) => did,
+                    ty::TyEnum(did, _) => did,
+                    ty::TyStruct(did, _) => did,
                     _ => return,
                 }
             }
@@ -641,9 +642,26 @@ impl LintPass for UnusedAttributes {
             }
         }
 
+        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");
-            if KNOWN_ATTRIBUTES.contains(&(&attr.name(), AttributeType::CrateLevel)) {
+            // Is it a builtin attribute that must be used at the crate level?
+            let known_crate = KNOWN_ATTRIBUTES.contains(&(&attr.name(),
+                                                          AttributeType::CrateLevel));
+            // 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::AttrOuter => "crate-level attribute should be an inner \
                                        attribute: add an exclamation mark: #![foo]",
@@ -716,10 +734,10 @@ impl LintPass for UnusedResults {
 
         let t = ty::expr_ty(cx.tcx, expr);
         let warned = match t.sty {
-            ty::ty_tup(ref tys) if tys.is_empty() => return,
-            ty::ty_bool => return,
-            ty::ty_struct(did, _) |
-            ty::ty_enum(did, _) => {
+            ty::TyTuple(ref tys) if tys.is_empty() => return,
+            ty::TyBool => return,
+            ty::TyStruct(did, _) |
+            ty::TyEnum(did, _) => {
                 if ast_util::is_local(did) {
                     if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
                         check_must_use(cx, &it.attrs, s.span)
@@ -840,7 +858,7 @@ impl LintPass for NonCamelCaseTypes {
     }
 
     fn check_generics(&mut self, cx: &Context, it: &ast::Generics) {
-        for gen in &*it.ty_params {
+        for gen in it.ty_params.iter() {
             self.check_case(cx, "type parameter", gen.ident, gen.span);
         }
     }
@@ -977,7 +995,7 @@ impl LintPass for NonSnakeCase {
                 },
                 _ => (),
             },
-            visit::FkItemFn(ident, _, _, _, _) => {
+            visit::FkItemFn(ident, _, _, _, _, _) => {
                 self.check_snake_case(cx, "function", &token::get_ident(ident), Some(span))
             },
             _ => (),
@@ -1324,7 +1342,7 @@ impl LintPass for UnsafeCode {
     fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
                 _: &ast::Block, span: Span, _: ast::NodeId) {
         match fk {
-            visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _, _) =>
+            visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _, _, _) =>
                 cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
 
             visit::FkMethod(_, sig, _) => {
@@ -1779,20 +1797,21 @@ declare_lint! {
 pub struct Stability;
 
 impl Stability {
-    fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
+    fn lint(&self, cx: &Context, _id: ast::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 { deprecated_since: Some(_), .. }) =>
                 (DEPRECATED, "deprecated"),
             _ => return
         };
 
         output(cx, span, stability, lint, label);
 
-        fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
+        fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>,
                   lint: &'static Lint, label: &'static str) {
             let msg = match *stability {
-                Some(attr::Stability { reason: Some(ref s), .. }) => {
+                Some(&attr::Stability { reason: Some(ref s), .. }) => {
                     format!("use of {} item: {}", label, *s)
                 }
                 _ => format!("use of {} item", label)
@@ -1853,7 +1872,7 @@ impl LintPass for UnconditionalRecursion {
                               ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
 
         let (name, checker) = match fn_kind {
-            visit::FkItemFn(name, _, _, _, _) => (name, id_refers_to_this_fn as F),
+            visit::FkItemFn(name, _, _, _, _, _) => (name, id_refers_to_this_fn as F),
             visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
             // closures can't recur, so they don't matter.
             visit::FkFnBlock => return
@@ -2141,7 +2160,7 @@ impl LintPass for MutableTransmutes {
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\
                    consider instead using an UnsafeCell";
         match get_transmute_from_to(cx, expr) {
-            Some((&ty::ty_rptr(_, from_mt), &ty::ty_rptr(_, to_mt))) => {
+            Some((&ty::TyRef(_, from_mt), &ty::TyRef(_, to_mt))) => {
                 if to_mt.mutbl == ast::Mutability::MutMutable
                     && from_mt.mutbl == ast::Mutability::MutImmutable {
                     cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
@@ -2151,7 +2170,7 @@ impl LintPass for MutableTransmutes {
         }
 
         fn get_transmute_from_to<'a, 'tcx>(cx: &Context<'a, 'tcx>, expr: &ast::Expr)
-            -> Option<(&'tcx ty::sty<'tcx>, &'tcx ty::sty<'tcx>)> {
+            -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
             match expr.node {
                 ast::ExprPath(..) => (),
                 _ => return None
@@ -2162,7 +2181,7 @@ impl LintPass for MutableTransmutes {
                 }
                 let typ = ty::node_id_to_type(cx.tcx, expr.id);
                 match typ.sty {
-                    ty::ty_bare_fn(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
+                    ty::TyBareFn(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
                         if let ty::FnConverging(to) = bare_fn.sig.0.output {
                             let from = bare_fn.sig.0.inputs[0];
                             return Some((&from.sty, &to.sty));
@@ -2176,7 +2195,7 @@ impl LintPass for MutableTransmutes {
 
         fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool {
             match ty::lookup_item_type(cx.tcx, def_id).ty.sty {
-                ty::ty_bare_fn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
+                ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
                 _ => return false
             }
             ty::with_path(cx.tcx, def_id, |path| match path.last() {
@@ -2194,7 +2213,7 @@ pub struct UnstableFeatures;
 declare_lint! {
     UNSTABLE_FEATURES,
     Allow,
-    "enabling unstable features"
+    "enabling unstable features (deprecated. do not use)"
 }
 
 impl LintPass for UnstableFeatures {
@@ -2203,7 +2222,11 @@ impl LintPass for UnstableFeatures {
     }
     fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
         if attr::contains_name(&[attr.node.value.clone()], "feature") {
-            ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
+            if let Some(items) = attr.node.value.meta_item_list() {
+                for item in items {
+                    ctx.span_lint(UNSTABLE_FEATURES, item.span, "unstable feature");
+                }
+            }
         }
     }
 }
@@ -2235,9 +2258,9 @@ impl LintPass for DropWithReprExtern {
                 };
 
             match dtor_self_type.sty {
-                ty::ty_enum(self_type_did, _) |
-                ty::ty_struct(self_type_did, _) |
-                ty::ty_closure(self_type_did, _) => {
+                ty::TyEnum(self_type_did, _) |
+                ty::TyStruct(self_type_did, _) |
+                ty::TyClosure(self_type_did, _) => {
                     let hints = ty::lookup_repr_hints(ctx.tcx, self_type_did);
                     if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
                         ty::ty_dtor(ctx.tcx, self_type_did).has_drop_flag() {
index df834c36e5b225262d13ccd18d3b941cb7f336a0..c680906dd135bc741703dd7f4a7392cf03864417 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![cfg_attr(test, feature(test))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(core)]
+#![feature(num_bits_bytes)]
 #![feature(quote)]
+#![feature(ref_slice)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_char)]
-#![cfg_attr(test, feature(test))]
 
 extern crate syntax;
 #[macro_use]
index 2a2aa2bf4cf93dcfc530e7e0504a4703ef050a4a..c4960c8d6a3998ac1c59ee4804bfbc10c1dae3a4 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(associated_consts)]
 #![feature(box_syntax)]
-#![feature(collections)]
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(staged_api)]
+#![feature(vec_push_all)]
 
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
@@ -55,6 +55,7 @@ pub use self::CallConv::*;
 pub use self::Visibility::*;
 pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
+pub use self::DLLStorageClassTypes::*;
 
 use std::ffi::CString;
 use std::cell::RefCell;
@@ -123,6 +124,15 @@ pub enum DiagnosticSeverity {
     Note,
 }
 
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub enum DLLStorageClassTypes {
+    DefaultStorageClass = 0,
+    DLLImportStorageClass = 1,
+    DLLExportStorageClass = 2,
+}
+
 bitflags! {
     flags Attribute : u32 {
         const ZExt            = 1 << 0,
@@ -468,9 +478,6 @@ pub type BuilderRef = *mut Builder_opaque;
 pub enum ExecutionEngine_opaque {}
 pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
 #[allow(missing_copy_implementations)]
-pub enum RustJITMemoryManager_opaque {}
-pub type RustJITMemoryManagerRef = *mut RustJITMemoryManager_opaque;
-#[allow(missing_copy_implementations)]
 pub enum MemoryBuffer_opaque {}
 pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
 #[allow(missing_copy_implementations)]
@@ -969,6 +976,9 @@ extern {
     pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
     pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
     pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
+    pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
+                                          Name: *const c_char,
+                                          Value: *const c_char);
     pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
     pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
     pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
@@ -1080,10 +1090,7 @@ extern {
     pub fn LLVMDisposeBuilder(Builder: BuilderRef);
 
     /* Execution engine */
-    pub fn LLVMRustCreateJITMemoryManager(morestack: *const ())
-                                          -> RustJITMemoryManagerRef;
-    pub fn LLVMBuildExecutionEngine(Mod: ModuleRef,
-                                    MM: RustJITMemoryManagerRef) -> ExecutionEngineRef;
+    pub fn LLVMBuildExecutionEngine(Mod: ModuleRef) -> ExecutionEngineRef;
     pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
     pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef);
     pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool;
@@ -1293,20 +1300,8 @@ extern {
                         -> ValueRef;
 
     /* Memory */
-    pub fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
-                           -> ValueRef;
-    pub fn LLVMBuildArrayMalloc(B: BuilderRef,
-                                Ty: TypeRef,
-                                Val: ValueRef,
-                                Name: *const c_char)
-                                -> ValueRef;
     pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
                            -> ValueRef;
-    pub fn LLVMBuildArrayAlloca(B: BuilderRef,
-                                Ty: TypeRef,
-                                Val: ValueRef,
-                                Name: *const c_char)
-                                -> ValueRef;
     pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
     pub fn LLVMBuildLoad(B: BuilderRef,
                          PointerVal: ValueRef,
@@ -1761,7 +1756,9 @@ extern {
                          Dialect: c_uint)
                          -> ValueRef;
 
-    pub static LLVMRustDebugMetadataVersion: u32;
+    pub fn LLVMRustDebugMetadataVersion() -> u32;
+    pub fn LLVMVersionMajor() -> u32;
+    pub fn LLVMVersionMinor() -> u32;
 
     pub fn LLVMRustAddModuleFlag(M: ModuleRef,
                                  name: *const c_char,
@@ -1914,6 +1911,7 @@ extern {
                                            VarInfo: DIVariable,
                                            AddrOps: *const i64,
                                            AddrOpsCount: c_uint,
+                                           DL: ValueRef,
                                            InsertAtEnd: BasicBlockRef)
                                            -> ValueRef;
 
@@ -1922,6 +1920,7 @@ extern {
                                             VarInfo: DIVariable,
                                             AddrOps: *const i64,
                                             AddrOpsCount: c_uint,
+                                            DL: ValueRef,
                                             InsertBefore: ValueRef)
                                             -> ValueRef;
 
@@ -2029,7 +2028,6 @@ extern {
                                        Level: CodeGenOptLevel,
                                        EnableSegstk: bool,
                                        UseSoftFP: bool,
-                                       NoFramePointerElim: bool,
                                        PositionIndependentExecutable: bool,
                                        FunctionSections: bool,
                                        DataSections: bool) -> TargetMachineRef;
@@ -2040,6 +2038,11 @@ extern {
     pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
                                          M: ModuleRef,
                                          DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
+                                               OptLevel: CodeGenOptLevel,
+                                               MergeFunctions: bool,
+                                               SLPVectorize: bool,
+                                               LoopVectorize: bool);
     pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
                                   DisableSimplifyLibCalls: bool);
     pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
@@ -2075,7 +2078,8 @@ extern {
     pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
     pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
 
-    pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
+    pub fn LLVMRustSetDLLStorageClass(V: ValueRef,
+                                      C: DLLStorageClassTypes);
 
     pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
                                   data: *mut *const c_char) -> c_int;
@@ -2109,6 +2113,12 @@ extern {
     pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
 }
 
+// LLVM requires symbols from this library, but apparently they're not printed
+// during llvm-config?
+#[cfg(windows)]
+#[link(name = "ole32")]
+extern {}
+
 pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
     unsafe {
         LLVMSetInstructionCallConv(instr, cc as c_uint);
@@ -2125,6 +2135,12 @@ pub fn SetLinkage(global: ValueRef, link: Linkage) {
     }
 }
 
+pub fn SetDLLStorageClass(global: ValueRef, class: DLLStorageClassTypes) {
+    unsafe {
+        LLVMRustSetDLLStorageClass(global, class);
+    }
+}
+
 pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
     unsafe {
         LLVMSetUnnamedAddr(global, unnamed as Bool);
@@ -2236,6 +2252,18 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
     }
 }
 
+pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
+    unsafe {
+        let num_params = LLVMCountParams(llfn);
+        let mut params = Vec::with_capacity(num_params as usize);
+        for idx in 0..num_params {
+            params.push(LLVMGetParam(llfn, idx));
+        }
+
+        params
+    }
+}
+
 #[allow(missing_copy_implementations)]
 pub enum RustString_opaque {}
 pub type RustStringRef = *mut RustString_opaque;
index 9a8bbc5ea0bc0c99426fb953e95c2d6730de7327..cae93baaf74be2392a75bae5990834711f22a893 100644 (file)
@@ -16,7 +16,7 @@
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(rustc_diagnostic_macros)]
@@ -33,6 +33,7 @@ use self::FieldName::*;
 
 use std::mem::replace;
 
+use rustc::ast_map;
 use rustc::metadata::csearch;
 use rustc::middle::def;
 use rustc::middle::privacy::ImportUse::*;
@@ -46,7 +47,7 @@ use rustc::middle::ty::MethodTraitObject;
 use rustc::middle::ty::{self, Ty};
 use rustc::util::nodemap::{NodeMap, NodeSet};
 
-use syntax::{ast, ast_map};
+use syntax::ast;
 use syntax::ast_util::{is_local, local_def};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -710,10 +711,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
 
         let struct_type = ty::lookup_item_type(self.tcx, id).ty;
         let struct_desc = match struct_type.sty {
-            ty::ty_struct(_, _) =>
+            ty::TyStruct(_, _) =>
                 format!("struct `{}`", ty::item_path_str(self.tcx, id)),
             // struct variant fields have inherited visibility
-            ty::ty_enum(..) => return,
+            ty::TyEnum(..) => return,
             _ => self.tcx.sess.span_bug(span, "can't find struct for field")
         };
         let msg = match name {
@@ -892,12 +893,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
         match expr.node {
             ast::ExprField(ref base, ident) => {
-                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                if let ty::TyStruct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
                     self.check_field(expr.span, id, NamedField(ident.node.name));
                 }
             }
             ast::ExprTupField(ref base, idx) => {
-                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                if let ty::TyStruct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
                     self.check_field(expr.span, id, UnnamedField(idx.node));
                 }
             }
@@ -917,7 +918,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
             }
             ast::ExprStruct(_, ref fields, _) => {
                 match ty::expr_ty(self.tcx, expr).sty {
-                    ty::ty_struct(ctor_id, _) => {
+                    ty::TyStruct(ctor_id, _) => {
                         // RFC 736: ensure all unmentioned fields are visible.
                         // Rather than computing the set of unmentioned fields
                         // (i.e. `all_fields - fields`), just check them all.
@@ -927,7 +928,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                                              NamedField(field.name));
                         }
                     }
-                    ty::ty_enum(_, _) => {
+                    ty::TyEnum(_, _) => {
                         match self.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
                             def::DefVariant(_, variant_id, _) => {
                                 for field in fields {
@@ -994,13 +995,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         match pattern.node {
             ast::PatStruct(_, ref fields, _) => {
                 match ty::pat_ty(self.tcx, pattern).sty {
-                    ty::ty_struct(id, _) => {
+                    ty::TyStruct(id, _) => {
                         for field in fields {
                             self.check_field(pattern.span, id,
                                              NamedField(field.node.ident.name));
                         }
                     }
-                    ty::ty_enum(_, _) => {
+                    ty::TyEnum(_, _) => {
                         match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
                             Some(def::DefVariant(_, variant_id, _)) => {
                                 for field in fields {
@@ -1025,7 +1026,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
             // elsewhere).
             ast::PatEnum(_, Some(ref fields)) => {
                 match ty::pat_ty(self.tcx, pattern).sty {
-                    ty::ty_struct(id, _) => {
+                    ty::TyStruct(id, _) => {
                         for (i, field) in fields.iter().enumerate() {
                             if let ast::PatWild(..) = field.node {
                                 continue
@@ -1033,7 +1034,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                             self.check_field(field.span, id, UnnamedField(i));
                         }
                     }
-                    ty::ty_enum(..) => {
+                    ty::TyEnum(..) => {
                         // enum fields have no privacy at this time
                     }
                     _ => {}
@@ -1300,7 +1301,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     return
                 }
 
-                for bound in &**bounds {
+                for bound in bounds.iter() {
                     self.check_ty_param_bound(bound)
                 }
             }
@@ -1465,15 +1466,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
     }
 
     fn visit_generics(&mut self, generics: &ast::Generics) {
-        for ty_param in &*generics.ty_params {
-            for bound in &*ty_param.bounds {
+        for ty_param in generics.ty_params.iter() {
+            for bound in ty_param.bounds.iter() {
                 self.check_ty_param_bound(bound)
             }
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
                 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                    for bound in &*bound_pred.bounds {
+                    for bound in bound_pred.bounds.iter() {
                         self.check_ty_param_bound(bound)
                     }
                 }
index 4ea18968d43ac218df9fbc3dda33aee3c716ad1e..30d5a4f111ba43e9b41bdd3636c52e947ae7714d 100644 (file)
@@ -425,7 +425,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                     .define_value(DefConst(local_def(item.id)), sp, modifiers);
                 parent.clone()
             }
-            ItemFn(_, _, _, _, _) => {
+            ItemFn(_, _, _, _, _, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
 
                 let def = DefFn(local_def(item.id), false);
index 38ab0a8c5ed0d1740163f3400ac9a2673f81d513..5d10b0d9a57b80b31990b6221e44f1cc87370e54 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
-#![feature(alloc)]
 #![feature(associated_consts)]
-#![feature(collections)]
+#![feature(rc_weak)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
+#![feature(slice_extras)]
 #![feature(staged_api)]
 
 #[macro_use] extern crate log;
@@ -49,12 +49,12 @@ use self::ParentLink::*;
 use self::ModuleKind::*;
 use self::FallbackChecks::*;
 
+use rustc::ast_map;
 use rustc::session::Session;
 use rustc::lint;
 use rustc::metadata::csearch;
 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
-use rustc::middle::lang_items::LanguageItems;
 use rustc::middle::pat_util::pat_bindings;
 use rustc::middle::privacy::*;
 use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
@@ -80,7 +80,6 @@ use syntax::ast::{TyPath, TyPtr};
 use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
 use syntax::ast::TypeImplItem;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util::{local_def, walk_pat};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
@@ -215,7 +214,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         // `visit::walk_variant` without the discriminant expression.
         match variant.node.kind {
             ast::TupleVariantKind(ref variant_arguments) => {
-                for variant_argument in variant_arguments.iter() {
+                for variant_argument in variant_arguments {
                     self.visit_ty(&*variant_argument.ty);
                 }
             }
@@ -245,7 +244,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
                 _: Span,
                 node_id: NodeId) {
         let rib_kind = match function_kind {
-            visit::FkItemFn(_, generics, _, _, _) => {
+            visit::FkItemFn(_, generics, _, _, _, _) => {
                 self.visit_generics(generics);
                 ItemRibKind
             }
@@ -1574,7 +1573,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // Descend into children and anonymous children.
         build_reduced_graph::populate_module_if_necessary(self, &module_);
 
-        for (_, child_node) in &*module_.children.borrow() {
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Continue.
@@ -1585,7 +1584,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
-        for (_, module_) in &*module_.anonymous_children.borrow() {
+        for (_, module_) in module_.anonymous_children.borrow().iter() {
             self.report_unresolved_imports(module_.clone());
         }
     }
@@ -1809,7 +1808,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                                ItemRibKind),
                                              |this| visit::walk_item(this, item));
             }
-            ItemFn(_, _, _, ref generics, _) => {
+            ItemFn(_, _, _, _, ref generics, _) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                FnSpace,
                                                                ItemRibKind),
@@ -2039,7 +2038,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn resolve_generics(&mut self, generics: &Generics) {
-        for type_parameter in &*generics.ty_params {
+        for type_parameter in generics.ty_params.iter() {
             self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
         }
         for predicate in &generics.where_clause.predicates {
@@ -2361,8 +2360,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             "type name"
                         };
 
-                        let msg = format!("use of undeclared {} `{}`", kind,
-                                          path_names_to_string(path, 0));
+                        let self_type_name = special_idents::type_self.name;
+                        let is_invalid_self_type_name =
+                            path.segments.len() > 0 &&
+                            maybe_qself.is_none() &&
+                            path.segments[0].identifier.name == self_type_name;
+                        let msg = if is_invalid_self_type_name {
+                            "use of `Self` outside of an impl or trait".to_string()
+                        } else {
+                            format!("use of undeclared {} `{}`",
+                                kind, path_names_to_string(path, 0))
+                        };
+
                         self.resolve_error(ty.span, &msg[..]);
                     }
                 }
@@ -3196,14 +3205,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         NoSuggestion
     }
 
-    fn find_best_match_for_name(&mut self, name: &str, max_distance: usize)
-                                -> Option<String> {
-        let this = &mut *self;
-
+    fn find_best_match_for_name(&mut self, name: &str) -> Option<String> {
         let mut maybes: Vec<token::InternedString> = Vec::new();
         let mut values: Vec<usize> = Vec::new();
 
-        for rib in this.value_ribs.iter().rev() {
+        for rib in self.value_ribs.iter().rev() {
             for (&k, _) in &rib.bindings {
                 maybes.push(token::get_name(k));
                 values.push(usize::MAX);
@@ -3219,9 +3225,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
+        // As a loose rule to avoid obviously incorrect suggestions, clamp the
+        // maximum edit distance we will accept for a suggestion to one third of
+        // the typo'd name's length.
+        let max_distance = std::cmp::max(name.len(), 3) / 3;
+
         if !values.is_empty() &&
-            values[smallest] != usize::MAX &&
-            values[smallest] < name.len() + 2 &&
             values[smallest] <= max_distance &&
             name != &maybes[smallest][..] {
 
@@ -3347,7 +3356,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     NoSuggestion => {
                                         // limit search to 5 to reduce the number
                                         // of stupid suggestions
-                                        self.find_best_match_for_name(&path_name, 5)
+                                        self.find_best_match_for_name(&path_name)
                                                             .map_or("".to_string(),
                                                                     |x| format!("`{}`", x))
                                     }
@@ -3492,7 +3501,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             build_reduced_graph::populate_module_if_necessary(self, &search_module);
 
             {
-                for (_, child_names) in &*search_module.children.borrow() {
+                for (_, child_names) in search_module.children.borrow().iter() {
                     let def = match child_names.def_for_namespace(TypeNS) {
                         Some(def) => def,
                         None => continue
@@ -3508,7 +3517,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             // Look for imports.
-            for (_, import) in &*search_module.import_resolutions.borrow() {
+            for (_, import) in search_module.import_resolutions.borrow().iter() {
                 let target = match import.target_for_namespace(TypeNS) {
                     None => continue,
                     Some(target) => target,
@@ -3581,13 +3590,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         debug!("Children:");
         build_reduced_graph::populate_module_if_necessary(self, &module_);
-        for (&name, _) in &*module_.children.borrow() {
+        for (&name, _) in module_.children.borrow().iter() {
             debug!("* {}", token::get_name(name));
         }
 
         debug!("Import resolutions:");
         let import_resolutions = module_.import_resolutions.borrow();
-        for (&name, import_resolution) in &*import_resolutions {
+        for (&name, import_resolution) in import_resolutions.iter() {
             let value_repr;
             match import_resolution.target_for_namespace(ValueNS) {
                 None => { value_repr = "".to_string(); }
@@ -3679,10 +3688,9 @@ pub enum MakeGlobMap {
 /// Entry point to crate resolution.
 pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
                                ast_map: &'a ast_map::Map<'tcx>,
-                               _: &LanguageItems,
-                               krate: &Crate,
                                make_glob_map: MakeGlobMap)
                                -> CrateMap {
+    let krate = ast_map.krate();
     let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map);
 
     build_reduced_graph::build_reduced_graph(&mut resolver, krate);
@@ -3713,7 +3721,4 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     }
 }
 
-#[cfg(stage0)]
-__build_diagnostic_array! { DIAGNOSTICS }
-#[cfg(not(stage0))]
 __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
index e953b6398f9c08e6eab61bfc34e807b28c92e740..3a566a9672f9ab8c9e72f802cded96a57625843c 100644 (file)
@@ -81,7 +81,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
         self.record_exports_for_module(&*module_);
         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
 
-        for (_, child_name_bindings) in &*module_.children.borrow() {
+        for (_, child_name_bindings) in module_.children.borrow().iter() {
             match child_name_bindings.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -92,7 +92,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
             }
         }
 
-        for (_, child_module) in &*module_.anonymous_children.borrow() {
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
             self.record_exports_for_module_subtree(child_module.clone());
         }
     }
@@ -134,7 +134,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
     fn add_exports_for_module(&mut self,
                               exports: &mut Vec<Export>,
                               module_: &Module) {
-        for (name, import_resolution) in &*module_.import_resolutions.borrow() {
+        for (name, import_resolution) in module_.import_resolutions.borrow().iter() {
             if !import_resolution.is_public {
                 continue
             }
index 9870b41e7fa631783312f98fbcec69e31b5d5b4b..e77e7116b9fea41c86b254c78fa228a3ee35e174 100644 (file)
@@ -12,6 +12,7 @@ use self::ImportDirectiveSubclass::*;
 
 use DefModifiers;
 use Module;
+use ModuleKind;
 use Namespace::{self, TypeNS, ValueNS};
 use NameBindings;
 use NamespaceResult::{BoundResult, UnboundResult, UnknownResult};
@@ -234,7 +235,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         self.resolver.current_module = orig_module;
 
         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
-        for (_, child_node) in &*module_.children.borrow() {
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -245,7 +246,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             }
         }
 
-        for (_, child_module) in &*module_.anonymous_children.borrow() {
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
             self.resolve_imports_for_module_subtree(child_module.clone());
         }
     }
@@ -732,7 +733,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
         // Add all resolved imports from the containing module.
         let import_resolutions = target_module.import_resolutions.borrow();
-        for (ident, target_import_resolution) in &*import_resolutions {
+        for (ident, target_import_resolution) in import_resolutions.iter() {
             debug!("(resolving glob import) writing module resolution \
                     {} into `{}`",
                    token::get_name(*ident),
@@ -793,7 +794,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         // Add all children from the containing module.
         build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module);
 
-        for (&name, name_bindings) in &*target_module.children.borrow() {
+        for (&name, name_bindings) in target_module.children.borrow().iter() {
             self.merge_import_resolution(module_,
                                          target_module.clone(),
                                          import_directive,
@@ -803,7 +804,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         }
 
         // Add external module children from the containing module.
-        for (&name, module) in &*target_module.external_module_children.borrow() {
+        for (&name, module) in target_module.external_module_children.borrow().iter() {
             let name_bindings =
                 Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
             self.merge_import_resolution(module_,
@@ -899,7 +900,19 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         match target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 let ns_word = match namespace {
-                    TypeNS => "type",
+                    TypeNS => {
+                        if let Some(ref ty_def) = *target.bindings.type_def.borrow() {
+                            match ty_def.module_def {
+                                Some(ref module)
+                                    if module.kind.get() == ModuleKind::NormalModuleKind =>
+                                        "module",
+                                Some(ref module)
+                                    if module.kind.get() == ModuleKind::TraitModuleKind =>
+                                        "trait",
+                                _ => "type",
+                            }
+                        } else { "type" }
+                    },
                     ValueNS => "value",
                 };
                 span_err!(self.resolver.session, import_span, E0252,
@@ -980,10 +993,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         match import_resolution.type_target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref ty) = *name_bindings.type_def.borrow() {
-                    let (what, note) = if ty.module_def.is_some() {
-                        ("existing submodule", "note conflicting module here")
-                    } else {
-                        ("type in this module", "note conflicting type here")
+                    let (what, note) = match ty.module_def {
+                        Some(ref module)
+                            if module.kind.get() == ModuleKind::NormalModuleKind =>
+                                ("existing submodule", "note conflicting module here"),
+                        Some(ref module)
+                            if module.kind.get() == ModuleKind::TraitModuleKind =>
+                                ("trait in this module", "note conflicting trait here"),
+                        _    => ("type in this module", "note conflicting type here"),
                     };
                     span_err!(self.resolver.session, import_span, E0256,
                               "import `{}` conflicts with {}",
index 38ad909dd012e41eca1c583080256cbbb6cabe2a..6b8b59de3c253b9a1a2124a0711ba044b9b40ce7 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use super::archive::{Archive, ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
-use super::archive;
-use super::rpath;
+use super::linker::{Linker, GnuLinker, MsvcLinker};
 use super::rpath::RPathConfig;
+use super::rpath;
 use super::svh::Svh;
 use session::config;
 use session::config::NoDebugInfo;
@@ -21,14 +21,15 @@ use session::Session;
 use metadata::common::LinkMeta;
 use metadata::{encoder, cstore, filesearch, csearch, creader};
 use metadata::filesearch::FileDoesntMatch;
-use trans::{CrateContext, CrateTranslation, gensym_name};
 use middle::ty::{self, Ty};
+use rustc::ast_map::{PathElem, PathElems, PathName};
+use trans::{CrateContext, CrateTranslation, gensym_name};
 use util::common::time;
-use util::ppaux;
 use util::sha2::{Digest, Sha256};
 use util::fs::fix_windows_verbatim_for_gcc;
 use rustc_back::tempdir::TempDir;
 
+use std::env;
 use std::ffi::OsString;
 use std::fs::{self, PathExt};
 use std::io::{self, Read, Write};
@@ -39,7 +40,6 @@ use std::str;
 use flate;
 use serialize::hex::ToHex;
 use syntax::ast;
-use syntax::ast_map::{PathElem, PathElems, PathName};
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -205,13 +205,13 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>,
     symbol_hasher.input_str(&link_meta.crate_name);
     symbol_hasher.input_str("-");
     symbol_hasher.input_str(link_meta.crate_hash.as_str());
-    for meta in &*tcx.sess.crate_metadata.borrow() {
+    for meta in tcx.sess.crate_metadata.borrow().iter() {
         symbol_hasher.input_str(&meta[..]);
     }
     symbol_hasher.input_str("-");
     symbol_hasher.input_str(&encoder::encoded_ty(tcx, t));
     // Prefix with 'h' so that it never blends into adjacent digits
-    let mut hash = String::from_str("h");
+    let mut hash = String::from("h");
     hash.push_str(&truncated_hash_result(symbol_hasher));
     hash
 }
@@ -280,7 +280,7 @@ pub fn sanitize(s: &str) -> String {
 }
 
 pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
-                                      hash: Option<&str>) -> String {
+                                           hash: Option<&str>) -> String {
     // Follow C++ namespace-mangling style, see
     // http://en.wikipedia.org/wiki/Name_mangling for more info.
     //
@@ -295,7 +295,7 @@ pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
     // To be able to work on all platforms and get *some* reasonable output, we
     // use C++ name-mangling.
 
-    let mut n = String::from_str("_ZN"); // _Z == Begin name-sequence, N == nested
+    let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested
 
     fn push(n: &mut String, s: &str) {
         let sani = sanitize(s);
@@ -348,15 +348,14 @@ 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 s = ppaux::ty_to_string(ccx.tcx(), t);
-    let path = [PathName(token::intern(&s[..])),
+    let path = [PathName(token::intern(&t.to_string())),
                 gensym_name(name)];
     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)).into_iter()), None)
+    mangle(path.chain(Some(gensym_name(flav))), None)
 }
 
 pub fn get_cc_prog(sess: &Session) -> String {
@@ -366,6 +365,23 @@ pub fn get_cc_prog(sess: &Session) -> String {
     }
 }
 
+pub fn get_ar_prog(sess: &Session) -> String {
+    sess.opts.cg.ar.clone().unwrap_or_else(|| {
+        sess.target.target.options.ar.clone()
+    })
+}
+
+fn command_path(sess: &Session) -> OsString {
+    // The compiler's sysroot often has some bundled tools, so add it to the
+    // PATH for the child.
+    let mut new_path = sess.host_filesearch(PathKind::All)
+                           .get_tools_search_paths();
+    if let Some(path) = env::var_os("PATH") {
+        new_path.extend(env::split_paths(&path));
+    }
+    env::join_paths(new_path).unwrap()
+}
+
 pub fn remove(sess: &Session, path: &Path) {
     match fs::remove_file(path) {
         Ok(..) => {}
@@ -384,7 +400,7 @@ pub fn link_binary(sess: &Session,
                    outputs: &OutputFilenames,
                    crate_name: &str) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
-    for &crate_type in &*sess.crate_types.borrow() {
+    for &crate_type in sess.crate_types.borrow().iter() {
         if invalid_output_for_target(sess, crate_type) {
             sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
                              crate_type, sess.opts.target_triple));
@@ -541,6 +557,7 @@ fn link_rlib<'a>(sess: &'a Session,
                  trans: Option<&CrateTranslation>, // None == no metadata/bytecode
                  obj_filename: &Path,
                  out_filename: &Path) -> ArchiveBuilder<'a> {
+    info!("preparing rlib from {:?} to {:?}", obj_filename, out_filename);
     let handler = &sess.diagnostic().handler;
     let config = ArchiveConfig {
         handler: handler,
@@ -548,16 +565,15 @@ fn link_rlib<'a>(sess: &'a Session,
         lib_search_paths: archive_search_paths(sess),
         slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
         slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
-        maybe_ar_prog: sess.opts.cg.ar.clone()
+        ar_prog: get_ar_prog(sess),
+        command_path: command_path(sess),
     };
     let mut ab = ArchiveBuilder::create(config);
     ab.add_file(obj_filename).unwrap();
 
-    for &(ref l, kind) in &*sess.cstore.get_used_libraries().borrow() {
+    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).unwrap(),
             cstore::NativeFramework | cstore::NativeUnknown => {}
         }
     }
@@ -608,10 +624,8 @@ fn link_rlib<'a>(sess: &'a Session,
             }) {
                 Ok(..) => {}
                 Err(e) => {
-                    sess.err(&format!("failed to write {}: {}",
-                                     metadata.display(),
-                                     e));
-                    sess.abort_if_errors();
+                    sess.fatal(&format!("failed to write {}: {}",
+                                        metadata.display(), e));
                 }
             }
             ab.add_file(&metadata).unwrap();
@@ -653,9 +667,8 @@ fn link_rlib<'a>(sess: &'a Session,
                                                     &bc_data_deflated) {
                     Ok(()) => {}
                     Err(e) => {
-                        sess.err(&format!("failed to write compressed bytecode: \
-                                          {}", e));
-                        sess.abort_if_errors()
+                        sess.fatal(&format!("failed to write compressed \
+                                             bytecode: {}", e));
                     }
                 };
 
@@ -760,7 +773,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
         ab.add_rlib(&p, &name[..], sess.lto()).unwrap();
 
         let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
-        all_native_libs.extend(native_libs.into_iter());
+        all_native_libs.extend(native_libs);
     }
 
     ab.update_symbols();
@@ -789,11 +802,14 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
 // links to all upstream files as well.
 fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
                  obj_filename: &Path, out_filename: &Path) {
+    info!("preparing dylib? ({}) from {:?} to {:?}", dylib, obj_filename,
+          out_filename);
     let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
 
     // The invocations of cc share some flags across platforms
     let pname = get_cc_prog(sess);
-    let mut cmd = Command::new(&pname[..]);
+    let mut cmd = Command::new(&pname);
+    cmd.env("PATH", command_path(sess));
 
     let root = sess.target_filesearch(PathKind::Native).get_lib_path();
     cmd.args(&sess.target.target.options.pre_link_args);
@@ -801,10 +817,17 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
         cmd.arg(root.join(obj));
     }
 
-    link_args(&mut cmd, sess, dylib, tmpdir.path(),
-              trans, obj_filename, out_filename);
-    if !sess.target.target.options.no_compiler_rt {
-        cmd.arg("-lcompiler-rt");
+    {
+        let mut linker = if sess.target.target.options.is_like_msvc {
+            Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
+        } else {
+            Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
+        };
+        link_args(&mut *linker, sess, dylib, tmpdir.path(),
+                  trans, obj_filename, out_filename);
+        if !sess.target.target.options.no_compiler_rt {
+            linker.link_staticlib("compiler-rt");
+        }
     }
     for obj in &sess.target.target.options.post_link_objects {
         cmd.arg(root.join(obj));
@@ -819,7 +842,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
     sess.abort_if_errors();
 
     // Invoke the system linker
-    debug!("{:?}", &cmd);
+    info!("{:?}", &cmd);
     let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output());
     match prog {
         Ok(prog) => {
@@ -833,14 +856,11 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
                 sess.note(str::from_utf8(&output[..]).unwrap());
                 sess.abort_if_errors();
             }
-            debug!("linker stderr:\n{}", String::from_utf8(prog.stderr).unwrap());
-            debug!("linker stdout:\n{}", String::from_utf8(prog.stdout).unwrap());
+            info!("linker stderr:\n{}", String::from_utf8(prog.stderr).unwrap());
+            info!("linker stdout:\n{}", String::from_utf8(prog.stdout).unwrap());
         },
         Err(e) => {
-            sess.err(&format!("could not exec the linker `{}`: {}",
-                             pname,
-                             e));
-            sess.abort_if_errors();
+            sess.fatal(&format!("could not exec the linker `{}`: {}", pname, e));
         }
     }
 
@@ -850,15 +870,12 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
     if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo {
         match Command::new("dsymutil").arg(out_filename).output() {
             Ok(..) => {}
-            Err(e) => {
-                sess.err(&format!("failed to run dsymutil: {}", e));
-                sess.abort_if_errors();
-            }
+            Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)),
         }
     }
 }
 
-fn link_args(cmd: &mut Command,
+fn link_args(cmd: &mut Linker,
              sess: &Session,
              dylib: bool,
              tmpdir: &Path,
@@ -873,10 +890,9 @@ fn link_args(cmd: &mut Command,
     // target descriptor
     let t = &sess.target.target;
 
-    cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(&lib_path));
-
-    cmd.arg("-o").arg(out_filename).arg(obj_filename);
-
+    cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
+    cmd.add_object(obj_filename);
+    cmd.output_filename(out_filename);
 
     // Stack growth requires statically linking a __morestack function. Note
     // that this is listed *before* all other libraries. Due to the usage of the
@@ -895,89 +911,44 @@ fn link_args(cmd: &mut Command,
     // will include the __morestack symbol 100% of the time, always resolving
     // references to it even if the object above didn't use it.
     if t.options.morestack {
-        if t.options.is_like_osx {
-            let morestack = lib_path.join("libmorestack.a");
-
-            let mut v = OsString::from("-Wl,-force_load,");
-            v.push(&morestack);
-            cmd.arg(&v);
-        } else {
-            cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]);
-        }
+        cmd.link_whole_staticlib("morestack", &[lib_path]);
     }
 
     // When linking a dynamic library, we put the metadata into a section of the
     // executable. This metadata is in a separate object file from the main
     // object file, so we link that in here.
     if dylib {
-        cmd.arg(&obj_filename.with_extension("metadata.o"));
+        cmd.add_object(&obj_filename.with_extension("metadata.o"));
     }
 
-    if t.options.is_like_osx {
-        // The dead_strip option to the linker specifies that functions and data
-        // unreachable by the entry point will be removed. This is quite useful
-        // with Rust's compilation model of compiling libraries at a time into
-        // one object file. For example, this brings hello world from 1.7MB to
-        // 458K.
-        //
-        // Note that this is done for both executables and dynamic libraries. We
-        // won't get much benefit from dylibs because LLVM will have already
-        // stripped away as much as it could. This has not been seen to impact
-        // link times negatively.
-        //
-        // -dead_strip can't be part of the pre_link_args because it's also used
-        // for partial linking when using multiple codegen units (-r). So we
-        // insert it here.
-        cmd.arg("-Wl,-dead_strip");
-    }
-
-    // If we're building a dylib, we don't use --gc-sections because LLVM has
-    // already done the best it can do, and we also don't want to eliminate the
-    // metadata. If we're building an executable, however, --gc-sections drops
-    // the size of hello world from 1.8MB to 597K, a 67% reduction.
-    if !dylib && !t.options.is_like_osx {
-        cmd.arg("-Wl,--gc-sections");
-    }
+    // Try to strip as much out of the generated object by removing unused
+    // sections if possible. See more comments in linker.rs
+    cmd.gc_sections(dylib);
 
     let used_link_args = sess.cstore.get_used_link_args().borrow();
 
-    if t.options.position_independent_executables {
+    if !dylib && t.options.position_independent_executables {
         let empty_vec = Vec::new();
         let empty_str = String::new();
         let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
         let mut args = args.iter().chain(used_link_args.iter());
-        if !dylib
-            && (t.options.relocation_model == "pic"
-                || *sess.opts.cg.relocation_model.as_ref()
-                   .unwrap_or(&empty_str) == "pic")
+        let relocation_model = sess.opts.cg.relocation_model.as_ref()
+                                   .unwrap_or(&empty_str);
+        if (t.options.relocation_model == "pic" || *relocation_model == "pic")
             && !args.any(|x| *x == "-static") {
-            cmd.arg("-pie");
+            cmd.position_independent_executable();
         }
     }
 
-    if t.options.linker_is_gnu {
-        // GNU-style linkers support optimization with -O. GNU ld doesn't need a
-        // numeric argument, but other linkers do.
-        if sess.opts.optimize == config::Default ||
-           sess.opts.optimize == config::Aggressive {
-            cmd.arg("-Wl,-O1");
-        }
-    }
+    // Pass optimization flags down to the linker.
+    cmd.optimize();
 
     // We want to prevent the compiler from accidentally leaking in any system
     // libraries, so we explicitly ask gcc to not link to any libraries by
     // 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.
-    if !t.options.is_like_windows {
-        cmd.arg("-nodefaultlibs");
-    }
-
-    // Mark all dynamic libraries and executables as compatible with ASLR
-    // FIXME #17098: ASLR breaks gdb
-    if t.options.is_like_windows && sess.opts.debuginfo == NoDebugInfo {
-        // cmd.arg("-Wl,--dynamicbase");
-    }
+    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
@@ -1019,18 +990,7 @@ fn link_args(cmd: &mut Command,
     // # Telling the linker what we're doing
 
     if dylib {
-        // On mac we need to tell the linker to let this library be rpathed
-        if sess.target.target.options.is_like_osx {
-            cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
-
-            if sess.opts.cg.rpath {
-                let mut v = OsString::from("-Wl,-install_name,@rpath/");
-                v.push(out_filename.file_name().unwrap());
-                cmd.arg(&v);
-            }
-        } else {
-            cmd.arg("-shared");
-        }
+        cmd.build_dylib(out_filename);
     }
 
     // FIXME (#2397): At some point we want to rpath our guesses as to
@@ -1059,9 +1019,10 @@ fn link_args(cmd: &mut Command,
 
     // Finally add all the linker arguments provided on the command line along
     // with any #[link_args] attributes found inside the crate
-    let empty = Vec::new();
-    cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty));
-    cmd.args(&used_link_args[..]);
+    if let Some(ref args) = sess.opts.cg.link_args {
+        cmd.args(args);
+    }
+    cmd.args(&used_link_args);
 }
 
 // # Native library linking
@@ -1075,21 +1036,15 @@ fn link_args(cmd: &mut Command,
 // Also note that the native libraries linked here are only the ones located
 // in the current crate. Upstream crates with native library dependencies
 // may have their native library pulled in above.
-fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
+fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
     sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
         match k {
-            PathKind::Framework => { cmd.arg("-F").arg(path); }
-            _ => { cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(path)); }
+            PathKind::Framework => { cmd.framework_path(path); }
+            _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(path)); }
         }
         FileDoesntMatch
     });
 
-    // Some platforms take hints about whether a library is static or dynamic.
-    // For those that support this, we ensure we pass the option if the library
-    // was flagged "static" (most defaults are dynamic) to ensure that if
-    // libfoo.a and libfoo.so both exist that the right one is chosen.
-    let takes_hints = !sess.target.target.options.is_like_osx;
-
     let libs = sess.cstore.get_used_libraries();
     let libs = libs.borrow();
 
@@ -1100,46 +1055,29 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
         kind != cstore::NativeStatic
     });
 
-    // Platforms that take hints generally also support the --whole-archive
-    // flag. We need to pass this flag when linking static native libraries to
-    // ensure the entire library is included.
-    //
-    // For more details see #15460, but the gist is that the linker will strip
-    // away any unused objects in the archive if we don't otherwise explicitly
-    // reference them. This can occur for libraries which are just providing
-    // bindings, libraries with generic functions, etc.
-    if takes_hints {
-        cmd.arg("-Wl,--whole-archive").arg("-Wl,-Bstatic");
-    }
+    // Some platforms take hints about whether a library is static or dynamic.
+    // For those that support this, we ensure we pass the option if the library
+    // was flagged "static" (most defaults are dynamic) to ensure that if
+    // libfoo.a and libfoo.so both exist that the right one is chosen.
+    cmd.hint_static();
+
     let search_path = archive_search_paths(sess);
     for l in staticlibs {
-        if takes_hints {
-            cmd.arg(&format!("-l{}", l));
-        } else {
-            // -force_load is the OSX equivalent of --whole-archive, but it
-            // involves passing the full path to the library to link.
-            let lib = archive::find_library(&l[..],
-                                            &sess.target.target.options.staticlib_prefix,
-                                            &sess.target.target.options.staticlib_suffix,
-                                            &search_path[..],
-                                            &sess.diagnostic().handler);
-            let mut v = OsString::from("-Wl,-force_load,");
-            v.push(&lib);
-            cmd.arg(&v);
-        }
-    }
-    if takes_hints {
-        cmd.arg("-Wl,--no-whole-archive").arg("-Wl,-Bdynamic");
+        // Here we explicitly ask that the entire archive is included into the
+        // result artifact. For more details see #15460, but the gist is that
+        // the linker will strip away any unused objects in the archive if we
+        // don't otherwise explicitly reference them. This can occur for
+        // libraries which are just providing bindings, libraries with generic
+        // functions, etc.
+        cmd.link_whole_staticlib(l, &search_path);
     }
 
+    cmd.hint_dynamic();
+
     for &(ref l, kind) in others {
         match kind {
-            cstore::NativeUnknown => {
-                cmd.arg(&format!("-l{}", l));
-            }
-            cstore::NativeFramework => {
-                cmd.arg("-framework").arg(&l[..]);
-            }
+            cstore::NativeUnknown => cmd.link_dylib(l),
+            cstore::NativeFramework => cmd.link_framework(l),
             cstore::NativeStatic => unreachable!(),
         }
     }
@@ -1150,7 +1088,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
 // Rust crates are not considered at all when creating an rlib output. All
 // dependencies will be linked when producing the final output (instead of
 // the intermediate rlib version)
-fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
+fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session,
                             dylib: bool, tmpdir: &Path,
                             trans: &CrateTranslation) {
     // All of the heavy lifting has previously been accomplished by the
@@ -1201,7 +1139,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
     }
 
     // Adds the static "rlib" versions of all crates to the command line.
-    fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
+    fn add_static_crate(cmd: &mut Linker, sess: &Session, tmpdir: &Path,
                         cratepath: &Path) {
         // When performing LTO on an executable output, all of the
         // bytecode from the upstream libraries has already been
@@ -1227,11 +1165,9 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
                 match fs::copy(&cratepath, &dst) {
                     Ok(..) => {}
                     Err(e) => {
-                        sess.err(&format!("failed to copy {} to {}: {}",
-                                         cratepath.display(),
-                                         dst.display(),
-                                         e));
-                        sess.abort_if_errors();
+                        sess.fatal(&format!("failed to copy {} to {}: {}",
+                                            cratepath.display(),
+                                            dst.display(), e));
                     }
                 }
                 // Fix up permissions of the copy, as fs::copy() preserves
@@ -1244,10 +1180,8 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
                 }) {
                     Ok(..) => {}
                     Err(e) => {
-                        sess.err(&format!("failed to chmod {} when preparing \
-                                          for LTO: {}", dst.display(),
-                                         e));
-                        sess.abort_if_errors();
+                        sess.fatal(&format!("failed to chmod {} when preparing \
+                                             for LTO: {}", dst.display(), e));
                     }
                 }
                 let handler = &sess.diagnostic().handler;
@@ -1257,22 +1191,23 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
                     lib_search_paths: archive_search_paths(sess),
                     slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
                     slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
-                    maybe_ar_prog: sess.opts.cg.ar.clone()
+                    ar_prog: get_ar_prog(sess),
+                    command_path: command_path(sess),
                 };
                 let mut archive = Archive::open(config);
                 archive.remove_file(&format!("{}.o", name));
                 let files = archive.files();
                 if files.iter().any(|s| s.ends_with(".o")) {
-                    cmd.arg(&dst);
+                    cmd.link_rlib(&dst);
                 }
             });
         } else {
-            cmd.arg(&fix_windows_verbatim_for_gcc(cratepath));
+            cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
         }
     }
 
     // Same thing as above, but for dynamic crates instead of static crates.
-    fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: &Path) {
+    fn add_dynamic_crate(cmd: &mut Linker, sess: &Session, cratepath: &Path) {
         // If we're performing LTO, then it should have been previously required
         // that all upstream rust dependencies were available in an rlib format.
         assert!(!sess.lto());
@@ -1280,10 +1215,10 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
         // Just need to tell the linker about where the library lives and
         // what its name is
         if let Some(dir) = cratepath.parent() {
-            cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(dir));
+            cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
         }
         let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
-        cmd.arg(&format!("-l{}", unlib(&sess.target, filestem)));
+        cmd.link_dylib(&unlib(&sess.target, filestem));
     }
 }
 
@@ -1305,7 +1240,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
 // generic function calls a native function, then the generic function must
 // be instantiated in the target crate, meaning that the native symbol must
 // also be resolved in the target crate.
-fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
+fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
     // Be sure to use a topological sorting of crates because there may be
     // interdependencies between native libraries. When passing -nodefaultlibs,
     // for example, almost all native libraries depend on libc, so we have to
@@ -1320,13 +1255,8 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
         let libs = csearch::get_native_libraries(&sess.cstore, cnum);
         for &(kind, ref lib) in &libs {
             match kind {
-                cstore::NativeUnknown => {
-                    cmd.arg(&format!("-l{}", *lib));
-                }
-                cstore::NativeFramework => {
-                    cmd.arg("-framework");
-                    cmd.arg(&lib[..]);
-                }
+                cstore::NativeUnknown => cmd.link_dylib(lib),
+                cstore::NativeFramework => cmd.link_framework(lib),
                 cstore::NativeStatic => {
                     sess.bug("statics shouldn't be propagated");
                 }
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
new file mode 100644 (file)
index 0000000..1eacec4
--- /dev/null
@@ -0,0 +1,253 @@
+// 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::ffi::OsString;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use rustc_back::archive;
+use session::Session;
+use session::config;
+
+/// Linker abstraction used by back::link to build up the command to invoke a
+/// linker.
+///
+/// This trait is the total list of requirements needed by `back::link` and
+/// represents the meaning of each option being passed down. This trait is then
+/// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
+/// MSVC linker (e.g. `link.exe`) is being used.
+pub trait Linker {
+    fn link_dylib(&mut self, lib: &str);
+    fn link_framework(&mut self, framework: &str);
+    fn link_staticlib(&mut self, lib: &str);
+    fn link_rlib(&mut self, lib: &Path);
+    fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]);
+    fn include_path(&mut self, path: &Path);
+    fn framework_path(&mut self, path: &Path);
+    fn output_filename(&mut self, path: &Path);
+    fn add_object(&mut self, path: &Path);
+    fn gc_sections(&mut self, is_dylib: bool);
+    fn position_independent_executable(&mut self);
+    fn optimize(&mut self);
+    fn no_default_libraries(&mut self);
+    fn build_dylib(&mut self, out_filename: &Path);
+    fn args(&mut self, args: &[String]);
+    fn hint_static(&mut self);
+    fn hint_dynamic(&mut self);
+    fn whole_archives(&mut self);
+    fn no_whole_archives(&mut self);
+}
+
+pub struct GnuLinker<'a> {
+    pub cmd: &'a mut Command,
+    pub sess: &'a Session,
+}
+
+impl<'a> GnuLinker<'a> {
+    fn takes_hints(&self) -> bool {
+        !self.sess.target.target.options.is_like_osx
+    }
+}
+
+impl<'a> Linker for GnuLinker<'a> {
+    fn link_dylib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
+    fn link_staticlib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
+    fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
+    fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
+    fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); }
+    fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
+    fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
+    fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
+    fn args(&mut self, args: &[String]) { self.cmd.args(args); }
+
+    fn link_framework(&mut self, framework: &str) {
+        self.cmd.arg("-framework").arg(framework);
+    }
+
+    fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
+        let target = &self.sess.target.target;
+        if !target.options.is_like_osx {
+            self.cmd.arg("-Wl,--whole-archive")
+                    .arg("-l").arg(lib)
+                    .arg("-Wl,--no-whole-archive");
+        } else {
+            // -force_load is the OSX equivalent of --whole-archive, but it
+            // involves passing the full path to the library to link.
+            let mut v = OsString::from("-Wl,-force_load,");
+            v.push(&archive::find_library(lib,
+                                          &target.options.staticlib_prefix,
+                                          &target.options.staticlib_suffix,
+                                          search_path,
+                                          &self.sess.diagnostic().handler));
+            self.cmd.arg(&v);
+        }
+    }
+
+    fn gc_sections(&mut self, is_dylib: bool) {
+        // The dead_strip option to the linker specifies that functions and data
+        // unreachable by the entry point will be removed. This is quite useful
+        // with Rust's compilation model of compiling libraries at a time into
+        // one object file. For example, this brings hello world from 1.7MB to
+        // 458K.
+        //
+        // Note that this is done for both executables and dynamic libraries. We
+        // won't get much benefit from dylibs because LLVM will have already
+        // stripped away as much as it could. This has not been seen to impact
+        // link times negatively.
+        //
+        // -dead_strip can't be part of the pre_link_args because it's also used
+        // for partial linking when using multiple codegen units (-r).  So we
+        // insert it here.
+        if self.sess.target.target.options.is_like_osx {
+            self.cmd.arg("-Wl,-dead_strip");
+
+        // If we're building a dylib, we don't use --gc-sections because LLVM
+        // has already done the best it can do, and we also don't want to
+        // eliminate the metadata. If we're building an executable, however,
+        // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
+        // reduction.
+        } else if !is_dylib {
+            self.cmd.arg("-Wl,--gc-sections");
+        }
+    }
+
+    fn optimize(&mut self) {
+        if !self.sess.target.target.options.linker_is_gnu { return }
+
+        // GNU-style linkers support optimization with -O. GNU ld doesn't
+        // need a numeric argument, but other linkers do.
+        if self.sess.opts.optimize == config::Default ||
+           self.sess.opts.optimize == config::Aggressive {
+            self.cmd.arg("-Wl,-O1");
+        }
+    }
+
+    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");
+        }
+    }
+
+    fn build_dylib(&mut self, out_filename: &Path) {
+        // On mac we need to tell the linker to let this library be rpathed
+        if self.sess.target.target.options.is_like_osx {
+            self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
+
+            if self.sess.opts.cg.rpath {
+                let mut v = OsString::from("-Wl,-install_name,@rpath/");
+                v.push(out_filename.file_name().unwrap());
+                self.cmd.arg(&v);
+            }
+        } else {
+            self.cmd.arg("-shared");
+        }
+    }
+
+    fn whole_archives(&mut self) {
+        if !self.takes_hints() { return }
+        self.cmd.arg("-Wl,--whole-archive");
+    }
+
+    fn no_whole_archives(&mut self) {
+        if !self.takes_hints() { return }
+        self.cmd.arg("-Wl,--no-whole-archive");
+    }
+
+    fn hint_static(&mut self) {
+        if !self.takes_hints() { return }
+        self.cmd.arg("-Wl,-Bstatic");
+    }
+
+    fn hint_dynamic(&mut self) {
+        if !self.takes_hints() { return }
+        self.cmd.arg("-Wl,-Bdynamic");
+    }
+}
+
+pub struct MsvcLinker<'a> {
+    pub cmd: &'a mut Command,
+    pub sess: &'a Session,
+}
+
+impl<'a> Linker for MsvcLinker<'a> {
+    fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
+    fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
+    fn args(&mut self, args: &[String]) { self.cmd.args(args); }
+    fn build_dylib(&mut self, _out_filename: &Path) { self.cmd.arg("/DLL"); }
+    fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); }
+
+    fn link_dylib(&mut self, lib: &str) {
+        self.cmd.arg(&format!("{}.lib", lib));
+    }
+    fn link_staticlib(&mut self, lib: &str) {
+        self.cmd.arg(&format!("{}.lib", lib));
+    }
+
+    fn position_independent_executable(&mut self) {
+        // noop
+    }
+
+    fn no_default_libraries(&mut self) {
+        // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
+        // as there's been trouble in the past of linking the C++ standard
+        // library required by LLVM. This likely needs to happen one day, but
+        // in general Windows is also a more controlled environment than
+        // Unix, so it's not necessarily as critical that this be implemented.
+        //
+        // Note that there are also some licensing worries about statically
+        // linking some libraries which require a specific agreement, so it may
+        // not ever be possible for us to pass this flag.
+    }
+
+    fn include_path(&mut self, path: &Path) {
+        let mut arg = OsString::from("/LIBPATH:");
+        arg.push(path);
+        self.cmd.arg(&arg);
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        let mut arg = OsString::from("/OUT:");
+        arg.push(path);
+        self.cmd.arg(&arg);
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        panic!("frameworks are not supported on windows")
+    }
+    fn link_framework(&mut self, _framework: &str) {
+        panic!("frameworks are not supported on windows")
+    }
+
+    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+        // not supported?
+        self.link_staticlib(lib);
+    }
+    fn optimize(&mut self) {
+        // Needs more investigation of `/OPT` arguments
+    }
+    fn whole_archives(&mut self) {
+        // hints not supported?
+    }
+    fn no_whole_archives(&mut self) {
+        // hints not supported?
+    }
+
+    // On windows static libraries are of the form `foo.lib` and dynamic
+    // libraries are not linked against directly, but rather through their
+    // import libraries also called `foo.lib`. As a result there's no
+    // possibility for a native library to appear both dynamically and
+    // statically in the same folder so we don't have to worry about hints like
+    // we do on Unix platforms.
+    fn hint_static(&mut self) {}
+    fn hint_dynamic(&mut self) {}
+}
index 6457140bcc0f987ba68fef92b00428c45cccc2b9..e13a5e97f7573c8207cfd21d09e88b7f1b656891 100644 (file)
@@ -31,7 +31,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     }
 
     // Make sure we actually can run LTO
-    for crate_type in &*sess.crate_types.borrow() {
+    for crate_type in sess.crate_types.borrow().iter() {
         match *crate_type {
             config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
             _ => {
index a10ff71a8f689d400f4b565109ac3649ab9fac01..267f0b6d95329dbfb9d80ffbc628d40988b28caf 100644 (file)
@@ -10,7 +10,7 @@
 
 use back::lto;
 use back::link::{get_cc_prog, remove};
-use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
+use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
 use session::Session;
 use session::config;
 use llvm;
@@ -21,11 +21,10 @@ use util::common::time;
 use util::common::path2cstr;
 use syntax::codemap;
 use syntax::diagnostic;
-use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
+use syntax::diagnostic::{Emitter, Handler, Level};
 
 use std::ffi::{CStr, CString};
 use std::fs;
-use std::iter::Unfold;
 use std::mem;
 use std::path::Path;
 use std::process::{Command, Stdio};
@@ -188,10 +187,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let opt_level = get_llvm_opt_level(sess.opts.optimize);
     let use_softfp = sess.opts.cg.soft_float;
 
-    // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
-    let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
-                     !sess.target.target.options.eliminate_frame_pointer;
-
     let any_library = sess.crate_types.borrow().iter().any(|ty| {
         *ty != config::CrateTypeExecutable
     });
@@ -237,7 +232,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
             opt_level,
             true /* EnableSegstk */,
             use_softfp,
-            no_fp_elim,
             !any_library && reloc_model == llvm::RelocPIC,
             ffunction_sections,
             fdata_sections,
@@ -279,6 +273,9 @@ struct ModuleConfig {
     no_prepopulate_passes: bool,
     no_builtins: bool,
     time_passes: bool,
+    vectorize_loop: bool,
+    vectorize_slp: bool,
+    merge_functions: bool,
 }
 
 unsafe impl Send for ModuleConfig { }
@@ -301,6 +298,9 @@ impl ModuleConfig {
             no_prepopulate_passes: false,
             no_builtins: false,
             time_passes: false,
+            vectorize_loop: false,
+            vectorize_slp: false,
+            merge_functions: false,
         }
     }
 
@@ -309,6 +309,18 @@ impl ModuleConfig {
         self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
         self.no_builtins = trans.no_builtins;
         self.time_passes = sess.time_passes();
+
+        // Copy what clang does by turning on loop vectorization at O2 and
+        // slp vectorization at O3. Otherwise configure other optimization aspects
+        // of this pass manager builder.
+        self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
+                             (sess.opts.optimize == config::Default ||
+                              sess.opts.optimize == config::Aggressive);
+        self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
+                            sess.opts.optimize == config::Aggressive;
+
+        self.merge_functions = sess.opts.optimize == config::Default ||
+                               sess.opts.optimize == config::Aggressive;
     }
 }
 
@@ -342,8 +354,8 @@ struct HandlerFreeVars<'a> {
 }
 
 unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
-                                           msg: &'b str,
-                                           cookie: c_uint) {
+                                               msg: &'b str,
+                                               cookie: c_uint) {
     use syntax::codemap::ExpnId;
 
     match cgcx.lto_ctxt {
@@ -448,27 +460,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
                 let pass = CString::new(pass).unwrap();
                 llvm::LLVMRustAddPass(fpm, pass.as_ptr())
             };
-            if !config.no_verify { assert!(addpass("verify")); }
 
+            if !config.no_verify { assert!(addpass("verify")); }
             if !config.no_prepopulate_passes {
                 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
                 llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-                populate_llvm_passes(fpm, mpm, llmod, opt_level,
-                                     config.no_builtins);
+                populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
             }
 
             for pass in &config.passes {
-                let pass = CString::new(pass.clone()).unwrap();
-                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
-                    cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
+                if !addpass(pass) {
+                    cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
+                                               pass));
                 }
             }
 
             for pass in &cgcx.plugin_passes {
-                let pass = CString::new(pass.clone()).unwrap();
-                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
-                    cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
-                                               does not recognize it", pass));
+                if !addpass(pass) {
+                    cgcx.handler.err(&format!("a plugin asked for LLVM pass \
+                                               `{}` but LLVM does not \
+                                               recognize it", pass));
                 }
             }
 
@@ -520,7 +531,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
         llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
         f(cpm);
-        llvm::LLVMDisposePassManager(cpm);
     }
 
     if config.emit_bc {
@@ -537,13 +547,15 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             let out = path2cstr(&out);
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
+                llvm::LLVMDisposePassManager(cpm);
             })
         }
 
         if config.emit_asm {
             let path = output_names.with_extension(&format!("{}.s", name_extra));
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
+                write_output_file(cgcx.handler, tm, cpm, llmod, &path,
+                                  llvm::AssemblyFileType);
             });
         }
 
@@ -900,11 +912,10 @@ fn run_work_singlethreaded(sess: &Session,
                            reachable: &[String],
                            work_items: Vec<WorkItem>) {
     let cgcx = CodegenContext::new_with_session(sess, reachable);
-    let mut work_items = work_items;
 
     // Since we're running single-threaded, we can pass the session to
     // the proc, allowing `optimize_and_codegen` to perform LTO.
-    for work in Unfold::new((), |_| work_items.pop()) {
+    for work in work_items.into_iter().rev() {
         execute_work_item(&cgcx, work);
     }
 }
@@ -928,7 +939,7 @@ fn run_work_multithreaded(sess: &Session,
         futures.push(rx);
 
         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
-            let diag_handler = mk_handler(true, box diag_emitter);
+            let diag_handler = Handler::with_emitter(true, box diag_emitter);
 
             // Must construct cgcx inside the proc because it has non-Send
             // fields.
@@ -1005,19 +1016,12 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
 }
 
 unsafe fn configure_llvm(sess: &Session) {
-    use std::sync::{Once, ONCE_INIT};
-    static INIT: Once = ONCE_INIT;
-
-    // Copy what clang does by turning on loop vectorization at O2 and
-    // slp vectorization at O3
-    let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
-                         (sess.opts.optimize == config::Default ||
-                          sess.opts.optimize == config::Aggressive);
-    let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
-                        sess.opts.optimize == config::Aggressive;
+    use std::sync::Once;
+    static INIT: Once = Once::new();
 
     let mut llvm_c_strs = Vec::new();
     let mut llvm_args = Vec::new();
+
     {
         let mut add = |arg: &str| {
             let s = CString::new(arg).unwrap();
@@ -1025,8 +1029,6 @@ unsafe fn configure_llvm(sess: &Session) {
             llvm_c_strs.push(s);
         };
         add("rustc"); // fake program name
-        if vectorize_loop { add("-vectorize-loops"); }
-        if vectorize_slp  { add("-vectorize-slp");   }
         if sess.time_llvm_passes() { add("-time-passes"); }
         if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
 
@@ -1084,41 +1086,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
                                mpm: llvm::PassManagerRef,
                                llmod: ModuleRef,
                                opt: llvm::CodeGenOptLevel,
-                               no_builtins: bool) {
+                               config: &ModuleConfig) {
     // Create the PassManagerBuilder for LLVM. We configure it with
     // reasonable defaults and prepare it to actually populate the pass
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
+
+    llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
+                                              config.merge_functions,
+                                              config.vectorize_slp,
+                                              config.vectorize_loop);
+
+    llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
+
+    // Here we match what clang does (kinda). For O0 we only inline
+    // always-inline functions (but don't add lifetime intrinsics), at O1 we
+    // inline with lifetime intrinsics, and O2+ we add an inliner with a
+    // thresholds copied from clang.
     match opt {
         llvm::CodeGenLevelNone => {
-            // Don't add lifetime intrinsics at O0
             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
         }
         llvm::CodeGenLevelLess => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
         }
-        // numeric values copied from clang
         llvm::CodeGenLevelDefault => {
-            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                225);
+            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
         }
         llvm::CodeGenLevelAggressive => {
-            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                275);
+            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
         }
     }
-    llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
-    llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
 
     // Use the builder to populate the function/module pass managers.
     llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
     llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
     llvm::LLVMPassManagerBuilderDispose(builder);
-
-    match opt {
-        llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
-            llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
-        }
-        _ => {}
-    };
 }
index 4ac5a0f388c7db12d5aff88c7095e5f34a7ac94b..bb7e95cd4ae44d7eb4db5f05c0c62d4953a35286 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
-#![feature(alloc)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(core)]
+#![feature(const_fn)]
+#![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(rc_weak)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(unicode)]
-#![feature(path_ext)]
-#![feature(path_relative_from)]
+#![feature(unicode)]
+#![feature(vec_push_all)]
 
 #![allow(trivial_casts)]
 
@@ -73,6 +78,7 @@ pub mod back {
     pub use rustc_back::x86;
     pub use rustc_back::x86_64;
 
+    pub mod linker;
     pub mod link;
     pub mod lto;
     pub mod write;
index 7f66d3a833fde3e8fa4b31646902116ad3c690f7..65d9d9809c926ce8ef1afc98512bb79d70470089 100644 (file)
@@ -34,6 +34,7 @@ use session::Session;
 
 use middle::def;
 use middle::ty::{self, Ty};
+use rustc::ast_map::NodeItem;
 
 use std::cell::Cell;
 use std::fs::File;
@@ -41,7 +42,6 @@ use std::path::Path;
 
 use syntax::ast_util;
 use syntax::ast::{self, NodeId, DefId};
-use syntax::ast_map::NodeItem;
 use syntax::codemap::*;
 use syntax::parse::token::{self, get_ident, keywords};
 use syntax::owned_slice::OwnedSlice;
@@ -52,13 +52,21 @@ use syntax::ptr::P;
 use super::span_utils::SpanUtils;
 use super::recorder::{Recorder, FmtStrs};
 
-use util::ppaux;
-
+macro_rules! down_cast_data {
+    ($id:ident, $kind:ident, $this:ident, $sp:expr) => {
+        let $id = if let super::Data::$kind(data) = $id {
+            data
+        } else {
+            $this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
+        };
+    };
+}
 
 pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
     save_ctxt: SaveContext<'l, 'tcx>,
     sess: &'l Session,
-    analysis: &'l ty::CrateAnalysis<'tcx>,
+    tcx: &'l ty::ctxt<'tcx>,
+    analysis: &'l ty::CrateAnalysis,
 
     span: SpanUtils<'l>,
     fmt: FmtStrs<'l>,
@@ -67,28 +75,23 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
 }
 
 impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
-    pub fn new(sess: &'l Session,
-               analysis: &'l ty::CrateAnalysis<'tcx>,
+    pub fn new(tcx: &'l ty::ctxt<'tcx>,
+               analysis: &'l ty::CrateAnalysis,
                output_file: Box<File>) -> DumpCsvVisitor<'l, 'tcx> {
+        let span_utils = SpanUtils {
+            sess: &tcx.sess,
+            err_count: Cell::new(0)
+        };
         DumpCsvVisitor {
-            sess: sess,
-            save_ctxt: SaveContext::new(sess, analysis, SpanUtils {
-                sess: sess,
-                err_count: Cell::new(0)
-            }),
+            sess: &tcx.sess,
+            tcx: tcx,
+            save_ctxt: SaveContext::new(tcx, span_utils.clone()),
             analysis: analysis,
-            span: SpanUtils {
-                sess: sess,
-                err_count: Cell::new(0)
-            },
+            span: span_utils.clone(),
             fmt: FmtStrs::new(box Recorder {
                                 out: output_file,
                                 dump_spans: false,
-                            },
-                            SpanUtils {
-                                sess: sess,
-                                err_count: Cell::new(0)
-                            }),
+                              }, span_utils),
             cur_scope: 0
         }
     }
@@ -138,7 +141,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let mut result: Vec<(Span, String)> = vec!();
 
         let mut segs = vec!();
-        for (i, (seg, span)) in path.segments.iter().zip(spans.iter()).enumerate() {
+        for (i, (seg, span)) in path.segments.iter().zip(&spans).enumerate() {
             segs.push(seg.clone());
             let sub_path = ast::Path{span: *span, // span for the last segment
                                      global: path.global,
@@ -169,7 +172,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             };
             self.fmt.sub_mod_ref_str(path.span,
                                      *span,
-                                     &qualname[..],
+                                     &qualname,
                                      self.cur_scope);
         }
     }
@@ -192,7 +195,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             };
             self.fmt.sub_mod_ref_str(path.span,
                                      *span,
-                                     &qualname[..],
+                                     &qualname,
                                      self.cur_scope);
         }
     }
@@ -211,7 +214,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let (ref span, ref qualname) = sub_paths[len-2];
         self.fmt.sub_type_ref_str(path.span,
                                   *span,
-                                  &qualname[..]);
+                                  &qualname);
 
         // write the other sub-paths
         if len <= 2 {
@@ -221,18 +224,18 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         for &(ref span, ref qualname) in sub_paths {
             self.fmt.sub_mod_ref_str(path.span,
                                      *span,
-                                     &qualname[..],
+                                     &qualname,
                                      self.cur_scope);
         }
     }
 
     // looks up anything, not just a type
     fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
-        if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
+        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));
         }
-        let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def();
+        let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
             def::DefPrimTy(_) => None,
             _ => Some(def.def_id()),
@@ -240,7 +243,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
     }
 
     fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
-        let def_map = self.analysis.ty_cx.def_map.borrow();
+        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));
@@ -249,7 +252,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         match def {
             def::DefMod(_) |
             def::DefForeignMod(_) => Some(recorder::ModRef),
-            def::DefStruct(_) => Some(recorder::StructRef),
+            def::DefStruct(_) => Some(recorder::TypeRef),
             def::DefTy(..) |
             def::DefAssociatedTy(..) |
             def::DefTrait(_) => Some(recorder::TypeRef),
@@ -282,10 +285,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
             for &(id, ref p, _, _) in &collector.collected_paths {
-                let typ =
-                    ppaux::ty_to_string(
-                        &self.analysis.ty_cx,
-                        *self.analysis.ty_cx.node_types().get(&id).unwrap());
+                let typ = self.tcx.node_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?)
                 self.fmt.formal_str(p.span,
@@ -293,7 +293,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                     id,
                                     qualname,
                                     &path_to_string(p),
-                                    &typ[..]);
+                                    &typ);
             }
         }
     }
@@ -311,22 +311,20 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let mut scope_id;
         // 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 ty::impl_of_method(&self.analysis.ty_cx,
-                                                ast_util::local_def(id)) {
-            Some(impl_id) => match self.analysis.ty_cx.map.get(impl_id.node) {
+        let qualname = match ty::impl_of_method(self.tcx, ast_util::local_def(id)) {
+            Some(impl_id) => match self.tcx.map.get(impl_id.node) {
                 NodeItem(item) => {
                     scope_id = item.id;
                     match item.node {
                         ast::ItemImpl(_, _, _, _, ref ty, _) => {
-                            let mut result = String::from_str("<");
+                            let mut result = String::from("<");
                             result.push_str(&ty_to_string(&**ty));
 
-                            match ty::trait_of_item(&self.analysis.ty_cx,
-                                                    ast_util::local_def(id)) {
+                            match ty::trait_of_item(self.tcx, ast_util::local_def(id)) {
                                 Some(def_id) => {
                                     result.push_str(" as ");
                                     result.push_str(
-                                        &ty::item_path_str(&self.analysis.ty_cx, def_id));
+                                        &ty::item_path_str(self.tcx, def_id));
                                 },
                                 None => {}
                             }
@@ -343,16 +341,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                 _ => {
                     self.sess.span_bug(span,
                         &format!("Container {} for method {} is not a node item {:?}",
-                                 impl_id.node, id, self.analysis.ty_cx.map.get(impl_id.node)));
+                                 impl_id.node, id, self.tcx.map.get(impl_id.node)));
                 },
             },
-            None => match ty::trait_of_item(&self.analysis.ty_cx,
-                                            ast_util::local_def(id)) {
+            None => match ty::trait_of_item(self.tcx, ast_util::local_def(id)) {
                 Some(def_id) => {
                     scope_id = def_id.node;
-                    match self.analysis.ty_cx.map.get(def_id.node) {
+                    match self.tcx.map.get(def_id.node) {
                         NodeItem(_) => {
-                            format!("::{}", ty::item_path_str(&self.analysis.ty_cx, def_id))
+                            format!("::{}", ty::item_path_str(self.tcx, def_id))
                         }
                         _ => {
                             self.sess.span_bug(span,
@@ -371,8 +368,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let qualname = &format!("{}::{}", qualname, &token::get_name(name));
 
         // record the decl for this def (if it has one)
-        let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
-                                             ast_util::local_def(id))
+        let decl_id = ty::trait_item_of_item(self.tcx, ast_util::local_def(id))
             .and_then(|new_id| {
                 let def_id = new_id.def_id();
                 if def_id.node != 0 && def_id != ast_util::local_def(id) {
@@ -419,48 +415,31 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                     id);
     }
 
-    fn process_trait_ref(&mut self,
-                         trait_ref: &ast::TraitRef) {
-        match self.lookup_type_ref(trait_ref.ref_id) {
-            Some(id) => {
-                let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
-                self.fmt.ref_str(recorder::TypeRef,
-                                 trait_ref.path.span,
-                                 sub_span,
-                                 id,
-                                 self.cur_scope);
-                visit::walk_path(self, &trait_ref.path);
-            },
-            None => ()
+    fn process_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
+        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope);
+        if let Some(trait_ref_data) = trait_ref_data {
+            self.fmt.ref_str(recorder::TypeRef,
+                             trait_ref.path.span,
+                             Some(trait_ref_data.span),
+                             trait_ref_data.ref_id,
+                             trait_ref_data.scope);
+            visit::walk_path(self, &trait_ref.path);
         }
     }
 
     fn process_struct_field_def(&mut self,
                                 field: &ast::StructField,
-                                qualname: &str,
-                                scope_id: NodeId) {
-        match field.node.kind {
-            ast::NamedField(ident, _) => {
-                let name = get_ident(ident);
-                let qualname = format!("{}::{}", qualname, name);
-                let typ =
-                    ppaux::ty_to_string(
-                        &self.analysis.ty_cx,
-                        *self.analysis.ty_cx.node_types().get(&field.node.id).unwrap());
-                match self.span.sub_span_before_token(field.span, token::Colon) {
-                    Some(sub_span) => self.fmt.field_str(field.span,
-                                                         Some(sub_span),
-                                                         field.node.id,
-                                                         &name[..],
-                                                         &qualname[..],
-                                                         &typ[..],
-                                                         scope_id),
-                    None => self.sess.span_bug(field.span,
-                                               &format!("Could not find sub-span for field {}",
-                                                       qualname)),
-                }
-            },
-            _ => (),
+                                parent_id: NodeId) {
+        let field_data = self.save_ctxt.get_field_data(field, parent_id);
+        if let Some(field_data) = field_data {
+            down_cast_data!(field_data, VariableData, self, field.span);
+            self.fmt.field_str(field.span,
+                               Some(field_data.span),
+                               field_data.id,
+                               &field_data.name,
+                               &field_data.qualname,
+                               &field_data.type_value,
+                               field_data.scope);
         }
     }
 
@@ -476,16 +455,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         // 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));
-        for (param, param_ss) in generics.ty_params.iter().zip(param_sub_spans.iter()) {
+        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)),
+                               escape(self.span.snippet(param_ss)),
                                id);
             self.fmt.typedef_str(full_span,
-                                 Some(*param_ss),
+                                 Some(param_ss),
                                  param.id,
-                                 &name[..],
+                                 &name,
                                  "");
         }
         self.visit_generics(generics);
@@ -497,19 +476,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                   ty_params: &ast::Generics,
                   body: &ast::Block) {
         let fn_data = self.save_ctxt.get_item_data(item);
-        if let super::Data::FunctionData(fn_data) = fn_data {
-            self.fmt.fn_str(item.span,
-                            Some(fn_data.span),
-                            fn_data.id,
-                            &fn_data.qualname,
-                            fn_data.scope);
+        down_cast_data!(fn_data, FunctionData, self, item.span);
+        self.fmt.fn_str(item.span,
+                        Some(fn_data.span),
+                        fn_data.id,
+                        &fn_data.qualname,
+                        fn_data.scope);
 
 
-            self.process_formals(&decl.inputs, &fn_data.qualname);
-            self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
-        } else {
-            unreachable!();
-        }
+        self.process_formals(&decl.inputs, &fn_data.qualname);
+        self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
 
         for arg in &decl.inputs {
             self.visit_ty(&arg.ty);
@@ -528,18 +504,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                     expr: &ast::Expr)
     {
         let var_data = self.save_ctxt.get_item_data(item);
-        if let super::Data::VariableData(var_data) = var_data {
-            self.fmt.static_str(item.span,
-                                Some(var_data.span),
-                                var_data.id,
-                                &var_data.name,
-                                &var_data.qualname,
-                                &var_data.value,
-                                &var_data.type_value,
-                                var_data.scope);
-        } else {
-            unreachable!();
-        }
+        down_cast_data!(var_data, VariableData, self, item.span);
+        self.fmt.static_str(item.span,
+                            Some(var_data.span),
+                            var_data.id,
+                            &var_data.name,
+                            &var_data.qualname,
+                            &var_data.value,
+                            &var_data.type_value,
+                            var_data.scope);
 
         self.visit_ty(&typ);
         self.visit_expr(expr);
@@ -552,7 +525,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                      typ: &ast::Ty,
                      expr: &ast::Expr)
     {
-        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(id));
+        let qualname = format!("::{}", self.tcx.map.path_to_string(id));
 
         let sub_span = self.span.sub_span_after_keyword(span,
                                                         keywords::Const);
@@ -561,7 +534,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                             sub_span,
                             id,
                             &get_ident((*ident).clone()),
-                            &qualname[..],
+                            &qualname,
                             &self.span.snippet(expr.span),
                             &ty_to_string(&*typ),
                             self.cur_scope);
@@ -575,7 +548,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                       item: &ast::Item,
                       def: &ast::StructDef,
                       ty_params: &ast::Generics) {
-        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+        let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
 
         let ctor_id = match def.ctor_id {
             Some(node_id) => node_id,
@@ -587,40 +560,35 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                             sub_span,
                             item.id,
                             ctor_id,
-                            &qualname[..],
+                            &qualname,
                             self.cur_scope,
-                            &val[..]);
+                            &val);
 
         // fields
         for field in &def.fields {
-            self.process_struct_field_def(field, &qualname[..], item.id);
-            self.visit_ty(&*field.node.ty);
+            self.process_struct_field_def(field, item.id);
+            self.visit_ty(&field.node.ty);
         }
 
-        self.process_generic_params(ty_params, item.span, &qualname[..], item.id);
+        self.process_generic_params(ty_params, item.span, &qualname, item.id);
     }
 
     fn process_enum(&mut self,
                     item: &ast::Item,
                     enum_definition: &ast::EnumDef,
                     ty_params: &ast::Generics) {
-        let enum_name = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
-        let val = self.span.snippet(item.span);
-        match self.span.sub_span_after_keyword(item.span, keywords::Enum) {
-            Some(sub_span) => self.fmt.enum_str(item.span,
-                                                Some(sub_span),
-                                                item.id,
-                                                &enum_name[..],
-                                                self.cur_scope,
-                                                &val[..]),
-            None => self.sess.span_bug(item.span,
-                                       &format!("Could not find subspan for enum {}",
-                                               enum_name)),
-        }
+        let enum_data = self.save_ctxt.get_item_data(item);
+        down_cast_data!(enum_data, EnumData, self, item.span);
+        self.fmt.enum_str(item.span,
+                          Some(enum_data.span),
+                          enum_data.id,
+                          &enum_data.qualname,
+                          enum_data.scope,
+                          &enum_data.value);
+
         for variant in &enum_definition.variants {
-            let name = get_ident(variant.node.name);
-            let name = &name;
-            let mut qualname = enum_name.clone();
+            let name = &get_ident(variant.node.name);
+            let mut qualname = enum_data.qualname.clone();
             qualname.push_str("::");
             qualname.push_str(name);
             let val = self.span.snippet(variant.span);
@@ -631,10 +599,10 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                                self.span.span_for_first_ident(variant.span),
                                                variant.node.id,
                                                name,
-                                               &qualname[..],
-                                               &enum_name[..],
-                                               &val[..],
-                                               item.id);
+                                               &qualname,
+                                               &enum_data.qualname,
+                                               &val,
+                                               enum_data.id);
                     for arg in args {
                         self.visit_ty(&*arg.ty);
                     }
@@ -644,25 +612,23 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                         Some(node_id) => node_id,
                         None => -1,
                     };
-                    self.fmt.struct_variant_str(
-                        variant.span,
-                        self.span.span_for_first_ident(variant.span),
-                        variant.node.id,
-                        ctor_id,
-                        &qualname[..],
-                        &enum_name[..],
-                        &val[..],
-                        item.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, &qualname, variant.node.id);
+                        self.process_struct_field_def(field, variant.node.id);
                         self.visit_ty(&*field.node.ty);
                     }
                 }
             }
         }
-
-        self.process_generic_params(ty_params, item.span, &enum_name[..], item.id);
+        self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
     }
 
     fn process_impl(&mut self,
@@ -671,45 +637,36 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     trait_ref: &Option<ast::TraitRef>,
                     typ: &ast::Ty,
                     impl_items: &[P<ast::ImplItem>]) {
-        let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
-        match typ.node {
-            // Common case impl for a struct or something basic.
-            ast::TyPath(None, ref path) => {
-                let sub_span = self.span.sub_span_for_type_name(path.span);
-                let self_id = self.lookup_type_ref(typ.id).map(|id| {
-                    self.fmt.ref_str(recorder::TypeRef,
-                                     path.span,
-                                     sub_span,
-                                     id,
-                                     self.cur_scope);
-                    id
-                });
-                self.fmt.impl_str(path.span,
-                                  sub_span,
-                                  item.id,
-                                  self_id,
-                                  trait_id,
-                                  self.cur_scope);
-            },
-            _ => {
-                // Less useful case, impl for a compound type.
-                self.visit_ty(&*typ);
-
-                let sub_span = self.span.sub_span_for_type_name(typ.span);
-                self.fmt.impl_str(typ.span,
-                                  sub_span,
-                                  item.id,
-                                  None,
-                                  trait_id,
-                                  self.cur_scope);
+        let impl_data = self.save_ctxt.get_item_data(item);
+        down_cast_data!(impl_data, ImplData, self, item.span);
+        match impl_data.self_ref {
+            Some(ref self_ref) => {
+                self.fmt.ref_str(recorder::TypeRef,
+                                 item.span,
+                                 Some(self_ref.span),
+                                 self_ref.ref_id,
+                                 self_ref.scope);
+            }
+            None => {
+                self.visit_ty(&typ);
             }
         }
-
-        match *trait_ref {
-            Some(ref trait_ref) => self.process_trait_ref(trait_ref),
-            None => (),
+        if let Some(ref trait_ref_data) = impl_data.trait_ref {
+            self.fmt.ref_str(recorder::TypeRef,
+                             item.span,
+                             Some(trait_ref_data.span),
+                             trait_ref_data.ref_id,
+                             trait_ref_data.scope);
+            visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
         }
 
+        self.fmt.impl_str(item.span,
+                          Some(impl_data.span),
+                          impl_data.id,
+                          impl_data.self_ref.map(|data| data.ref_id),
+                          impl_data.trait_ref.map(|data| data.ref_id),
+                          impl_data.scope);
+
         self.process_generic_params(type_parameters, item.span, "", item.id);
         for impl_item in impl_items {
             self.visit_impl_item(impl_item);
@@ -721,18 +678,18 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                      generics: &ast::Generics,
                      trait_refs: &OwnedSlice<ast::TyParamBound>,
                      methods: &[P<ast::TraitItem>]) {
-        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+        let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
         let val = self.span.snippet(item.span);
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
         self.fmt.trait_str(item.span,
                            sub_span,
                            item.id,
-                           &qualname[..],
+                           &qualname,
                            self.cur_scope,
-                           &val[..]);
+                           &val);
 
         // super-traits
-        for super_bound in &**trait_refs {
+        for super_bound in trait_refs.iter() {
             let trait_ref = match *super_bound {
                 ast::TraitTyParamBound(ref trait_ref, _) => {
                     trait_ref
@@ -761,29 +718,22 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         }
 
         // walk generics and methods
-        self.process_generic_params(generics, item.span, &qualname[..], item.id);
+        self.process_generic_params(generics, item.span, &qualname, item.id);
         for method in methods {
             self.visit_trait_item(method)
         }
     }
 
     fn process_mod(&mut self,
-                   item: &ast::Item,  // The module in question, represented as an item.
-                   m: &ast::Mod) {
-        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
-
-        let cm = self.sess.codemap();
-        let filename = cm.span_to_filename(m.inner);
-
-        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Mod);
+                   item: &ast::Item) {  // The module in question, represented as an item.
+        let mod_data = self.save_ctxt.get_item_data(item);
+        down_cast_data!(mod_data, ModData, self, item.span);
         self.fmt.mod_str(item.span,
-                         sub_span,
-                         item.id,
-                         &qualname[..],
-                         self.cur_scope,
-                         &filename[..]);
-
-        self.nest(item.id, |v| visit::walk_mod(v, m));
+                         Some(mod_data.span),
+                         mod_data.id,
+                         &mod_data.qualname,
+                         mod_data.scope,
+                         &mod_data.filename);
     }
 
     fn process_path(&mut self,
@@ -795,7 +745,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             return
         }
 
-        let def_map = self.analysis.ty_cx.def_map.borrow();
+        let def_map = self.tcx.def_map.borrow();
         if !def_map.contains_key(&id) {
             self.sess.span_bug(span,
                                &format!("def_map has no key for {} in visit_expr", id));
@@ -813,7 +763,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                                     sub_span,
                                                     def.def_id(),
                                                     self.cur_scope),
-            def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
+            def::DefStruct(def_id) => self.fmt.ref_str(recorder::TypeRef,
                                                        span,
                                                        sub_span,
                                                        def_id,
@@ -826,12 +776,10 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             def::DefMethod(declid, provenence) => {
                 let sub_span = self.span.sub_span_for_meth_name(span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
-                    let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
-                                                    declid);
+                    let ti = ty::impl_or_trait_item(self.tcx, declid);
                     match provenence {
                         def::FromTrait(def_id) => {
-                            Some(ty::trait_items(&self.analysis.ty_cx,
-                                                 def_id)
+                            Some(ty::trait_items(self.tcx, def_id)
                                     .iter()
                                     .find(|mr| {
                                         mr.name() == ti.name()
@@ -840,16 +788,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                     .def_id())
                         }
                         def::FromImpl(def_id) => {
-                            let impl_items = self.analysis
-                                                 .ty_cx
-                                                 .impl_items
-                                                 .borrow();
+                            let impl_items = self.tcx.impl_items.borrow();
                             Some(impl_items.get(&def_id)
                                            .unwrap()
                                            .iter()
                                            .find(|mr| {
                                                 ty::impl_or_trait_item(
-                                                    &self.analysis.ty_cx,
+                                                    self.tcx,
                                                     mr.def_id()
                                                 ).name() == ti.name()
                                             })
@@ -881,7 +826,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         // modules or types in the path prefix
         match def {
             def::DefMethod(did, _) => {
-                let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did);
+                let ti = ty::impl_or_trait_item(self.tcx, did);
                 if let ty::MethodTraitItem(m) = ti {
                     if m.explicit_self == ty::StaticExplicitSelfCategory {
                         self.write_sub_path_trait_truncated(path);
@@ -910,68 +855,54 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
 
         self.write_sub_paths_truncated(path, false);
 
-        let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, ex).sty;
-        let struct_def = match *ty {
-            ty::ty_struct(def_id, _) => {
-                let sub_span = self.span.span_for_last_ident(path.span);
-                self.fmt.ref_str(recorder::StructRef,
-                                 path.span,
-                                 sub_span,
-                                 def_id,
-                                 self.cur_scope);
-                Some(def_id)
-            }
-            _ => None
-        };
-
-        for field in fields {
-            match struct_def {
-                Some(struct_def) => {
-                    let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
-                    for f in &fields {
-                        if generated_code(field.ident.span) {
-                            continue;
-                        }
-                        if f.name == field.ident.node.name {
-                            // We don't really need a sub-span here, but no harm done
-                            let sub_span = self.span.span_for_last_ident(field.ident.span);
-                            self.fmt.ref_str(recorder::VarRef,
-                                             field.ident.span,
-                                             sub_span,
-                                             f.id,
-                                             self.cur_scope);
-                        }
-                    }
+        if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
+            down_cast_data!(struct_lit_data, TypeRefData, self, ex.span);
+            self.fmt.ref_str(recorder::TypeRef,
+                             ex.span,
+                             Some(struct_lit_data.span),
+                             struct_lit_data.ref_id,
+                             struct_lit_data.scope);
+            let struct_def = struct_lit_data.ref_id;
+
+            for field in fields {
+                if generated_code(field.ident.span) {
+                    continue;
                 }
-                None => {}
-            }
 
-            self.visit_expr(&*field.expr)
+                let field_data = self.save_ctxt.get_field_ref_data(field,
+                                                                   struct_def,
+                                                                   self.cur_scope);
+                self.fmt.ref_str(recorder::VarRef,
+                                 field.ident.span,
+                                 Some(field_data.span),
+                                 field_data.ref_id,
+                                 field_data.scope);
+
+                self.visit_expr(&field.expr)
+            }
         }
+
         visit::walk_expr_opt(self, base)
     }
 
     fn process_method_call(&mut self,
                            ex: &ast::Expr,
                            args: &Vec<P<ast::Expr>>) {
-        let method_map = self.analysis.ty_cx.method_map.borrow();
+        let method_map = self.tcx.method_map.borrow();
         let method_callee = method_map.get(&ty::MethodCall::expr(ex.id)).unwrap();
         let (def_id, decl_id) = match method_callee.origin {
             ty::MethodStatic(def_id) |
             ty::MethodStaticClosure(def_id) => {
                 // method invoked on an object with a concrete type (not a static method)
                 let decl_id =
-                    match ty::trait_item_of_item(&self.analysis.ty_cx,
-                                                 def_id) {
+                    match ty::trait_item_of_item(self.tcx, def_id) {
                         None => None,
                         Some(decl_id) => Some(decl_id.def_id()),
                     };
 
                 // This incantation is required if the method referenced is a
                 // trait's default implementation.
-                let def_id = match ty::impl_or_trait_item(&self.analysis
-                                                               .ty_cx,
-                                                          def_id) {
+                let def_id = match ty::impl_or_trait_item(self.tcx, def_id) {
                     ty::MethodTraitItem(method) => {
                         method.provided_source.unwrap_or(def_id)
                     }
@@ -984,14 +915,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             }
             ty::MethodTypeParam(ref mp) => {
                 // method invoked on a type parameter
-                let trait_item = ty::trait_item(&self.analysis.ty_cx,
+                let trait_item = ty::trait_item(self.tcx,
                                                 mp.trait_ref.def_id,
                                                 mp.method_num);
                 (None, Some(trait_item.def_id()))
             }
             ty::MethodTraitObject(ref mo) => {
                 // method invoked on a trait instance
-                let trait_item = ty::trait_item(&self.analysis.ty_cx,
+                let trait_item = ty::trait_item(self.tcx,
                                                 mo.trait_ref.def_id,
                                                 mo.method_num);
                 (None, Some(trait_item.def_id()))
@@ -1005,7 +936,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                self.cur_scope);
 
         // walk receiver and args
-        visit::walk_exprs(self, &args[..]);
+        visit::walk_exprs(self, &args);
     }
 
     fn process_pat(&mut self, p:&ast::Pat) {
@@ -1017,12 +948,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             ast::PatStruct(ref path, ref fields, _) => {
                 visit::walk_path(self, path);
 
-                let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def();
+                let def = self.tcx.def_map.borrow().get(&p.id).unwrap().full_def();
                 let struct_def = match def {
                     def::DefConst(..) | def::DefAssociatedConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
                     _ => {
-                        match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) {
+                        match ty::ty_to_def_id(ty::node_id_to_type(self.tcx, p.id)) {
                             None => {
                                 self.sess.span_bug(p.span,
                                                    &format!("Could not find struct_def for `{}`",
@@ -1034,7 +965,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                 };
 
                 if let Some(struct_def) = struct_def {
-                    let struct_fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
+                    let struct_fields = ty::lookup_struct_fields(self.tcx, struct_def);
                     for &Spanned { node: ref field, span } in fields {
                         let sub_span = self.span.span_for_first_ident(span);
                         for f in &struct_fields {
@@ -1164,10 +1095,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                                           item.id,
                                           cnum,
                                           name,
-                                          &location[..],
+                                          &location,
                                           self.cur_scope);
             }
-            ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
+            ast::ItemFn(ref decl, _, _, _, ref ty_params, ref body) =>
                 self.process_fn(item, &**decl, ty_params, &**body),
             ast::ItemStatic(ref typ, _, ref expr) =>
                 self.process_static_or_const_item(item, typ, expr),
@@ -1183,21 +1114,24 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 self.process_impl(item,
                                   ty_params,
                                   trait_ref,
-                                  &**typ,
+                                  &typ,
                                   impl_items)
             }
             ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
-            ast::ItemMod(ref m) => self.process_mod(item, m),
+            ast::ItemMod(ref m) => {
+                self.process_mod(item);
+                self.nest(item.id, |v| visit::walk_mod(v, m));
+            }
             ast::ItemTy(ref ty, ref ty_params) => {
-                let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+                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[..]);
+                                     &qualname,
+                                     &value);
 
                 self.visit_ty(&**ty);
                 self.process_generic_params(ty_params, item.span, &qualname, item.id);
@@ -1208,8 +1142,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
     }
 
     fn visit_generics(&mut self, generics: &ast::Generics) {
-        for param in &*generics.ty_params {
-            for bound in &*param.bounds {
+        for param in generics.ty_params.iter() {
+            for bound in param.bounds.iter() {
                 if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
                     self.process_trait_ref(&trait_ref.trait_ref);
                 }
@@ -1295,30 +1229,20 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
             ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
-            ast::ExprField(ref sub_ex, ident) => {
+            ast::ExprField(ref sub_ex, _) => {
                 if generated_code(sub_ex.span) {
                     return
                 }
 
-                self.visit_expr(&**sub_ex);
-                let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, &**sub_ex).sty;
-                match *ty {
-                    ty::ty_struct(def_id, _) => {
-                        let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, def_id);
-                        for f in &fields {
-                            if f.name == ident.node.name {
-                                let sub_span = self.span.span_for_last_ident(ex.span);
-                                self.fmt.ref_str(recorder::VarRef,
-                                                 ex.span,
-                                                 sub_span,
-                                                 f.id,
-                                                 self.cur_scope);
-                                break;
-                            }
-                        }
-                    }
-                    _ => self.sess.span_bug(ex.span,
-                                            &format!("Expected struct type, found {:?}", ty)),
+                self.visit_expr(&sub_ex);
+
+                if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
+                    down_cast_data!(field_data, VariableRefData, self, ex.span);
+                    self.fmt.ref_str(recorder::VarRef,
+                                     ex.span,
+                                     Some(field_data.span),
+                                     field_data.ref_id,
+                                     field_data.scope);
                 }
             },
             ast::ExprTupField(ref sub_ex, idx) => {
@@ -1328,10 +1252,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
 
                 self.visit_expr(&**sub_ex);
 
-                let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, &**sub_ex).sty;
+                let ty = &ty::expr_ty_adjusted(self.tcx, &**sub_ex).sty;
                 match *ty {
-                    ty::ty_struct(def_id, _) => {
-                        let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, def_id);
+                    ty::TyStruct(def_id, _) => {
+                        let fields = ty::lookup_struct_fields(self.tcx, def_id);
                         for (i, f) in fields.iter().enumerate() {
                             if i == idx.node {
                                 let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
@@ -1344,7 +1268,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                             }
                         }
                     }
-                    ty::ty_tup(_) => {}
+                    ty::TyTuple(_) => {}
                     _ => self.sess.span_bug(ex.span,
                                             &format!("Expected struct or tuple \
                                                       type, found {:?}", ty)),
@@ -1355,9 +1279,9 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                     return
                 }
 
-                let mut id = String::from_str("$");
+                let mut id = String::from("$");
                 id.push_str(&ex.id.to_string());
-                self.process_formals(&decl.inputs, &id[..]);
+                self.process_formals(&decl.inputs, &id);
 
                 // walk arg and return types
                 for arg in &decl.inputs {
@@ -1397,7 +1321,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
         let mut paths_to_process = vec![];
         // process collected paths
         for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
-            let def_map = self.analysis.ty_cx.def_map.borrow();
+            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",
@@ -1417,7 +1341,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                                           Some(p.span),
                                           id,
                                           &path_to_string(p),
-                                          &value[..],
+                                          &value,
                                           "")
                 }
                 def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => {
@@ -1465,8 +1389,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
             } else {
                 "<mutable>".to_string()
             };
-            let types = self.analysis.ty_cx.node_types();
-            let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap());
+            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);
@@ -1475,8 +1399,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                                   sub_span,
                                   id,
                                   &path_to_string(p),
-                                  &value[..],
-                                  &typ[..]);
+                                  &value,
+                                  &typ);
         }
 
         // Just walk the initialiser and type (don't want to walk the pattern again).
index c5c4a75ef823bcae29a0567985f4f066db5085fd..fdfb101ed78cc4be6485a13a7caa40a30869469d 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use session::Session;
 use middle::ty;
+use middle::def;
 
 use std::env;
 use std::fs::{self, File};
@@ -23,17 +23,16 @@ use syntax::parse::token::{self, get_ident, keywords};
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::ty_to_string;
 
-
 use self::span_utils::SpanUtils;
 
+
 mod span_utils;
 mod recorder;
 
 mod dump_csv;
 
 pub struct SaveContext<'l, 'tcx: 'l> {
-    sess: &'l Session,
-    analysis: &'l ty::CrateAnalysis<'tcx>,
+    tcx: &'l ty::ctxt<'tcx>,
     span_utils: SpanUtils<'l>,
 }
 
@@ -44,14 +43,28 @@ pub struct CrateData {
 
 /// Data for any entity in the Rust language. The actual data contained varied
 /// with the kind of entity being queried. See the nested structs for details.
+#[derive(Debug)]
 pub enum Data {
     /// Data for all kinds of functions and methods.
     FunctionData(FunctionData),
-    /// Data for local and global variables (consts and statics).
+    /// Data for local and global variables (consts and statics), and fields.
     VariableData(VariableData),
+    /// Data for modules.
+    ModData(ModData),
+    /// Data for Enums.
+    EnumData(EnumData),
+    /// Data for impls.
+    ImplData(ImplData),
+
+    /// Data for the use of some variable (e.g., the use of a local variable, which
+    /// will refere to that variables declaration).
+    VariableRefData(VariableRefData),
+    /// Data for a reference to a type or trait.
+    TypeRefData(TypeRefData),
 }
 
 /// Data for all kinds of functions and methods.
+#[derive(Debug)]
 pub struct FunctionData {
     pub id: NodeId,
     pub name: String,
@@ -62,6 +75,7 @@ pub struct FunctionData {
 }
 
 /// Data for local and global variables (consts and statics).
+#[derive(Debug)]
 pub struct VariableData {
     pub id: NodeId,
     pub name: String,
@@ -72,14 +86,64 @@ pub struct VariableData {
     pub type_value: String,
 }
 
+/// Data for modules.
+#[derive(Debug)]
+pub struct ModData {
+    pub id: NodeId,
+    pub name: String,
+    pub qualname: String,
+    pub span: Span,
+    pub scope: NodeId,
+    pub filename: String,
+}
+
+/// Data for enum declarations.
+#[derive(Debug)]
+pub struct EnumData {
+    pub id: NodeId,
+    pub value: String,
+    pub qualname: String,
+    pub span: Span,
+    pub scope: NodeId,
+}
+
+#[derive(Debug)]
+pub struct ImplData {
+    pub id: NodeId,
+    pub span: Span,
+    pub scope: NodeId,
+    // FIXME: I'm not really sure inline data is the best way to do this. Seems
+    // OK in this case, but generalising leads to returning chunks of AST, which
+    // feels wrong.
+    pub trait_ref: Option<TypeRefData>,
+    pub self_ref: Option<TypeRefData>,
+}
+
+/// Data for the use of some item (e.g., the use of a local variable, which
+/// will refere to that variables declaration (by ref_id)).
+#[derive(Debug)]
+pub struct VariableRefData {
+    pub name: String,
+    pub span: Span,
+    pub scope: NodeId,
+    pub ref_id: DefId,
+}
+
+/// Data for a reference to a type or trait.
+#[derive(Debug)]
+pub struct TypeRefData {
+    pub span: Span,
+    pub scope: NodeId,
+    pub ref_id: DefId,
+}
+
+
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
-    pub fn new(sess: &'l Session,
-               analysis: &'l ty::CrateAnalysis<'tcx>,
+    pub fn new(tcx: &'l ty::ctxt<'tcx>,
                span_utils: SpanUtils<'l>)
                -> SaveContext<'l, 'tcx> {
         SaveContext {
-            sess: sess,
-            analysis: analysis,
+            tcx: tcx,
             span_utils: span_utils,
         }
     }
@@ -88,7 +152,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_external_crates(&self) -> Vec<CrateData> {
         let mut result = Vec::new();
 
-        self.sess.cstore.iter_crate_data(|n, cmd| {
+        self.tcx.sess.cstore.iter_crate_data(|n, cmd| {
             result.push(CrateData { name: cmd.name.clone(), number: n });
         });
 
@@ -97,8 +161,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     pub fn get_item_data(&self, item: &ast::Item) -> Data {
         match item.node {
-            ast::Item_::ItemFn(..) => {
-                let name = self.analysis.ty_cx.map.path_to_string(item.id);
+            ast::ItemFn(..) => {
+                let name = self.tcx.map.path_to_string(item.id);
                 let qualname = format!("::{}", name);
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
 
@@ -108,15 +172,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     qualname: qualname,
                     declaration: None,
                     span: sub_span.unwrap(),
-                    scope: self.analysis.ty_cx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_parent(item.id),
                 })
             }
             ast::ItemStatic(ref typ, mt, ref expr) => {
-                let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+                let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
 
                 // If the variable is immutable, save the initialising expression.
                 let (value, keyword) = match mt {
-                    ast::MutMutable => (String::from_str("<mutable>"), keywords::Mut),
+                    ast::MutMutable => (String::from("<mutable>"), keywords::Mut),
                     ast::MutImmutable => (self.span_utils.snippet(expr.span), keywords::Static),
                 };
 
@@ -127,13 +191,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     name: get_ident(item.ident).to_string(),
                     qualname: qualname,
                     span: sub_span.unwrap(),
-                    scope: self.analysis.ty_cx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_parent(item.id),
                     value: value,
                     type_value: ty_to_string(&typ),
                 })
             }
             ast::ItemConst(ref typ, ref expr) => {
-                let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+                let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
                 let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const);
 
                 Data::VariableData(VariableData {
@@ -141,11 +205,75 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     name: get_ident(item.ident).to_string(),
                     qualname: qualname,
                     span: sub_span.unwrap(),
-                    scope: self.analysis.ty_cx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_parent(item.id),
                     value: self.span_utils.snippet(expr.span),
                     type_value: ty_to_string(&typ),
                 })
             }
+            ast::ItemMod(ref m) => {
+                let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
+
+                let cm = self.tcx.sess.codemap();
+                let filename = cm.span_to_filename(m.inner);
+
+                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod);
+
+                Data::ModData(ModData {
+                    id: item.id,
+                    name: get_ident(item.ident).to_string(),
+                    qualname: qualname,
+                    span: sub_span.unwrap(),
+                    scope: self.tcx.map.get_parent(item.id),
+                    filename: filename,
+                })
+            },
+            ast::ItemEnum(..) => {
+                let enum_name = format!("::{}", self.tcx.map.path_to_string(item.id));
+                let val = self.span_utils.snippet(item.span);
+                let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Enum);
+
+                Data::EnumData(EnumData {
+                    id: item.id,
+                    value: val,
+                    span: sub_span.unwrap(),
+                    qualname: enum_name,
+                    scope: self.tcx.map.get_parent(item.id),
+                })
+            },
+            ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
+                let mut type_data = None;
+                let sub_span;
+
+                let parent = self.tcx.map.get_parent(item.id);
+
+                match typ.node {
+                    // 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,
+                        });
+                    },
+                    _ => {
+                        // Less useful case, impl for a compound type.
+                        let span = typ.span;
+                        sub_span = self.span_utils.sub_span_for_type_name(span).unwrap_or(span);
+                    }
+                }
+
+                let trait_data =
+                    trait_ref.as_ref().and_then(|tr| self.get_trait_ref_data(tr, parent));
+
+                Data::ImplData(ImplData {
+                    id: item.id,
+                    span: sub_span,
+                    scope: parent,
+                    trait_ref: trait_data,
+                    self_ref: type_data,
+                })
+            }
             _ => {
                 // FIXME
                 unimplemented!();
@@ -153,10 +281,145 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         }
     }
 
+    // FIXME: we ought to be able to get the parent id ourselves, but we can't
+    // for now.
+    pub fn get_field_data(&self, field: &ast::StructField, parent: NodeId) -> Option<Data> {
+        match field.node.kind {
+            ast::NamedField(ident, _) => {
+                let name = get_ident(ident);
+                let qualname = format!("::{}::{}",
+                                       self.tcx.map.path_to_string(parent),
+                                       name);
+                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(Data::VariableData(VariableData {
+                    id: field.node.id,
+                    name: get_ident(ident).to_string(),
+                    qualname: qualname,
+                    span: sub_span.unwrap(),
+                    scope: parent,
+                    value: "".to_owned(),
+                    type_value: typ,
+                }))
+            },
+            _ => None,
+        }
+    }
+
+    // FIXME: we ought to be able to get the parent id ourselves, but we can't
+    // for now.
+    pub fn get_trait_ref_data(&self,
+                              trait_ref: &ast::TraitRef,
+                              parent: NodeId)
+                              -> Option<TypeRefData> {
+        self.lookup_ref_id(trait_ref.ref_id).map(|def_id| {
+            let span = trait_ref.path.span;
+            let sub_span = self.span_utils.sub_span_for_type_name(span).unwrap_or(span);
+            TypeRefData {
+                span: sub_span,
+                scope: parent,
+                ref_id: def_id,
+            }
+        })
+    }
+
+    pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
+        match expr.node {
+            ast::ExprField(ref sub_ex, ident) => {
+                let ty = &ty::expr_ty_adjusted(self.tcx, &sub_ex).sty;
+                match *ty {
+                    ty::TyStruct(def_id, _) => {
+                        let fields = ty::lookup_struct_fields(self.tcx, def_id);
+                        for f in &fields {
+                            if f.name == ident.node.name {
+                                let sub_span = self.span_utils.span_for_last_ident(expr.span);
+                                return Some(Data::VariableRefData(VariableRefData {
+                                    name: get_ident(ident.node).to_string(),
+                                    span: sub_span.unwrap(),
+                                    scope: self.tcx.map.get_parent(expr.id),
+                                    ref_id: f.id,
+                                }));
+                            }
+                        }
+
+                        self.tcx.sess.span_bug(expr.span,
+                                               &format!("Couldn't find field {} on {:?}",
+                                                        &get_ident(ident.node), ty))
+                    }
+                    _ => {
+                        debug!("Expected struct type, found {:?}", ty);
+                        None
+                    }
+                }
+            }
+            ast::ExprStruct(ref path, _, _) => {
+                let ty = &ty::expr_ty_adjusted(&self.tcx, expr).sty;
+                match *ty {
+                    ty::TyStruct(def_id, _) => {
+                        let sub_span = self.span_utils.span_for_last_ident(path.span);
+                        Some(Data::TypeRefData(TypeRefData {
+                            span: sub_span.unwrap(),
+                            scope: self.tcx.map.get_parent(expr.id),
+                            ref_id: def_id,
+                        }))
+                    }
+                    _ => {
+                        // FIXME ty could legitimately be a TyEnum, but then we will fail
+                        // later if we try to look up the fields.
+                        debug!("expected TyStruct, found {:?}", ty);
+                        None
+                    }
+                }
+            }
+            _ => {
+                // FIXME
+                unimplemented!();
+            }
+        }
+    }
+
+    pub fn get_field_ref_data(&self,
+                              field_ref: &ast::Field,
+                              struct_id: DefId,
+                              parent: NodeId)
+                              -> VariableRefData {
+        let fields = ty::lookup_struct_fields(&self.tcx, struct_id);
+        let field_name = get_ident(field_ref.ident.node).to_string();
+        for f in &fields {
+            if f.name == field_ref.ident.node.name {
+                // We don't really need a sub-span here, but no harm done
+                let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
+                return VariableRefData {
+                    name: field_name,
+                    span: sub_span.unwrap(),
+                    scope: parent,
+                    ref_id: f.id,
+                };
+            }
+        }
+
+        self.tcx.sess.span_bug(field_ref.span,
+                               &format!("Couldn't find field {}", field_name));
+    }
+
     pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
         // FIXME
         unimplemented!();
     }
+
+    fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
+        if !self.tcx.def_map.borrow().contains_key(&ref_id) {
+            self.tcx.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
+                                       ref_id));
+        }
+        let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
+        match def {
+            def::DefPrimTy(_) => None,
+            _ => Some(def.def_id()),
+        }
+    }
+
 }
 
 // An AST visitor for collecting paths from patterns.
@@ -184,7 +447,7 @@ impl<'v> Visitor<'v> for PathCollector {
                 self.collected_paths.push((p.id,
                                            path.clone(),
                                            ast::MutMutable,
-                                           recorder::StructRef));
+                                           recorder::TypeRef));
             }
             ast::PatEnum(ref path, _) |
             ast::PatQPath(_, ref path) => {
@@ -213,10 +476,10 @@ impl<'v> Visitor<'v> for PathCollector {
 }
 
 #[allow(deprecated)]
-pub fn process_crate(sess: &Session,
-                     krate: &ast::Crate,
+pub fn process_crate(tcx: &ty::ctxt,
                      analysis: &ty::CrateAnalysis,
                      odir: Option<&Path>) {
+    let krate = tcx.map.krate();
     if generated_code(krate.span) {
         return;
     }
@@ -226,7 +489,7 @@ pub fn process_crate(sess: &Session,
         Some(name) => name.to_string(),
         None => {
             info!("Could not find crate name, using 'unknown_crate'");
-            String::from_str("unknown_crate")
+            String::from("unknown_crate")
         },
     };
 
@@ -241,10 +504,9 @@ pub fn process_crate(sess: &Session,
         },
     };
 
-    match fs::create_dir_all(&root_path) {
-        Err(e) => sess.err(&format!("Could not create directory {}: {}",
-                           root_path.display(), e)),
-        _ => (),
+    if let Err(e) = fs::create_dir_all(&root_path) {
+        tcx.sess.err(&format!("Could not create directory {}: {}",
+                              root_path.display(), e));
     }
 
     {
@@ -260,14 +522,14 @@ pub fn process_crate(sess: &Session,
         Ok(f) => box f,
         Err(e) => {
             let disp = root_path.display();
-            sess.fatal(&format!("Could not open {}: {}", disp, e));
+            tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
         }
     };
     root_path.pop();
 
-    let mut visitor = dump_csv::DumpCsvVisitor::new(sess, analysis, output_file);
+    let mut visitor = dump_csv::DumpCsvVisitor::new(tcx, analysis, output_file);
 
-    visitor.dump_crate_info(&cratename[..], krate);
+    visitor.dump_crate_info(&cratename, krate);
     visit::walk_crate(&mut visitor, krate);
 }
 
index 193902d981d690b30cf3795d6f58af419818038e..c53fa22a2c196d9ab21c30c56f034b5871dbcef0 100644 (file)
@@ -89,7 +89,6 @@ pub enum Row {
     ModRef,
     VarRef,
     TypeRef,
-    StructRef,
     FnRef,
 }
 
@@ -150,9 +149,6 @@ impl<'a> FmtStrs<'a> {
             TypeRef => ("type_ref",
                         vec!("refid","refidcrate","qualname","scopeid"),
                         true, true),
-            StructRef => ("struct_ref",
-                          vec!("refid","refidcrate","qualname","scopeid"),
-                          true, true),
             FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
         }
     }
@@ -178,7 +174,7 @@ impl<'a> FmtStrs<'a> {
         });
 
         let pairs = fields.iter().zip(values);
-        let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from_str(v))));
+        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
@@ -207,7 +203,7 @@ impl<'a> FmtStrs<'a> {
             None => return,
         };
 
-        let mut result = String::from_str(label);
+        let mut result = String::from(label);
         result.push_str(&values_str[..]);
         result.push_str("\n");
         self.recorder.record(&result[..]);
@@ -269,7 +265,7 @@ impl<'a> FmtStrs<'a> {
         // the local case they can be overridden in one block and there is no nice way
         // to refer to such a scope in english, so we just hack it by appending the
         // variable def's node id
-        let mut qualname = String::from_str(name);
+        let mut qualname = String::from(name);
         qualname.push_str("$");
         qualname.push_str(&id.to_string());
         self.check_and_record(Variable,
@@ -286,7 +282,7 @@ impl<'a> FmtStrs<'a> {
                       fn_name: &str,
                       name: &str,
                       typ: &str) {
-        let mut qualname = String::from_str(fn_name);
+        let mut qualname = String::from(fn_name);
         qualname.push_str("::");
         qualname.push_str(name);
         self.check_and_record(Variable,
index c3ac805af27ec1fcd6b5d684af0f353cb987b93d..08cbd777c095cdefc09644f86761b0c7b4ffb050 100644 (file)
@@ -83,7 +83,7 @@ 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_str("<anon-dxr>"),
+        let filemap = self.sess.codemap().new_filemap(String::from("<anon-dxr>"),
                                                       self.snippet(span));
         let s = self.sess;
         lexer::StringReader::new(s.diagnostic(), filemap)
index 84d464e8f07814d4f72d12ec6f7d5a55625c0ac0..4df10ee3d098e82efcb7b789c71944e9c811df6a 100644 (file)
@@ -217,10 +217,11 @@ use middle::ty::{self, Ty};
 use session::config::{NoDebugInfo, FullDebugInfo};
 use util::common::indenter;
 use util::nodemap::FnvHashMap;
-use util::ppaux::{Repr, vec_map_to_string};
+use util::ppaux;
 
 use std;
 use std::cmp::Ordering;
+use std::fmt;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::ast::{DUMMY_NODE_ID, NodeId};
@@ -233,7 +234,8 @@ struct ConstantExpr<'a>(&'a ast::Expr);
 
 impl<'a> ConstantExpr<'a> {
     fn eq(self, other: ConstantExpr<'a>, tcx: &ty::ctxt) -> bool {
-        match const_eval::compare_lit_exprs(tcx, self.0, other.0, None) {
+        match const_eval::compare_lit_exprs(tcx, self.0, other.0, None,
+                                            |id| {ty::node_id_item_substs(tcx, id).substs}) {
             Some(result) => result == Ordering::Equal,
             None => panic!("compare_list_exprs: type mismatch"),
         }
@@ -278,14 +280,14 @@ impl<'a, 'tcx> Opt<'a, 'tcx> {
         match *self {
             ConstantValue(ConstantExpr(lit_expr), _) => {
                 let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id);
-                let (llval, _) = consts::const_expr(ccx, &*lit_expr, bcx.fcx.param_substs);
+                let (llval, _) = consts::const_expr(ccx, &*lit_expr, bcx.fcx.param_substs, None);
                 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);
-                let (l2, _) = consts::const_expr(ccx, &**l2, bcx.fcx.param_substs);
+                let (l1, _) = consts::const_expr(ccx, &**l1, bcx.fcx.param_substs, None);
+                let (l2, _) = consts::const_expr(ccx, &**l2, bcx.fcx.param_substs, None);
                 RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
             }
             Variant(disr_val, ref repr, _, _) => {
@@ -370,13 +372,13 @@ struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
     pat_renaming_map: Option<&'a FnvHashMap<(NodeId, Span), NodeId>>
 }
 
-impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        if tcx.sess.verbose() {
+impl<'a, 'p, 'blk, 'tcx> fmt::Debug for Match<'a, 'p, 'blk, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if ppaux::verbose() {
             // for many programs, this just take too long to serialize
-            self.pats.repr(tcx)
+            write!(f, "{:?}", self.pats)
         } else {
-            format!("{} pats", self.pats.len())
+            write!(f, "{} pats", self.pats.len())
         }
     }
 }
@@ -396,9 +398,9 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                               col: usize,
                                               val: ValueRef)
                                               -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
-    debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
+    debug!("expand_nested_bindings(bcx={}, m={:?}, col={}, val={})",
            bcx.to_str(),
-           m.repr(bcx.tcx()),
+           m,
            col,
            bcx.val_to_string(val));
     let _indenter = indenter();
@@ -436,9 +438,9 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                                           -> Vec<Match<'a, 'p, 'blk, 'tcx>> where
     F: FnMut(&[&'p ast::Pat]) -> Option<Vec<&'p ast::Pat>>,
 {
-    debug!("enter_match(bcx={}, m={}, col={}, val={})",
+    debug!("enter_match(bcx={}, m={:?}, col={}, val={})",
            bcx.to_str(),
-           m.repr(bcx.tcx()),
+           m,
            col,
            bcx.val_to_string(val));
     let _indenter = indenter();
@@ -479,9 +481,9 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      col: usize,
                                      val: ValueRef)
                                      -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
-    debug!("enter_default(bcx={}, m={}, col={}, val={})",
+    debug!("enter_default(bcx={}, m={:?}, col={}, val={})",
            bcx.to_str(),
-           m.repr(bcx.tcx()),
+           m,
            col,
            bcx.val_to_string(val));
     let _indenter = indenter();
@@ -536,9 +538,9 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
              variant_size: usize,
              val: ValueRef)
              -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
-    debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
+    debug!("enter_opt(bcx={}, m={:?}, opt={:?}, col={}, val={})",
            bcx.to_str(),
-           m.repr(bcx.tcx()),
+           m,
            *opt,
            col,
            bcx.val_to_string(val));
@@ -824,22 +826,13 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                -> Result<'blk, 'tcx> {
         let did = langcall(cx,
                            None,
-                           &format!("comparison of `{}`",
-                                   cx.ty_to_string(rhs_t)),
+                           &format!("comparison of `{}`", rhs_t),
                            StrEqFnLangItem);
-        let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable);
-        // The comparison function gets the slices by value, so we have to make copies here. Even
-        // if the function doesn't write through the pointer, things like lifetime intrinsics
-        // require that we do this properly
-        let lhs_arg = alloc_ty(cx, t, "lhs");
-        let rhs_arg = alloc_ty(cx, t, "rhs");
-        memcpy_ty(cx, lhs_arg, lhs, t);
-        memcpy_ty(cx, rhs_arg, rhs, t);
-        let res = callee::trans_lang_call(cx, did, &[lhs_arg, rhs_arg], None, debug_loc);
-        call_lifetime_end(res.bcx, lhs_arg);
-        call_lifetime_end(res.bcx, rhs_arg);
-
-        res
+        let lhs_data = Load(cx, expr::get_dataptr(cx, lhs));
+        let lhs_len = Load(cx, expr::get_len(cx, lhs));
+        let rhs_data = Load(cx, expr::get_dataptr(cx, rhs));
+        let rhs_len = Load(cx, expr::get_len(cx, rhs));
+        callee::trans_lang_call(cx, did, &[lhs_data, lhs_len, rhs_data, rhs_len], None, debug_loc)
     }
 
     let _icx = push_ctxt("compare_values");
@@ -849,10 +842,10 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     }
 
     match rhs_t.sty {
-        ty::ty_rptr(_, mt) => match mt.ty.sty {
-            ty::ty_str => compare_str(cx, lhs, rhs, rhs_t, debug_loc),
-            ty::ty_vec(ty, _) => match ty.sty {
-                ty::ty_uint(ast::TyU8) => {
+        ty::TyRef(_, mt) => match mt.ty.sty {
+            ty::TyStr => compare_str(cx, lhs, rhs, rhs_t, debug_loc),
+            ty::TyArray(ty, _) | ty::TySlice(ty) => match ty.sty {
+                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();
@@ -936,11 +929,11 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      chk: &FailureHandler,
                                      has_genuine_default: bool)
                                      -> Block<'blk, 'tcx> {
-    debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
+    debug!("compile_guard(bcx={}, guard_expr={:?}, m={:?}, vals=[{}])",
            bcx.to_str(),
-           bcx.expr_to_string(guard_expr),
-           m.repr(bcx.tcx()),
-           vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
+           guard_expr,
+           m,
+           vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().connect(", "));
     let _indenter = indenter();
 
     let mut bcx = insert_lllocals(bcx, &data.bindings_map, None);
@@ -982,10 +975,10 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         vals: &[ValueRef],
                                         chk: &FailureHandler,
                                         has_genuine_default: bool) {
-    debug!("compile_submatch(bcx={}, m={}, vals={})",
+    debug!("compile_submatch(bcx={}, m={:?}, vals=[{}])",
            bcx.to_str(),
-           m.repr(bcx.tcx()),
-           vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
+           m,
+           vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().connect(", "));
     let _indenter = indenter();
     let _icx = push_ctxt("match::compile_submatch");
     let mut bcx = bcx;
@@ -1091,7 +1084,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         ).collect();
 
         match left_ty.sty {
-            ty::ty_struct(def_id, substs) if !type_is_sized(bcx.tcx(), left_ty) => {
+            ty::TyStruct(def_id, substs) if !type_is_sized(bcx.tcx(), left_ty) => {
                 // The last field is technically unsized but
                 // since we can only ever match that field behind
                 // a reference we construct a fat ptr here.
@@ -1115,7 +1108,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         Some(vec!(Load(bcx, val)))
     } else {
         match left_ty.sty {
-            ty::ty_vec(_, Some(n)) => {
+            ty::TyArray(_, n) => {
                 let args = extract_vec_elems(bcx, left_ty, n, 0, val);
                 Some(args.vals)
             }
@@ -1500,7 +1493,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     };
 
     let mut matches = Vec::new();
-    for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) {
+    for (arm_data, pats) in arm_datas.iter().zip(&arm_pats) {
         matches.extend(pats.iter().map(|p| Match {
             pats: vec![&**p],
             data: arm_data,
@@ -1695,13 +1688,13 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     val: ValueRef,
                                     cleanup_scope: cleanup::ScopeId)
                                     -> Block<'blk, 'tcx> {
-    debug!("bind_irrefutable_pat(bcx={}, pat={})",
+    debug!("bind_irrefutable_pat(bcx={}, pat={:?})",
            bcx.to_str(),
-           pat.repr(bcx.tcx()));
+           pat);
 
     if bcx.sess().asm_comments() {
-        add_comment(bcx, &format!("bind_irrefutable_pat(pat={})",
-                                 pat.repr(bcx.tcx())));
+        add_comment(bcx, &format!("bind_irrefutable_pat(pat={:?})",
+                                 pat));
     }
 
     let _indenter = indenter();
@@ -1832,7 +1825,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 .iter()
                 .chain(slice.iter())
                 .chain(after.iter())
-                .zip(extracted.vals.into_iter())
+                .zip(extracted.vals)
                 .fold(bcx, |bcx, (inner, elem)|
                     bind_irrefutable_pat(bcx, &**inner, elem, cleanup_scope)
                 );
index 17c9fa248180c01ddd8dd3b57db8ebd8dac6154e..2a1c2457b9d32d5a6d7d287a07710698809ae5a8 100644 (file)
@@ -66,7 +66,6 @@ use trans::machine;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
-use util::ppaux::ty_to_string;
 
 type Hint = attr::ReprAttr;
 
@@ -143,7 +142,7 @@ pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                 t: Ty<'tcx>)
                                 -> Rc<Repr<'tcx>> {
-    debug!("Representing: {}", ty_to_string(cx.tcx(), t));
+    debug!("Representing: {}", t);
     match cx.adt_reprs().borrow().get(&t) {
         Some(repr) => return repr.clone(),
         None => {}
@@ -206,10 +205,10 @@ fn dtor_active(flag: u8) -> bool {
 fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                      t: Ty<'tcx>) -> Repr<'tcx> {
     match t.sty {
-        ty::ty_tup(ref elems) => {
+        ty::TyTuple(ref elems) => {
             Univariant(mk_struct(cx, &elems[..], false, t), 0)
         }
-        ty::ty_struct(def_id, substs) => {
+        ty::TyStruct(def_id, substs) => {
             let fields = ty::lookup_struct_fields(cx.tcx(), def_id);
             let mut ftys = fields.iter().map(|field| {
                 let fty = ty::lookup_field_type(cx.tcx(), def_id, field.id, substs);
@@ -223,13 +222,13 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
         }
-        ty::ty_closure(def_id, substs) => {
+        ty::TyClosure(def_id, substs) => {
             let typer = NormalizingClosureTyper::new(cx.tcx());
             let upvars = typer.closure_upvars(def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
             Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
         }
-        ty::ty_enum(def_id, substs) => {
+        ty::TyEnum(def_id, substs) => {
             let cases = get_cases(cx.tcx(), def_id, substs);
             let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).get(0)
                 .unwrap_or(&attr::ReprAny);
@@ -381,8 +380,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             General(ity, fields, dtor_to_init_u8(dtor))
         }
-        _ => cx.sess().bug(&format!("adt::represent_type called on non-ADT type: {}",
-                           ty_to_string(cx.tcx(), t)))
+        _ => cx.sess().bug(&format!("adt::represent_type called on non-ADT type: {}", t))
     }
 }
 
@@ -400,28 +398,28 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
                                     mut path: DiscrField) -> Option<DiscrField> {
     match ty.sty {
         // Fat &T/&mut T/Box<T> i.e. T is [T], str, or Trait
-        ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !type_is_sized(tcx, ty) => {
+        ty::TyRef(_, ty::mt { ty, .. }) | ty::TyBox(ty) if !type_is_sized(tcx, ty) => {
             path.push(FAT_PTR_ADDR);
             Some(path)
         },
 
         // Regular thin pointer: &T/&mut T/Box<T>
-        ty::ty_rptr(..) | ty::ty_uniq(..) => Some(path),
+        ty::TyRef(..) | ty::TyBox(..) => Some(path),
 
         // Functions are just pointers
-        ty::ty_bare_fn(..) => Some(path),
+        ty::TyBareFn(..) => Some(path),
 
         // Is this the NonZero lang item wrapping a pointer or integer type?
-        ty::ty_struct(did, substs) if Some(did) == tcx.lang_items.non_zero() => {
+        ty::TyStruct(did, substs) if Some(did) == tcx.lang_items.non_zero() => {
             let nonzero_fields = ty::lookup_struct_fields(tcx, did);
             assert_eq!(nonzero_fields.len(), 1);
             let nonzero_field = ty::lookup_field_type(tcx, did, nonzero_fields[0].id, substs);
             match nonzero_field.sty {
-                ty::ty_ptr(ty::mt { ty, .. }) if !type_is_sized(tcx, ty) => {
+                ty::TyRawPtr(ty::mt { ty, .. }) if !type_is_sized(tcx, ty) => {
                     path.push_all(&[0, FAT_PTR_ADDR]);
                     Some(path)
                 },
-                ty::ty_ptr(..) | ty::ty_int(..) | ty::ty_uint(..) => {
+                ty::TyRawPtr(..) | ty::TyInt(..) | ty::TyUint(..) => {
                     path.push(0);
                     Some(path)
                 },
@@ -431,7 +429,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
 
         // Perhaps one of the fields of this struct is non-zero
         // let's recurse and find out
-        ty::ty_struct(def_id, substs) => {
+        ty::TyStruct(def_id, substs) => {
             let fields = ty::lookup_struct_fields(tcx, def_id);
             for (j, field) in fields.iter().enumerate() {
                 let field_ty = ty::lookup_field_type(tcx, def_id, field.id, substs);
@@ -445,7 +443,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
 
         // Perhaps one of the upvars of this struct is non-zero
         // Let's recurse and find out!
-        ty::ty_closure(def_id, substs) => {
+        ty::TyClosure(def_id, substs) => {
             let typer = NormalizingClosureTyper::new(tcx);
             let upvars = typer.closure_upvars(def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
@@ -460,7 +458,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
         },
 
         // Can we use one of the fields in this tuple?
-        ty::ty_tup(ref tys) => {
+        ty::TyTuple(ref tys) => {
             for (j, &ty) in tys.iter().enumerate() {
                 if let Some(mut fpath) = find_discr_field_candidate(tcx, ty, path.clone()) {
                     fpath.push(j);
@@ -472,7 +470,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
 
         // Is this a fixed-size array of something non-zero
         // with at least one element?
-        ty::ty_vec(ety, Some(d)) if d > 0 => {
+        ty::TyArray(ety, d) if d > 0 => {
             if let Some(mut vpath) = find_discr_field_candidate(tcx, ety, path) {
                 vpath.push(0);
                 Some(vpath)
@@ -795,43 +793,40 @@ pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-
+pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
+    match *r {
+        CEnum(ity, _, _) => ity.is_signed(),
+        General(ity, _, _) => ity.is_signed(),
+        Univariant(..) => false,
+        RawNullablePointer { .. } => false,
+        StructWrappedNullablePointer { .. } => false,
+    }
+}
 
 /// Obtain the actual discriminant of a value.
 pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
                                    scrutinee: ValueRef, cast_to: Option<Type>)
     -> ValueRef {
-    let signed;
-    let val;
     debug!("trans_get_discr r: {:?}", r);
-    match *r {
-        CEnum(ity, min, max) => {
-            val = load_discr(bcx, ity, scrutinee, min, max);
-            signed = ity.is_signed();
-        }
+    let val = match *r {
+        CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
         General(ity, ref cases, _) => {
             let ptr = GEPi(bcx, scrutinee, &[0, 0]);
-            val = load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr);
-            signed = ity.is_signed();
-        }
-        Univariant(..) => {
-            val = C_u8(bcx.ccx(), 0);
-            signed = false;
+            load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr)
         }
+        Univariant(..) => C_u8(bcx.ccx(), 0),
         RawNullablePointer { nndiscr, nnty, .. } =>  {
             let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
             let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
-            val = ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None);
-            signed = false;
+            ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None)
         }
         StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
-            val = struct_wrapped_nullable_bitdiscr(bcx, nndiscr, discrfield, scrutinee);
-            signed = false;
+            struct_wrapped_nullable_bitdiscr(bcx, nndiscr, discrfield, scrutinee)
         }
-    }
+    };
     match cast_to {
         None => val,
-        Some(llty) => if signed { SExt(bcx, val, llty) } else { ZExt(bcx, val, llty) }
+        Some(llty) => if is_discr_signed(r) { SExt(bcx, val, llty) } else { ZExt(bcx, val, llty) }
     }
 }
 
@@ -1032,11 +1027,26 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         }
         General(ity, ref cases, _) => {
             let ccx = bcx.ccx();
-            let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
-            Unreachable(unr_cx);
+
+            // See the comments in trans/base.rs for more information (inside
+            // iter_structural_ty), but the gist here is that if the enum's
+            // discriminant is *not* in the range that we're expecting (in which
+            // case we'll take the fall-through branch on the switch
+            // instruction) then we can't just optimize this to an Unreachable
+            // block.
+            //
+            // Currently we still have filling drop, so this means that the drop
+            // glue for enums may be called when the enum has been paved over
+            // with the "I've been dropped" value. In this case the default
+            // branch of the switch instruction will actually be taken at
+            // runtime, so the basic block isn't actually unreachable, so we
+            // need to make it do something with defined behavior. In this case
+            // we just return early from the function.
+            let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
+            RetVoid(ret_void_cx, DebugLoc::None);
 
             let discr_val = trans_get_discr(bcx, r, value, None);
-            let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
+            let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
             let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
 
             for (discr, case) in cases.iter().enumerate() {
@@ -1202,7 +1212,7 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // offset of current value
     let mut offset = 0;
     let mut cfields = Vec::new();
-    for (&val, &target_offset) in vals.iter().zip(target_offsets.iter()) {
+    for (&val, target_offset) in vals.iter().zip(target_offsets) {
         if !st.packed {
             let val_align = machine::llalign_of_min(ccx, val_ty(val));
             offset = roundup(offset, val_align);
index 27128827e267603e0a9b90c155647755093b7dd8..b25d6f2daaca93fe865bbd879895dfd488c078d5 100644 (file)
@@ -45,13 +45,12 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
         let val = out_datum.val;
         if is_rw {
-            ext_inputs.push(unpack_result!(bcx, {
-                callee::trans_arg_datum(bcx,
-                                       expr_ty(bcx, &**out),
-                                       out_datum,
-                                       cleanup::CustomScope(temp_scope),
-                                       callee::DontAutorefArg)
-            }));
+            bcx = callee::trans_arg_datum(bcx,
+                                          expr_ty(bcx, &**out),
+                                          out_datum,
+                                          cleanup::CustomScope(temp_scope),
+                                          callee::DontAutorefArg,
+                                          &mut ext_inputs);
             ext_constraints.push(i.to_string());
         }
         val
@@ -59,18 +58,18 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
     }).collect::<Vec<_>>();
 
     // Now the input operands
-    let mut inputs = ia.inputs.iter().map(|&(ref c, ref input)| {
+    let mut inputs = Vec::new();
+    for &(ref c, ref input) in &ia.inputs {
         constraints.push((*c).clone());
 
         let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
-        unpack_result!(bcx, {
-            callee::trans_arg_datum(bcx,
+        bcx = callee::trans_arg_datum(bcx,
                                     expr_ty(bcx, &**input),
                                     in_datum,
                                     cleanup::CustomScope(temp_scope),
-                                    callee::DontAutorefArg)
-        })
-    }).collect::<Vec<_>>();
+                                    callee::DontAutorefArg,
+                                    &mut inputs);
+    }
     inputs.push_all(&ext_inputs[..]);
 
     // no failure occurred preparing operands, no need to cleanup
@@ -88,7 +87,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
 
     let all_constraints= constraints.iter()
                                     .map(|s| s.to_string())
-                                    .chain(ext_constraints.into_iter())
+                                    .chain(ext_constraints)
                                     .chain(clobbers)
                                     .chain(arch_clobbers.iter()
                                                .map(|s| s.to_string()))
index 132947e34d795e052da61c5214e1960077ad4668..39e5670c975e0e040813b5ad4b8bfa46a1730a9b 100644 (file)
@@ -12,6 +12,7 @@
 use libc::{c_uint, c_ulonglong};
 use llvm::{self, ValueRef, AttrHelper};
 use middle::ty::{self, ClosureTyper};
+use session::config::NoDebugInfo;
 use syntax::abi;
 use syntax::ast;
 pub use syntax::attr::InlineAttr;
@@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
     use syntax::attr::*;
     inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
 
+    // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
+    // parameter.
+    let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
+                     !ccx.sess().target.target.options.eliminate_frame_pointer;
+    if no_fp_elim {
+        unsafe {
+            let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
+            let val = "true\0".as_ptr() as *const _;
+            llvm::LLVMAddFunctionAttrStringValue(llfn,
+                                                 llvm::FunctionIndex as c_uint,
+                                                 attr, val);
+        }
+    }
+
     for attr in attrs {
         if attr.check_name("no_stack_check") {
             split_stack(llfn, false);
@@ -128,8 +143,8 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
 
     let function_type;
     let (fn_sig, abi, env_ty) = match fn_type.sty {
-        ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None),
-        ty::ty_closure(closure_did, substs) => {
+        ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
+        ty::TyClosure(closure_did, substs) => {
             let typer = common::NormalizingClosureTyper::new(ccx.tcx());
             function_type = typer.closure_type(closure_did, substs);
             let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
@@ -146,11 +161,11 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
     // These have an odd calling convention, so we need to manually
     // unpack the input ty's
     let input_tys = match fn_type.sty {
-        ty::ty_closure(..) => {
+        ty::TyClosure(..) => {
             assert!(abi == abi::RustCall);
 
             match fn_sig.inputs[0].sty {
-                ty::ty_tup(ref inputs) => {
+                ty::TyTuple(ref inputs) => {
                     let mut full_inputs = vec![env_ty.expect("Missing closure environment")];
                     full_inputs.push_all(inputs);
                     full_inputs
@@ -158,11 +173,11 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 _ => ccx.sess().bug("expected tuple'd inputs")
             }
         },
-        ty::ty_bare_fn(..) if abi == abi::RustCall => {
+        ty::TyBareFn(..) if abi == abi::RustCall => {
             let mut inputs = vec![fn_sig.inputs[0]];
 
             match fn_sig.inputs[1].sty {
-                ty::ty_tup(ref t_in) => {
+                ty::TyTuple(ref t_in) => {
                     inputs.push_all(&t_in[..]);
                     inputs
                 }
@@ -173,7 +188,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
     };
 
     // Index 0 is the return value of the llvm func, so we start at 1
-    let mut first_arg_offset = 1;
+    let mut idx = 1;
     if let ty::FnConverging(ret_ty) = ret_ty {
         // A function pointer is called without the declaration
         // available, so we have to apply any attributes with ABI
@@ -191,14 +206,14 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                  .arg(1, llvm::DereferenceableAttribute(llret_sz));
 
             // Add one more since there's an outptr
-            first_arg_offset += 1;
+            idx += 1;
         } else {
             // The `noalias` attribute on the return value is useful to a
             // function ptr caller.
             match ret_ty.sty {
                 // `Box` pointer return values never alias because ownership
                 // is transferred
-                ty::ty_uniq(it) if common::type_is_sized(ccx.tcx(), it) => {
+                ty::TyBox(it) if common::type_is_sized(ccx.tcx(), it) => {
                     attrs.ret(llvm::Attribute::NoAlias);
                 }
                 _ => {}
@@ -207,24 +222,23 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
             // We can also mark the return value as `dereferenceable` in certain cases
             match ret_ty.sty {
                 // These are not really pointers but pairs, (pointer, len)
-                ty::ty_rptr(_, ty::mt { ty: inner, .. })
-                | ty::ty_uniq(inner) if common::type_is_sized(ccx.tcx(), inner) => {
+                ty::TyRef(_, ty::mt { ty: inner, .. })
+                | ty::TyBox(inner) if common::type_is_sized(ccx.tcx(), inner) => {
                     let llret_sz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
                     attrs.ret(llvm::DereferenceableAttribute(llret_sz));
                 }
                 _ => {}
             }
 
-            if let ty::ty_bool = ret_ty.sty {
+            if let ty::TyBool = ret_ty.sty {
                 attrs.ret(llvm::Attribute::ZExt);
             }
         }
     }
 
-    for (idx, &t) in input_tys.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
+    for &t in input_tys.iter() {
         match t.sty {
-            // this needs to be first to prevent fat pointers from falling through
-            _ if !common::type_is_immediate(ccx, t) => {
+            _ if type_of::arg_is_indirect(ccx, t) => {
                 let llarg_sz = machine::llsize_of_real(ccx, type_of::type_of(ccx, t));
 
                 // For non-immediate arguments the callee gets its own copy of
@@ -235,55 +249,69 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                      .arg(idx, llvm::DereferenceableAttribute(llarg_sz));
             }
 
-            ty::ty_bool => {
+            ty::TyBool => {
                 attrs.arg(idx, llvm::Attribute::ZExt);
             }
 
             // `Box` pointer parameters never alias because ownership is transferred
-            ty::ty_uniq(inner) => {
-                let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
-
-                attrs.arg(idx, llvm::Attribute::NoAlias)
-                     .arg(idx, llvm::DereferenceableAttribute(llsz));
+            ty::TyBox(inner) => {
+                attrs.arg(idx, llvm::Attribute::NoAlias);
+
+                if common::type_is_sized(ccx.tcx(), inner) {
+                    let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
+                    attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
+                } else {
+                    attrs.arg(idx, llvm::NonNullAttribute);
+                    if ty::type_is_trait(inner) {
+                        attrs.arg(idx + 1, llvm::NonNullAttribute);
+                    }
+                }
             }
 
-            // `&mut` pointer parameters never alias other parameters, or mutable global data
-            //
-            // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
-            // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on
-            // memory dependencies rather than pointer equality
-            ty::ty_rptr(b, mt) if mt.mutbl == ast::MutMutable ||
-                                  !ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe() => {
+            ty::TyRef(b, mt) => {
+                // `&mut` pointer parameters never alias other parameters, or mutable global data
+                //
+                // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as
+                // both `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely
+                // on memory dependencies rather than pointer equality
+                let interior_unsafe = ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe();
 
-                let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
-                attrs.arg(idx, llvm::Attribute::NoAlias)
-                     .arg(idx, llvm::DereferenceableAttribute(llsz));
+                if mt.mutbl == ast::MutMutable || !interior_unsafe {
+                    attrs.arg(idx, llvm::Attribute::NoAlias);
+                }
 
-                if mt.mutbl == ast::MutImmutable {
+                if mt.mutbl == ast::MutImmutable && !interior_unsafe {
                     attrs.arg(idx, llvm::Attribute::ReadOnly);
                 }
 
+                // & pointer parameters are also never null and for sized types we also know
+                // exactly how many bytes we can dereference
+                if common::type_is_sized(ccx.tcx(), mt.ty) {
+                    let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
+                    attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
+                } else {
+                    attrs.arg(idx, llvm::NonNullAttribute);
+                    if ty::type_is_trait(mt.ty) {
+                        attrs.arg(idx + 1, llvm::NonNullAttribute);
+                    }
+                }
+
+                // When a reference in an argument has no named lifetime, it's
+                // impossible for that reference to escape this function
+                // (returned or stored beyond the call by a closure).
                 if let ReLateBound(_, BrAnon(_)) = *b {
                     attrs.arg(idx, llvm::Attribute::NoCapture);
                 }
             }
 
-            // When a reference in an argument has no named lifetime, it's impossible for that
-            // reference to escape this function (returned or stored beyond the call by a closure).
-            ty::ty_rptr(&ReLateBound(_, BrAnon(_)), mt) => {
-                let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
-                attrs.arg(idx, llvm::Attribute::NoCapture)
-                     .arg(idx, llvm::DereferenceableAttribute(llsz));
-            }
-
-            // & pointer parameters are also never null and we know exactly how
-            // many bytes we can dereference
-            ty::ty_rptr(_, mt) => {
-                let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
-                attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
-            }
             _ => ()
         }
+
+        if common::type_is_fat_ptr(ccx.tcx(), t) {
+            idx += 2;
+        } else {
+            idx += 1;
+        }
     }
 
     attrs
index 4879975dde695c265bd7505b3e1127a0bccebf5c..461739a362d30e20f4413f23ff9af377ef79e130 100644 (file)
@@ -41,6 +41,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
 use middle::subst::Substs;
 use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size};
+use rustc::ast_map;
 use session::config::{self, NoDebugInfo};
 use session::Session;
 use trans::_match;
@@ -79,7 +80,6 @@ use trans::type_of;
 use trans::type_of::*;
 use trans::value::Value;
 use util::common::indenter;
-use util::ppaux::{Repr, ty_to_string};
 use util::sha2::Sha256;
 use util::nodemap::NodeMap;
 
@@ -99,7 +99,7 @@ use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 use syntax::visit::Visitor;
 use syntax::visit;
-use syntax::{ast, ast_util, ast_map};
+use syntax::{ast, ast_util};
 
 thread_local! {
     static TASK_LOCAL_INSN_KEY: RefCell<Option<Vec<&'static str>>> = {
@@ -232,11 +232,14 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
     // don't do this then linker errors can be generated where the linker
     // complains that one object files has a thread local version of the
     // symbol and another one doesn't.
-    for attr in &*ty::get_attrs(ccx.tcx(), did) {
+    for attr in ty::get_attrs(ccx.tcx(), did).iter() {
         if attr.check_name("thread_local") {
             llvm::set_thread_local(c, true);
         }
     }
+    if ccx.use_dll_storage_attrs() {
+        llvm::SetDLLStorageClass(c, llvm::DLLImportStorageClass);
+    }
     ccx.externs().borrow_mut().insert(name.to_string(), c);
     return c;
 }
@@ -246,9 +249,7 @@ fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match bcx.tcx().lang_items.require(it) {
         Ok(id) => id,
         Err(s) => {
-            bcx.sess().fatal(&format!("allocation of `{}` {}",
-                                     bcx.ty_to_string(info_ty),
-                                     s));
+            bcx.sess().fatal(&format!("allocation of `{}` {}", info_ty, s));
         }
     }
 }
@@ -316,7 +317,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         debug_loc: DebugLoc)
                                         -> ValueRef {
     match t.sty {
-        ty::ty_tup(ref tys) if tys.is_empty() => {
+        ty::TyTuple(ref tys) if tys.is_empty() => {
             // We don't need to do actual comparisons for nil.
             // () == () holds but () < () does not.
             match op {
@@ -326,16 +327,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator")
             }
         }
-        ty::ty_bare_fn(..) | ty::ty_bool | ty::ty_uint(_) | ty::ty_char => {
+        ty::TyBareFn(..) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
         }
-        ty::ty_ptr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
+        ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
         }
-        ty::ty_int(_) => {
+        ty::TyInt(_) => {
             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, true), lhs, rhs, debug_loc)
         }
-        ty::ty_float(_) => {
+        ty::TyFloat(_) => {
             FCmp(bcx, bin_op_to_fcmp_predicate(bcx.ccx(), op), lhs, rhs, debug_loc)
         }
         // Should never get here, because t is scalar.
@@ -351,7 +352,7 @@ pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                       debug_loc: DebugLoc)
                                       -> ValueRef {
     let signed = match t.sty {
-        ty::ty_float(_) => {
+        ty::TyFloat(_) => {
             // The comparison operators for floating point vectors are challenging.
             // LLVM outputs a `< size x i1 >`, but if we perform a sign extension
             // then bitcast to a floating point vector, the result will be `-NaN`
@@ -359,8 +360,8 @@ pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             bcx.sess().bug("compare_simd_types: comparison operators \
                             not supported for floating point SIMD types")
         },
-        ty::ty_uint(_) => false,
-        ty::ty_int(_) => true,
+        ty::TyUint(_) => false,
+        ty::TyInt(_) => true,
         _ => bcx.sess().bug("compare_simd_types: invalid SIMD type"),
     };
 
@@ -412,7 +413,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
 
     let mut cx = cx;
     match t.sty {
-      ty::ty_struct(..) => {
+      ty::TyStruct(..) => {
           let repr = adt::represent_type(cx.ccx(), t);
           expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| {
               for (i, field_ty) in field_tys.iter().enumerate() {
@@ -431,7 +432,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
               }
           })
       }
-      ty::ty_closure(def_id, substs) => {
+      ty::TyClosure(def_id, substs) => {
           let repr = adt::represent_type(cx.ccx(), t);
           let typer = common::NormalizingClosureTyper::new(cx.tcx());
           let upvars = typer.closure_upvars(def_id, substs).unwrap();
@@ -440,23 +441,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
               cx = f(cx, llupvar, upvar.ty);
           }
       }
-      ty::ty_vec(_, Some(n)) => {
+      ty::TyArray(_, n) => {
         let (base, len) = tvec::get_fixed_base_and_len(cx, data_ptr, n);
         let unit_ty = ty::sequence_element_type(cx.tcx(), t);
         cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
       }
-      ty::ty_vec(_, None) | ty::ty_str => {
+      ty::TySlice(_) | ty::TyStr => {
         let unit_ty = ty::sequence_element_type(cx.tcx(), t);
         cx = tvec::iter_vec_raw(cx, data_ptr, unit_ty, info.unwrap(), f);
       }
-      ty::ty_tup(ref args) => {
+      ty::TyTuple(ref args) => {
           let repr = adt::represent_type(cx.ccx(), t);
           for (i, arg) in args.iter().enumerate() {
               let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
               cx = f(cx, llfld_a, *arg);
           }
       }
-      ty::ty_enum(tid, substs) => {
+      ty::TyEnum(tid, substs) => {
           let fcx = cx.fcx;
           let ccx = fcx.ccx;
 
@@ -477,9 +478,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
               }
               (_match::Switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
-                  let unr_cx = fcx.new_temp_block("enum-iter-unr");
-                  Unreachable(unr_cx);
-                  let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
+
+                  // Create a fall-through basic block for the "else" case of
+                  // the switch instruction we're about to generate. Note that
+                  // we do **not** use an Unreachable instruction here, even
+                  // though most of the time this basic block will never be hit.
+                  //
+                  // When an enum is dropped it's contents are currently
+                  // overwritten to DTOR_DONE, which means the discriminant
+                  // could have changed value to something not within the actual
+                  // range of the discriminant. Currently this function is only
+                  // used for drop glue so in this case we just return quickly
+                  // from the outer function, and any other use case will only
+                  // call this for an already-valid enum in which case the `ret
+                  // void` will never be hit.
+                  let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
+                  RetVoid(ret_void_cx, DebugLoc::None);
+                  let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
                                         n_variants);
                   let next_cx = fcx.new_temp_block("enum-iter-next");
 
@@ -512,8 +527,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
           }
       }
       _ => {
-          cx.sess().unimpl(&format!("type in iter_structural_ty: {}",
-                                   ty_to_string(cx.tcx(), t)))
+          cx.sess().unimpl(&format!("type in iter_structural_ty: {}", t))
       }
     }
     return cx;
@@ -570,7 +584,7 @@ fn cast_shift_rhs<F, G>(op: ast::BinOp_,
 pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                               val_t: Ty<'tcx>) -> (Type, u64) {
     match val_t.sty {
-        ty::ty_int(t) => {
+        ty::TyInt(t) => {
             let llty = Type::int_from_ty(cx.ccx(), t);
             let min = match t {
                 ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
@@ -604,15 +618,15 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
     let debug_loc = call_info.debug_loc();
 
     let (is_zero, is_signed) = match rhs_t.sty {
-        ty::ty_int(t) => {
+        ty::TyInt(t) => {
             let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0, false);
             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), true)
         }
-        ty::ty_uint(t) => {
+        ty::TyUint(t) => {
             let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
         }
-        ty::ty_struct(_, _) if type_is_simd(cx.tcx(), rhs_t) => {
+        ty::TyStruct(_, _) if type_is_simd(cx.tcx(), rhs_t) => {
             let mut res = C_bool(cx.ccx(), false);
             for i in 0 .. simd_size(cx.tcx(), rhs_t) {
                 res = Or(cx, res,
@@ -622,8 +636,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
             (res, false)
         }
         _ => {
-            cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
-                                  ty_to_string(cx.tcx(), rhs_t)));
+            cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", rhs_t));
         }
     };
     let bcx = with_cond(cx, is_zero, |bcx| {
@@ -661,7 +674,7 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      did: ast::DefId, t: Ty<'tcx>) -> ValueRef {
     let name = csearch::get_symbol(&ccx.sess().cstore, did);
     match t.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => {
+        ty::TyBareFn(_, ref fn_ty) => {
             match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
                 Rust | RustCall => {
                     get_extern_rust_fn(ccx, t, &name[..], did)
@@ -670,7 +683,8 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     ccx.sess().bug("unexpected intrinsic in trans_external_path")
                 }
                 _ => {
-                    let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name[..]);
+                    let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi,
+                                                                 t, &name);
                     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
                     attributes::from_fn_attrs(ccx, &attrs, llfn);
                     llfn
@@ -737,7 +751,12 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn need_invoke(bcx: Block) -> bool {
-    if bcx.sess().no_landing_pads() {
+    // FIXME(#25869) currently unwinding is not implemented for MSVC and our
+    //               normal unwinding infrastructure ends up just causing linker
+    //               errors with the current LLVM implementation, so landing
+    //               pads are disabled entirely for MSVC targets
+    if bcx.sess().no_landing_pads() ||
+       bcx.sess().target.target.options.is_like_msvc {
         return false;
     }
 
@@ -781,7 +800,7 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
             let val = llvm::LLVMGetInitializer(global);
             if !val.is_null() {
-                return from_arg_ty(cx, val, t);
+                return to_arg_ty(cx, val, t);
             }
         }
     }
@@ -803,7 +822,7 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         llvm::LLVMSetAlignment(val, align);
     }
 
-    from_arg_ty(cx, val, t)
+    to_arg_ty(cx, val, t)
 }
 
 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
@@ -813,13 +832,13 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
         return;
     }
 
-    let store = Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
+    let store = Store(cx, from_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
     unsafe {
         llvm::LLVMSetAlignment(store, type_of::align_of(cx.ccx(), t));
     }
 }
 
-pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
     if ty::type_is_bool(ty) {
         ZExt(bcx, val, Type::i8(bcx.ccx()))
     } else {
@@ -827,7 +846,7 @@ pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
     }
 }
 
-pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
     if ty::type_is_bool(ty) {
         Trunc(bcx, val, Type::i1(bcx.ccx()))
     } else {
@@ -869,8 +888,7 @@ pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 {
     let _icx = push_ctxt("with_cond");
 
-    if bcx.unreachable.get() ||
-            (common::is_const(val) && common::const_to_uint(val) == 0) {
+    if bcx.unreachable.get() || common::const_to_opt_uint(val) == Some(0) {
         return bcx;
     }
 
@@ -1070,7 +1088,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
     let blk = match tcx.map.find(id) {
         Some(ast_map::NodeItem(i)) => {
             match i.node {
-                ast::ItemFn(_, _, _, _, ref blk) => {
+                ast::ItemFn(_, _, _, _, _, ref blk) => {
                     blk
                 }
                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
@@ -1124,7 +1142,8 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
 // return slot alloca. This can cause errors related to clean-up due to
 // the clobbering of the existing value in the return slot.
 fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
-    for n in cfg.graph.depth_traverse(cfg.entry) {
+    for index in cfg.graph.depth_traverse(cfg.entry) {
+        let n = cfg.graph.node_data(index);
         match tcx.map.find(n.id()) {
             Some(ast_map::NodeExpr(ex)) => {
                 if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
@@ -1169,13 +1188,13 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
                              -> FunctionContext<'a, 'tcx> {
     common::validate_substs(param_substs);
 
-    debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
+    debug!("new_fn_ctxt(path={}, id={}, param_substs={:?})",
            if id == !0 {
                "".to_string()
            } else {
                ccx.tcx().map.path_to_string(id).to_string()
            },
-           id, param_substs.repr(ccx.tcx()));
+           id, param_substs);
 
     let uses_outptr = match output_type {
         ty::FnConverging(output_type) => {
@@ -1278,16 +1297,28 @@ pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
 // create_datums_for_fn_args: creates rvalue datums for each of the
 // incoming function arguments. These will later be stored into
 // appropriate lvalue datums.
-pub fn create_datums_for_fn_args<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
+pub fn create_datums_for_fn_args<'a, 'tcx>(bcx: Block<'a, 'tcx>,
                                            arg_tys: &[Ty<'tcx>])
                                            -> Vec<RvalueDatum<'tcx>> {
     let _icx = push_ctxt("create_datums_for_fn_args");
+    let fcx = bcx.fcx;
 
     // Return an array wrapping the ValueRefs that we get from `get_param` for
     // each argument into datums.
-    arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
-        let llarg = get_param(fcx.llfn, fcx.arg_pos(i) as c_uint);
-        datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
+    let mut i = fcx.arg_offset() as c_uint;
+    arg_tys.iter().map(|&arg_ty| {
+        if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+            let llty = type_of::type_of(bcx.ccx(), arg_ty);
+            let data = get_param(fcx.llfn, i);
+            let extra = get_param(fcx.llfn, i + 1);
+            let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
+            i += 2;
+            datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
+        } else {
+            let llarg = get_param(fcx.llfn, i);
+            i += 1;
+            datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
+        }
     }).collect()
 }
 
@@ -1302,18 +1333,29 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
         arg_tys: &[Ty<'tcx>])
         -> Vec<RvalueDatum<'tcx>> {
     let mut result = Vec::new();
+    let mut idx = bcx.fcx.arg_offset() as c_uint;
     for (i, &arg_ty) in arg_tys.iter().enumerate() {
         if i < arg_tys.len() - 1 {
             // Regular argument.
-            let llarg = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(i) as c_uint);
-            result.push(datum::Datum::new(llarg, arg_ty, arg_kind(bcx.fcx,
-                                                                  arg_ty)));
+            result.push(if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+                let llty = type_of::type_of(bcx.ccx(), arg_ty);
+                let data = get_param(bcx.fcx.llfn, idx);
+                let extra = get_param(bcx.fcx.llfn, idx + 1);
+                idx += 2;
+                let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
+                datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
+            } else {
+                let val = get_param(bcx.fcx.llfn, idx);
+                idx += 1;
+                datum::Datum::new(val, arg_ty, arg_kind(bcx.fcx, arg_ty))
+            });
+
             continue
         }
 
         // This is the last argument. Tuple it.
         match arg_ty.sty {
-            ty::ty_tup(ref tupled_arg_tys) => {
+            ty::TyTuple(ref tupled_arg_tys) => {
                 let tuple_args_scope_id = cleanup::CustomScope(arg_scope);
                 let tuple =
                     unpack_datum!(bcx,
@@ -1327,15 +1369,21 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
                                                                llval| {
                         for (j, &tupled_arg_ty) in
                                     tupled_arg_tys.iter().enumerate() {
-                            let llarg =
-                                get_param(bcx.fcx.llfn,
-                                          bcx.fcx.arg_pos(i + j) as c_uint);
                             let lldest = GEPi(bcx, llval, &[0, j]);
-                            let datum = datum::Datum::new(
-                                llarg,
-                                tupled_arg_ty,
-                                arg_kind(bcx.fcx, tupled_arg_ty));
-                            bcx = datum.store_to(bcx, lldest);
+                            if common::type_is_fat_ptr(bcx.tcx(), tupled_arg_ty) {
+                                let data = get_param(bcx.fcx.llfn, idx);
+                                let extra = get_param(bcx.fcx.llfn, idx + 1);
+                                Store(bcx, data, expr::get_dataptr(bcx, lldest));
+                                Store(bcx, extra, expr::get_len(bcx, lldest));
+                                idx += 2;
+                            } else {
+                                let datum = datum::Datum::new(
+                                    get_param(bcx.fcx.llfn, idx),
+                                    tupled_arg_ty,
+                                    arg_kind(bcx.fcx, tupled_arg_ty));
+                                idx += 1;
+                                bcx = datum.store_to(bcx, lldest);
+                            };
                         }
                         bcx
                     }));
@@ -1492,8 +1540,8 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let _icx = push_ctxt("trans_closure");
     attributes::emit_uwtable(llfndecl, true);
 
-    debug!("trans_closure(..., param_substs={})",
-           param_substs.repr(ccx.tcx()));
+    debug!("trans_closure(..., param_substs={:?})",
+           param_substs);
 
     let has_env = match closure_env {
         closure::ClosureEnv::Closure(_) => true,
@@ -1535,8 +1583,8 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     };
     for monomorphized_arg_type in &monomorphized_arg_types {
-        debug!("trans_closure: monomorphized_arg_type: {}",
-               ty_to_string(ccx.tcx(), *monomorphized_arg_type));
+        debug!("trans_closure: monomorphized_arg_type: {:?}",
+               monomorphized_arg_type);
     }
     debug!("trans_closure: function lltype: {}",
            bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn));
@@ -1547,7 +1595,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         _ => {
             let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi);
-            create_datums_for_fn_args(&fcx, &arg_tys)
+            create_datums_for_fn_args(bcx, &arg_tys)
         }
     };
 
@@ -1618,7 +1666,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                           id: ast::NodeId,
                           attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
-    debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
+    debug!("trans_fn(param_substs={:?})", param_substs);
     let _icx = push_ctxt("trans_fn");
     let fn_ty = ty::node_id_to_type(ccx.tcx(), id);
     let output_type = ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fn_ty));
@@ -1653,16 +1701,15 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                                  -> Result<'blk, 'tcx> {
 
     let ccx = bcx.fcx.ccx;
-    let tcx = ccx.tcx();
 
     let result_ty = match ctor_ty.sty {
-        ty::ty_bare_fn(_, ref bft) => {
+        ty::TyBareFn(_, ref bft) => {
             ty::erase_late_bound_regions(bcx.tcx(), &bft.sig.output()).unwrap()
         }
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_constructor: \
                      unexpected ctor return type {}",
-                     ctor_ty.repr(tcx)))
+                     ctor_ty))
     };
 
     // Get location to store the result. If the user does not care about
@@ -1673,7 +1720,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             if !type_is_zero_size(ccx, result_ty) {
                 alloc_ty(bcx, result_ty, "constructor_result")
             } else {
-                C_undef(type_of::type_of(ccx, result_ty))
+                C_undef(type_of::type_of(ccx, result_ty).ptr_to())
             }
         }
     };
@@ -1734,13 +1781,13 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
     let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
 
     let result_ty = match ctor_ty.sty {
-        ty::ty_bare_fn(_, ref bft) => {
+        ty::TyBareFn(_, ref bft) => {
             ty::erase_late_bound_regions(ccx.tcx(), &bft.sig.output())
         }
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_or_tuple_like_struct: \
                      unexpected ctor return type {}",
-                    ty_to_string(ccx.tcx(), ctor_ty)))
+                    ctor_ty))
     };
 
     let (arena, fcx): (TypedArena<_>, FunctionContext);
@@ -1755,7 +1802,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
         ty::erase_late_bound_regions(
             ccx.tcx(), &ty::ty_fn_args(ctor_ty));
 
-    let arg_datums = create_datums_for_fn_args(&fcx, &arg_tys[..]);
+    let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
 
     if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
         let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
@@ -1939,11 +1986,17 @@ pub fn update_linkage(ccx: &CrateContext,
     match id {
         Some(id) if ccx.reachable().contains(&id) => {
             llvm::SetLinkage(llval, llvm::ExternalLinkage);
+            if ccx.use_dll_storage_attrs() {
+                llvm::SetDLLStorageClass(llval, llvm::DLLExportStorageClass);
+            }
         },
         _ => {
             // `id` does not refer to an item in `ccx.reachable`.
             if ccx.sess().opts.cg.codegen_units > 1 {
                 llvm::SetLinkage(llval, llvm::ExternalLinkage);
+                if ccx.use_dll_storage_attrs() {
+                    llvm::SetDLLStorageClass(llval, llvm::DLLExportStorageClass);
+                }
             } else {
                 llvm::SetLinkage(llval, llvm::InternalLinkage);
             }
@@ -1957,7 +2010,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
     let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
 
     match item.node {
-      ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => {
+      ast::ItemFn(ref decl, _, _, abi, ref generics, ref body) => {
         if !generics.is_type_parameterized() {
             let trans_everywhere = attr::requests_inline(&item.attrs);
             // Ignore `trans_everywhere` for cross-crate inlined items
@@ -2023,28 +2076,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
 
           let g = consts::trans_static(ccx, m, item.id);
           update_linkage(ccx, g, Some(item.id), OriginalTranslation);
-
-          // Do static_assert checking. It can't really be done much earlier
-          // because we need to get the value of the bool out of LLVM
-          if attr::contains_name(&item.attrs, "static_assert") {
-              if !ty::type_is_bool(ty::expr_ty(ccx.tcx(), expr)) {
-                  ccx.sess().span_fatal(expr.span,
-                                        "can only have static_assert on a static \
-                                         with type `bool`");
-              }
-              if m == ast::MutMutable {
-                  ccx.sess().span_fatal(expr.span,
-                                        "cannot have static_assert on a mutable \
-                                         static");
-              }
-
-              let v = ccx.static_values().borrow().get(&item.id).unwrap().clone();
-              unsafe {
-                  if !(llvm::LLVMConstIntGetZExtValue(v) != 0) {
-                      ccx.sess().span_fatal(expr.span, "static assertion failed");
-                  }
-              }
-          }
       },
       ast::ItemForeignMod(ref foreign_mod) => {
         foreign::trans_foreign_mod(ccx, foreign_mod);
@@ -2102,9 +2133,15 @@ fn finish_register_fn(ccx: &CrateContext, sym: String, node_id: ast::NodeId,
     if ccx.tcx().lang_items.stack_exhausted() == Some(def) {
         attributes::split_stack(llfn, false);
         llvm::SetLinkage(llfn, llvm::ExternalLinkage);
+        if ccx.use_dll_storage_attrs() {
+            llvm::SetDLLStorageClass(llfn, llvm::DLLExportStorageClass);
+        }
     }
     if ccx.tcx().lang_items.eh_personality() == Some(def) {
         llvm::SetLinkage(llfn, llvm::ExternalLinkage);
+        if ccx.use_dll_storage_attrs() {
+            llvm::SetDLLStorageClass(llfn, llvm::DLLExportStorageClass);
+        }
     }
 }
 
@@ -2114,7 +2151,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                          node_id: ast::NodeId,
                          node_type: Ty<'tcx>)
                          -> ValueRef {
-    if let ty::ty_bare_fn(_, ref f) = node_type.sty {
+    if let ty::TyBareFn(_, ref f) = node_type.sty {
         if f.abi != Rust && f.abi != RustCall {
             ccx.sess().span_bug(sp, &format!("only the `{}` or `{}` calling conventions are valid \
                                               for this function; `{}` was specified",
@@ -2171,7 +2208,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
         // FIXME: #16581: Marking a symbol in the executable with `dllexport`
         // linkage forces MinGW's linker to output a `.reloc` section for ASLR
         if ccx.sess().target.target.options.is_like_windows {
-            unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
+            llvm::SetDLLStorageClass(llfn, llvm::DLLExportStorageClass);
         }
 
         let llbb = unsafe {
@@ -2292,7 +2329,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     // We need the translated value here, because for enums the
                     // LLVM type is not fully determined by the Rust type.
                     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-                    let (v, ty) = consts::const_expr(ccx, &**expr, empty_substs);
+                    let (v, ty) = consts::const_expr(ccx, &**expr, empty_substs, None);
                     ccx.static_values().borrow_mut().insert(id, v);
                     unsafe {
                         // boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -2321,7 +2358,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     }
                 }
 
-                ast::ItemFn(_, _, abi, _, _) => {
+                ast::ItemFn(_, _, _, abi, _, _) => {
                     let sym = sym();
                     let llfn = if abi == Rust {
                         register_fn(ccx, i.span, sym, i.id, ty)
@@ -2470,7 +2507,7 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId,
 
     let sym = exported_name(ccx, id, mty, &attrs);
 
-    if let ty::ty_bare_fn(_, ref f) = mty.sty {
+    if let ty::TyBareFn(_, ref f) = mty.sty {
         let llfn = if f.abi == Rust || f.abi == RustCall {
             register_fn(ccx, span, sym, id, mty)
         } else {
@@ -2483,7 +2520,7 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId,
     }
 }
 
-pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>,
+pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'a, 'tcx>,
                                             ie: encoder::EncodeInlinedItem<'a>)
                                             -> encoder::EncodeParams<'a, 'tcx> {
     encoder::EncodeParams {
@@ -2527,7 +2564,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
+        let name = loader::meta_section_name(&cx.sess().target.target);
         let name = CString::new(name).unwrap();
         llvm::LLVMSetSection(llglobal, name.as_ptr())
     }
@@ -2588,6 +2625,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
                 if !declared.contains(&name) &&
                    !reachable.contains(str::from_utf8(&name).unwrap()) {
                     llvm::SetLinkage(val, llvm::InternalLinkage);
+                    llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
                 }
             }
         }
@@ -2618,9 +2656,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
     }
 }
 
-pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
-                         -> (ty::ctxt<'tcx>, CrateTranslation) {
-    let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis;
+pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslation {
+    let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
     let krate = tcx.map.krate();
 
     let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
@@ -2637,8 +2674,8 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
 
     // Before we touch LLVM, make sure that multithreading is enabled.
     unsafe {
-        use std::sync::{Once, ONCE_INIT};
-        static INIT: Once = ONCE_INIT;
+        use std::sync::Once;
+        static INIT: Once = Once::new();
         static mut POISONED: bool = false;
         INIT.call_once(|| {
             if llvm::LLVMStartMultithreaded() != 1 {
@@ -2703,7 +2740,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
         stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
             insns_b.cmp(&insns_a)
         });
-        for tuple in &*stats.fn_stats.borrow() {
+        for tuple in stats.fn_stats.borrow().iter() {
             match *tuple {
                 (ref name, insns) => {
                     println!("{} insns, {}", insns, *name);
@@ -2712,7 +2749,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
         }
     }
     if shared_ccx.sess().count_llvm_insns() {
-        for (k, v) in &*shared_ccx.stats().llvm_insns.borrow() {
+        for (k, v) in shared_ccx.stats().llvm_insns.borrow().iter() {
             println!("{:7} {}", *v, *k);
         }
     }
@@ -2760,7 +2797,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
     let formats = shared_ccx.tcx().dependency_formats.borrow().clone();
     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
 
-    let translation = CrateTranslation {
+    CrateTranslation {
         modules: modules,
         metadata_module: metadata_module,
         link: link_meta,
@@ -2768,7 +2805,5 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
         reachable: reachable,
         crate_formats: formats,
         no_builtins: no_builtins,
-    };
-
-    (shared_ccx.take_tcx(), translation)
+    }
 }
index d6ac412a4faead9678cc7711671e87e40a1e78df..05d0a967e64b6e13d76e2ea50153b7a17fe46d80 100644 (file)
@@ -522,30 +522,6 @@ pub fn Not(cx: Block, v: ValueRef, debug_loc: DebugLoc) -> ValueRef {
     B(cx).not(v)
 }
 
-/* Memory */
-pub fn Malloc(cx: Block, ty: Type, debug_loc: DebugLoc) -> ValueRef {
-    unsafe {
-        if cx.unreachable.get() {
-            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
-        }
-        debug_loc.apply(cx.fcx);
-        B(cx).malloc(ty)
-    }
-}
-
-pub fn ArrayMalloc(cx: Block,
-                   ty: Type,
-                   val: ValueRef,
-                   debug_loc: DebugLoc) -> ValueRef {
-    unsafe {
-        if cx.unreachable.get() {
-            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
-        }
-        debug_loc.apply(cx.fcx);
-        B(cx).array_malloc(ty, val)
-    }
-}
-
 pub fn Alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
     unsafe {
         if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); }
@@ -560,16 +536,6 @@ pub fn AllocaFcx(fcx: &FunctionContext, ty: Type, name: &str) -> ValueRef {
     b.alloca(ty, name)
 }
 
-pub fn ArrayAlloca(cx: Block, ty: Type, val: ValueRef) -> ValueRef {
-    unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); }
-        let b = cx.fcx.ccx.builder();
-        b.position_before(cx.fcx.alloca_insert_pt.get().unwrap());
-        DebugLoc::None.apply(cx.fcx);
-        b.array_alloca(ty, val)
-    }
-}
-
 pub fn Free(cx: Block, pointer_val: ValueRef) {
     if cx.unreachable.get() { return; }
     B(cx).free(pointer_val)
index 497e0ae422c1fa3659c17eadb3e0140b518f5956..e100defc248755c0155544783d01f21cc52051dc 100644 (file)
@@ -71,7 +71,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Pass 2: concat strings for each elt, skipping
                 // forwards over any cycles by advancing to rightmost
                 // occurrence of each element in path.
-                let mut s = String::from_str(".");
+                let mut s = String::from(".");
                 i = 0;
                 while i < len {
                     i = mm[v[i]];
@@ -410,21 +410,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    /* Memory */
-    pub fn malloc(&self, ty: Type) -> ValueRef {
-        self.count_insn("malloc");
-        unsafe {
-            llvm::LLVMBuildMalloc(self.llbuilder, ty.to_ref(), noname())
-        }
-    }
-
-    pub fn array_malloc(&self, ty: Type, val: ValueRef) -> ValueRef {
-        self.count_insn("arraymalloc");
-        unsafe {
-            llvm::LLVMBuildArrayMalloc(self.llbuilder, ty.to_ref(), val, noname())
-        }
-    }
-
     pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
         self.count_insn("alloca");
         unsafe {
@@ -438,13 +423,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn array_alloca(&self, ty: Type, val: ValueRef) -> ValueRef {
-        self.count_insn("arrayalloca");
-        unsafe {
-            llvm::LLVMBuildArrayAlloca(self.llbuilder, ty.to_ref(), val, noname())
-        }
-    }
-
     pub fn free(&self, ptr: ValueRef) {
         self.count_insn("free");
         unsafe {
@@ -561,7 +539,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // we care about.
         if ixs.len() < 16 {
             let mut small_vec = [ C_i32(self.ccx, 0); 16 ];
-            for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs.iter()) {
+            for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs) {
                 *small_vec_e = C_i32(self.ccx, ix as i32);
             }
             self.inbounds_gep(base, &small_vec[..ixs.len()])
index e87c058faf9c19b3626b5a77b3673e9a8ff56b74..093b824701fa4c9ec50b45bec5fc65aeecd9305d 100644 (file)
@@ -21,9 +21,7 @@ pub use self::CallArgs::*;
 use arena::TypedArena;
 use back::link;
 use session;
-use llvm::ValueRef;
-use llvm::get_param;
-use llvm;
+use llvm::{self, ValueRef, get_params};
 use metadata::csearch;
 use middle::def;
 use middle::subst;
@@ -53,12 +51,10 @@ use trans::type_::Type;
 use trans::type_of;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
-use util::ppaux::Repr;
-use util::ppaux::ty_to_string;
+use rustc::ast_map;
 
 use syntax::abi as synabi;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ptr::P;
 
 #[derive(Copy, Clone)]
@@ -90,7 +86,7 @@ pub struct Callee<'blk, 'tcx: 'blk> {
 fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                      -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("trans_callee");
-    debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
+    debug!("callee::trans(expr={:?})", expr);
 
     // pick out special kinds of expressions that can be called:
     match expr.node {
@@ -107,7 +103,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                                 -> Callee<'blk, 'tcx> {
         let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr);
         match datum.ty.sty {
-            ty::ty_bare_fn(..) => {
+            ty::TyBareFn(..) => {
                 let llval = datum.to_llscalarish(bcx);
                 return Callee {
                     bcx: bcx,
@@ -117,9 +113,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
             _ => {
                 bcx.tcx().sess.span_bug(
                     expr.span,
-                    &format!("type of callee is neither bare-fn nor closure: \
-                             {}",
-                            bcx.ty_to_string(datum.ty)));
+                    &format!("type of callee is neither bare-fn nor closure: {}",
+                             datum.ty));
             }
         }
     }
@@ -136,7 +131,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                              def: def::Def,
                              ref_expr: &ast::Expr)
                              -> Callee<'blk, 'tcx> {
-        debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
+        debug!("trans_def(def={:?}, ref_expr={:?})", def, ref_expr);
         let expr_ty = common::node_id_type(bcx, ref_expr.id);
         match def {
             def::DefFn(did, _) if {
@@ -157,7 +152,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                 }
             }
             def::DefFn(did, _) if match expr_ty.sty {
-                ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
+                ty::TyBareFn(_, ref f) => f.abi == synabi::RustIntrinsic,
                 _ => false
             } => {
                 let substs = common::node_id_substs(bcx.ccx(),
@@ -230,10 +225,10 @@ pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let _icx = push_ctxt("trans_fn_ref");
 
     let substs = common::node_id_substs(ccx, node, param_substs);
-    debug!("trans_fn_ref(def_id={}, node={:?}, substs={})",
-           def_id.repr(ccx.tcx()),
+    debug!("trans_fn_ref(def_id={:?}, node={:?}, substs={:?})",
+           def_id,
            node,
-           substs.repr(ccx.tcx()));
+           substs);
     trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs)
 }
 
@@ -293,14 +288,14 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
         None => { }
     }
 
-    debug!("trans_fn_pointer_shim(bare_fn_ty={})",
-           bare_fn_ty.repr(tcx));
+    debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
+           bare_fn_ty);
 
     // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
     // which is the fn pointer, and `args`, which is the arguments tuple.
     let (opt_def_id, sig) =
         match bare_fn_ty.sty {
-            ty::ty_bare_fn(opt_def_id,
+            ty::TyBareFn(opt_def_id,
                            &ty::BareFnTy { unsafety: ast::Unsafety::Normal,
                                            abi: synabi::Rust,
                                            ref sig }) => {
@@ -309,7 +304,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 
             _ => {
                 tcx.sess.bug(&format!("trans_fn_pointer_shim invoked on invalid type: {}",
-                                           bare_fn_ty.repr(tcx)));
+                                      bare_fn_ty));
             }
         };
     let sig = ty::erase_late_bound_regions(tcx, sig);
@@ -325,7 +320,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                                              output: sig.output,
                                              variadic: false
                                          })}));
-    debug!("tuple_fn_ty: {}", tuple_fn_ty.repr(tcx));
+    debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
 
     //
     let function_name = link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
@@ -346,19 +341,16 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                       &block_arena);
     let mut bcx = init_function(&fcx, false, sig.output);
 
+    let llargs = get_params(fcx.llfn);
+
+    let self_idx = fcx.arg_offset();
     // the first argument (`self`) will be ptr to the the fn pointer
     let llfnpointer = if is_by_ref {
-        Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32))
+        Load(bcx, llargs[self_idx])
     } else {
-        get_param(fcx.llfn, fcx.arg_pos(0) as u32)
+        llargs[self_idx]
     };
 
-    // the remaining arguments will be the untupled values
-    let llargs: Vec<_> =
-        sig.inputs.iter()
-        .enumerate()
-        .map(|(i, _)| get_param(fcx.llfn, fcx.arg_pos(i+1) as u32))
-        .collect();
     assert!(!fcx.needs_ret_allocas);
 
     let dest = fcx.llretslotptr.get().map(|_|
@@ -369,7 +361,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                            DebugLoc::None,
                            bare_fn_ty,
                            |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) },
-                           ArgVals(&llargs[..]),
+                           ArgVals(&llargs[(self_idx + 1)..]),
                            dest).bcx;
 
     finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
@@ -403,12 +395,12 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
     let _icx = push_ctxt("trans_fn_ref_with_substs");
     let tcx = ccx.tcx();
 
-    debug!("trans_fn_ref_with_substs(def_id={}, node={:?}, \
-            param_substs={}, substs={})",
-           def_id.repr(tcx),
+    debug!("trans_fn_ref_with_substs(def_id={:?}, node={:?}, \
+            param_substs={:?}, substs={:?})",
+           def_id,
            node,
-           param_substs.repr(tcx),
-           substs.repr(tcx));
+           param_substs,
+           substs);
 
     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
     assert!(substs.types.all(|t| !ty::type_has_escaping_regions(*t)));
@@ -459,10 +451,10 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
                     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.repr(tcx), trait_ref.substs.repr(tcx),
-                           first_subst.repr(tcx), new_substs.repr(tcx));
+                            substs = {:?}, trait_subst = {:?}, \
+                            first_subst = {:?}, new_subst = {:?}",
+                           substs, trait_ref.substs,
+                           first_subst, new_substs);
 
                     (true, source_id, new_substs)
                 }
@@ -506,6 +498,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
         false
     };
 
+    debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
+           def_id, must_monomorphise);
+
     // Create a monomorphic version of generic functions
     if must_monomorphise {
         // Should be either intra-crate or inlined.
@@ -614,12 +609,12 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                          dest: expr::Dest)
                                          -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_method_call");
-    debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx()));
+    debug!("trans_method_call(call_expr={:?})", call_expr);
     let method_call = MethodCall::expr(call_expr.id);
     let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) {
         Some(method) => match method.origin {
             ty::MethodTraitObject(_) => match method.ty.sty {
-                ty::ty_bare_fn(_, ref fty) => {
+                ty::TyBareFn(_, ref fty) => {
                     ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty))
                 }
                 _ => method.ty
@@ -697,7 +692,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let mut bcx = callee.bcx;
 
     let (abi, ret_ty) = match callee_ty.sty {
-        ty::ty_bare_fn(_, ref f) => {
+        ty::TyBareFn(_, ref f) => {
             let output = ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output());
             (f.abi, output)
         }
@@ -846,7 +841,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
         let mut llargs = Vec::new();
         let arg_tys = match args {
-            ArgExprs(a) => a.iter().map(|x| common::expr_ty(bcx, &**x)).collect(),
+            ArgExprs(a) => a.iter().map(|x| common::expr_ty_adjusted(bcx, &**x)).collect(),
             _ => panic!("expected arg exprs.")
         };
         bcx = trans_args(bcx,
@@ -927,13 +922,12 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
     // Translate the `self` argument first.
     if !ignore_self {
         let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &*arg_exprs[0]));
-        llargs.push(unpack_result!(bcx, {
-            trans_arg_datum(bcx,
-                            args[0],
-                            arg_datum,
-                            arg_cleanup_scope,
-                            DontAutorefArg)
-        }))
+        bcx = trans_arg_datum(bcx,
+                              args[0],
+                              arg_datum,
+                              arg_cleanup_scope,
+                              DontAutorefArg,
+                              llargs);
     }
 
     // Now untuple the rest of the arguments.
@@ -941,7 +935,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
     let tuple_type = common::node_id_type(bcx, tuple_expr.id);
 
     match tuple_type.sty {
-        ty::ty_tup(ref field_types) => {
+        ty::TyTuple(ref field_types) => {
             let tuple_datum = unpack_datum!(bcx,
                                             expr::trans(bcx, &**tuple_expr));
             let tuple_lvalue_datum =
@@ -951,21 +945,20 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
                                                           tuple_expr.id));
             let repr = adt::represent_type(bcx.ccx(), tuple_type);
             let repr_ptr = &*repr;
-            llargs.extend(field_types.iter().enumerate().map(|(i, field_type)| {
+            for (i, field_type) in field_types.iter().enumerate() {
                 let arg_datum = tuple_lvalue_datum.get_element(
                     bcx,
                     field_type,
                     |srcval| {
                         adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i)
                     }).to_expr_datum();
-                unpack_result!(bcx, trans_arg_datum(
-                    bcx,
-                    field_type,
-                    arg_datum,
-                    arg_cleanup_scope,
-                    DontAutorefArg)
-                )
-            }));
+                bcx = trans_arg_datum(bcx,
+                                      field_type,
+                                      arg_datum,
+                                      arg_cleanup_scope,
+                                      DontAutorefArg,
+                                      llargs);
+            }
         }
         _ => {
             bcx.sess().span_bug(tuple_expr.span,
@@ -988,29 +981,27 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
     let arg_tys = ty::erase_late_bound_regions(bcx.tcx(),  &ty::ty_fn_args(fn_ty));
     if !ignore_self {
         let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
-        llargs.push(unpack_result!(bcx, {
-            trans_arg_datum(bcx,
-                            arg_tys[0],
-                            arg_datum,
-                            arg_cleanup_scope,
-                            DontAutorefArg)
-        }))
+        bcx = trans_arg_datum(bcx,
+                              arg_tys[0],
+                              arg_datum,
+                              arg_cleanup_scope,
+                              DontAutorefArg,
+                              llargs);
     }
 
     // Now untuple the rest of the arguments.
     let tuple_type = arg_tys[1];
     match tuple_type.sty {
-        ty::ty_tup(ref field_types) => {
+        ty::TyTuple(ref field_types) => {
             for (i, &field_type) in field_types.iter().enumerate() {
                 let arg_datum =
                     unpack_datum!(bcx, expr::trans(bcx, arg_exprs[i + 1]));
-                llargs.push(unpack_result!(bcx, {
-                    trans_arg_datum(bcx,
-                                    field_type,
-                                    arg_datum,
-                                    arg_cleanup_scope,
-                                    DontAutorefArg)
-                }))
+                bcx = trans_arg_datum(bcx,
+                                      field_type,
+                                      arg_datum,
+                                      arg_cleanup_scope,
+                                      DontAutorefArg,
+                                      llargs);
             }
         }
         _ => {
@@ -1067,11 +1058,10 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                 };
 
                 let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &**arg_expr));
-                llargs.push(unpack_result!(bcx, {
-                    trans_arg_datum(bcx, arg_ty, arg_datum,
-                                    arg_cleanup_scope,
-                                    DontAutorefArg)
-                }));
+                bcx = trans_arg_datum(bcx, arg_ty, arg_datum,
+                                      arg_cleanup_scope,
+                                      DontAutorefArg,
+                                      llargs);
             }
         }
         ArgOverloadedCall(arg_exprs) => {
@@ -1085,19 +1075,17 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         ArgOverloadedOp(lhs, rhs, autoref) => {
             assert!(!variadic);
 
-            llargs.push(unpack_result!(bcx, {
-                trans_arg_datum(bcx, arg_tys[0], lhs,
-                                arg_cleanup_scope,
-                                DontAutorefArg)
-            }));
+            bcx = trans_arg_datum(bcx, arg_tys[0], lhs,
+                                  arg_cleanup_scope,
+                                  DontAutorefArg,
+                                  llargs);
 
             assert_eq!(arg_tys.len(), 1 + rhs.len());
             for (rhs, rhs_id) in rhs {
-                llargs.push(unpack_result!(bcx, {
-                    trans_arg_datum(bcx, arg_tys[1], rhs,
-                                    arg_cleanup_scope,
-                                    if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg })
-                }));
+                bcx = trans_arg_datum(bcx, arg_tys[1], rhs,
+                                      arg_cleanup_scope,
+                                      if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg },
+                                      llargs);
             }
         }
         ArgVals(vs) => {
@@ -1118,14 +1106,15 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    formal_arg_ty: Ty<'tcx>,
                                    arg_datum: Datum<'tcx, Expr>,
                                    arg_cleanup_scope: cleanup::ScopeId,
-                                   autoref_arg: AutorefArg)
-                                   -> Result<'blk, 'tcx> {
+                                   autoref_arg: AutorefArg,
+                                   llargs: &mut Vec<ValueRef>)
+                                   -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_arg_datum");
     let mut bcx = bcx;
     let ccx = bcx.ccx();
 
-    debug!("trans_arg_datum({})",
-           formal_arg_ty.repr(bcx.tcx()));
+    debug!("trans_arg_datum({:?})",
+           formal_arg_ty);
 
     let arg_datum_ty = arg_datum.ty;
 
@@ -1141,6 +1130,10 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id));
             val = arg_datum.val;
         }
+        DontAutorefArg if common::type_is_fat_ptr(bcx.tcx(), arg_datum_ty) &&
+                !bcx.fcx.type_needs_drop(arg_datum_ty) => {
+            val = arg_datum.val
+        }
         DontAutorefArg => {
             // Make this an rvalue, since we are going to be
             // passing ownership.
@@ -1159,16 +1152,24 @@ pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
     }
 
-    if formal_arg_ty != arg_datum_ty {
+    if type_of::arg_is_indirect(ccx, formal_arg_ty) && formal_arg_ty != arg_datum_ty {
         // this could happen due to e.g. subtyping
         let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
         debug!("casting actual type ({}) to match formal ({})",
                bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
-        debug!("Rust types: {}; {}", ty_to_string(bcx.tcx(), arg_datum_ty),
-                                     ty_to_string(bcx.tcx(), formal_arg_ty));
+        debug!("Rust types: {:?}; {:?}", arg_datum_ty,
+                                     formal_arg_ty);
         val = PointerCast(bcx, val, llformal_arg_ty);
     }
 
     debug!("--- trans_arg_datum passing {}", bcx.val_to_string(val));
-    Result::new(bcx, val)
+
+    if common::type_is_fat_ptr(bcx.tcx(), formal_arg_ty) {
+        llargs.push(Load(bcx, expr::get_dataptr(bcx, val)));
+        llargs.push(Load(bcx, expr::get_len(bcx, val)));
+    } else {
+        llargs.push(val);
+    }
+
+    bcx
 }
index 9133004dfeff1f0ef78b84e80e268f519be52ee0..6355a713a2ce61b1898062f89b5fd57598d3a955 100644 (file)
@@ -133,7 +133,6 @@ use trans::type_::Type;
 use middle::ty::{self, Ty};
 use std::fmt;
 use syntax::ast;
-use util::ppaux::Repr;
 
 pub struct CleanupScope<'blk, 'tcx: 'blk> {
     // The id of this cleanup scope. If the id is None,
@@ -397,10 +396,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
             skip_dtor: false,
         };
 
-        debug!("schedule_drop_mem({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
+        debug!("schedule_drop_mem({:?}, val={}, ty={:?}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()),
+               ty,
                drop.fill_on_drop,
                drop.skip_dtor);
 
@@ -423,10 +422,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
             skip_dtor: false,
         };
 
-        debug!("schedule_drop_and_fill_mem({:?}, val={}, ty={}, fill_on_drop={}, skip_dtor={})",
+        debug!("schedule_drop_and_fill_mem({:?}, val={}, ty={:?}, fill_on_drop={}, skip_dtor={})",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()),
+               ty,
                drop.fill_on_drop,
                drop.skip_dtor);
 
@@ -455,10 +454,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
             skip_dtor: true,
         };
 
-        debug!("schedule_drop_adt_contents({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
+        debug!("schedule_drop_adt_contents({:?}, val={}, ty={:?}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()),
+               ty,
                drop.fill_on_drop,
                drop.skip_dtor);
 
@@ -484,7 +483,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
         debug!("schedule_drop_immediate({:?}, val={}, ty={:?}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()),
+               ty,
                drop.fill_on_drop,
                drop.skip_dtor);
 
index eb4acec25510ac7f28370210cfeced6fc5562f34..61351847a830cf4f22c5524ced07b29702d1266a 100644 (file)
@@ -10,7 +10,7 @@
 
 use arena::TypedArena;
 use back::link::{self, mangle_internal_name_by_path_and_seq};
-use llvm::{ValueRef, get_param};
+use llvm::{ValueRef, get_params};
 use middle::mem_categorization::Typer;
 use trans::adt;
 use trans::attributes;
@@ -28,7 +28,6 @@ use trans::type_of::*;
 use middle::ty::{self, ClosureTyper};
 use middle::subst::Substs;
 use session::config::FullDebugInfo;
-use util::ppaux::Repr;
 
 use syntax::abi::RustCall;
 use syntax::ast;
@@ -143,7 +142,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
     // duplicate declarations
     let function_type = erase_regions(ccx.tcx(), &function_type);
     let params = match function_type.sty {
-        ty::ty_closure(_, substs) => &substs.types,
+        ty::TyClosure(_, substs) => &substs.types,
         _ => unreachable!()
     };
     let mono_id = MonoId {
@@ -153,7 +152,8 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
 
     match ccx.closure_vals().borrow().get(&mono_id) {
         Some(&llfn) => {
-            debug!("get_or_create_declaration_if_closure(): found closure");
+            debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
+                   mono_id, ccx.tn().val_to_string(llfn));
             return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
         }
         None => {}
@@ -173,9 +173,10 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
     attributes::inline(llfn, attributes::InlineAttr::Hint);
 
     debug!("get_or_create_declaration_if_closure(): inserting new \
-            closure {:?} (type {})",
+            closure {:?} (type {}): {:?}",
            mono_id,
-           ccx.tn().type_to_string(val_ty(llfn)));
+           ccx.tn().type_to_string(val_ty(llfn)),
+           ccx.tn().val_to_string(llfn));
     ccx.closure_vals().borrow_mut().insert(mono_id, llfn);
 
     Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
@@ -198,9 +199,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
         Dest::Ignore(ccx) => ccx
     };
     let tcx = ccx.tcx();
-    let _icx = push_ctxt("closure::trans_closure");
+    let _icx = push_ctxt("closure::trans_closure_expr");
 
-    debug!("trans_closure()");
+    debug!("trans_closure_expr()");
 
     let closure_id = ast_util::local_def(id);
     let llfn = get_or_create_declaration_if_closure(
@@ -230,7 +231,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
                   &[],
                   sig.output,
                   function_type.abi,
-                  ClosureEnv::Closure(&freevars[..]));
+                  ClosureEnv::Closure(&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
@@ -238,7 +239,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     let (mut bcx, dest_addr) = match dest {
         Dest::SaveIn(bcx, p) => (bcx, p),
         Dest::Ignore(_) => {
-            debug!("trans_closure() ignoring result");
+            debug!("trans_closure_expr() ignoring result");
             return None;
         }
     };
@@ -351,9 +352,9 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     llreffn: ValueRef)
     -> ValueRef
 {
-    debug!("trans_fn_once_adapter_shim(closure_def_id={}, substs={}, llreffn={})",
-           closure_def_id.repr(ccx.tcx()),
-           substs.repr(ccx.tcx()),
+    debug!("trans_fn_once_adapter_shim(closure_def_id={:?}, substs={:?}, llreffn={})",
+           closure_def_id,
+           substs,
            ccx.tn().val_to_string(llreffn));
 
     let tcx = ccx.tcx();
@@ -372,8 +373,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
                                                                abi: abi,
                                                                sig: sig.clone() });
     let llref_fn_ty = ty::mk_bare_fn(tcx, None, llref_bare_fn_ty);
-    debug!("trans_fn_once_adapter_shim: llref_fn_ty={}",
-           llref_fn_ty.repr(tcx));
+    debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
+           llref_fn_ty);
 
     // Make a version of the closure type with the same arguments, but
     // with argument #0 being by value.
@@ -404,11 +405,14 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
                       &block_arena);
     let mut bcx = init_function(&fcx, false, sig.output);
 
+    let llargs = get_params(fcx.llfn);
+
     // the first argument (`self`) will be the (by value) closure env.
     let self_scope = fcx.push_custom_cleanup_scope();
     let self_scope_id = CustomScope(self_scope);
     let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty);
-    let llself = get_param(lloncefn, fcx.arg_pos(0) as u32);
+    let self_idx = fcx.arg_offset();
+    let llself = llargs[self_idx];
     let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode));
     let env_datum = unpack_datum!(bcx,
                                   env_datum.to_lvalue_datum_in_scope(bcx, "self",
@@ -417,19 +421,6 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     debug!("trans_fn_once_adapter_shim: env_datum={}",
            bcx.val_to_string(env_datum.val));
 
-    // the remaining arguments will be packed up in a tuple.
-    let input_tys = match sig.inputs[1].sty {
-        ty::ty_tup(ref tys) => &**tys,
-        _ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \
-                                      closure_def_id={}",
-                                     closure_def_id.repr(tcx)))
-    };
-    let llargs: Vec<_> =
-        input_tys.iter()
-                 .enumerate()
-                 .map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32))
-                 .collect();
-
     let dest =
         fcx.llretslotptr.get().map(
             |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
@@ -441,7 +432,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
                                    DebugLoc::None,
                                    llref_fn_ty,
                                    |bcx, _| Callee { bcx: bcx, data: callee_data },
-                                   ArgVals(&llargs),
+                                   ArgVals(&llargs[(self_idx + 1)..]),
                                    dest).bcx;
 
     fcx.pop_custom_cleanup_scope(self_scope);
index 03dda57e5689fab9d4112575892d0f4dd662a040..1d81347956ad082e429e8eafb09f22a9c49722d7 100644 (file)
@@ -40,7 +40,7 @@ use middle::traits;
 use middle::ty::{self, HasProjectionTypes, Ty};
 use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
-use util::ppaux::Repr;
+use rustc::ast_map::{PathElem, PathName};
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use arena::TypedArena;
@@ -50,7 +50,6 @@ use std::cell::{Cell, RefCell};
 use std::result::Result as StdResult;
 use std::vec::Vec;
 use syntax::ast;
-use syntax::ast_map::{PathElem, PathName};
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
@@ -64,11 +63,11 @@ pub use trans::context::CrateContext;
 /// subtyping, but they are anonymized and normalized as well). This
 /// is a stronger, caching version of `ty_fold::erase_regions`.
 pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
     let value1 = value.fold_with(&mut RegionEraser(cx));
-    debug!("erase_regions({}) = {}",
-           value.repr(cx), value1.repr(cx));
+    debug!("erase_regions({:?}) = {:?}",
+           value, value1);
     return value1;
 
     struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
@@ -87,8 +86,18 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
             return t_norm;
         }
 
+        fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
+                                   -> ty::ExistentialBounds<'tcx> {
+            let mut s = ty_fold::super_fold_existential_bounds(self, s);
+
+            // this annoying flag messes up trans normalization
+            s.region_bound_will_change = false;
+
+            s
+        }
+
         fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
-            where T : TypeFoldable<'tcx> + Repr<'tcx>
+            where T : TypeFoldable<'tcx>
         {
             let u = ty::anonymize_late_bound_regions(self.tcx(), t);
             ty_fold::super_fold_binder(self, &u)
@@ -118,26 +127,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
     }
 }
 
-// Is the type's representation size known at compile time?
+/// Is the type's representation size known at compile time?
 pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    let param_env = ty::empty_parameter_environment(tcx);
-    // FIXME(#4287) This can cause errors due to polymorphic recursion,
-    // a better span should be provided, if available.
-    let err_count = tcx.sess.err_count();
-    let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
-    // Those errors aren't fatal, but an incorrect result can later
-    // trip over asserts in both rustc's trans and LLVM.
-    if err_count < tcx.sess.err_count() {
-        tcx.sess.abort_if_errors();
-    }
-    is_sized
+    ty::type_is_sized(None, tcx, DUMMY_SP, ty)
 }
 
 pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
-        ty::ty_ptr(ty::mt{ty, ..}) |
-        ty::ty_rptr(_, ty::mt{ty, ..}) |
-        ty::ty_uniq(ty) => {
+        ty::TyRawPtr(ty::mt{ty, ..}) |
+        ty::TyRef(_, ty::mt{ty, ..}) |
+        ty::TyBox(ty) => {
             !type_is_sized(cx, ty)
         }
         _ => {
@@ -168,10 +167,10 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
         let mut needs_unwind_cleanup = false;
         ty::maybe_walk_ty(ty, |ty| {
             needs_unwind_cleanup |= match ty.sty {
-                ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) |
-                ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false,
+                ty::TyBool | ty::TyInt(_) | ty::TyUint(_) |
+                ty::TyFloat(_) | ty::TyTuple(_) | ty::TyRawPtr(_) => false,
 
-                ty::ty_enum(did, substs) =>
+                ty::TyEnum(did, substs) =>
                     ty::enum_variants(tcx, did).iter().any(|v|
                         v.args.iter().any(|&aty| {
                             let t = aty.subst(tcx, substs);
@@ -222,13 +221,13 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
     // destructor (e.g. zero its memory on move).
 
     let contents = ty::type_contents(cx, ty);
-    debug!("type_needs_drop ty={} contents={:?}", ty.repr(cx), contents);
+    debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
     contents.needs_drop(cx)
 }
 
 fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
-        ty::ty_struct(def_id, substs) => {
+        ty::TyStruct(def_id, substs) => {
             let fields = ty::lookup_struct_fields(ccx.tcx(), def_id);
             fields.len() == 1 && {
                 let ty = ty::lookup_field_type(ccx.tcx(), def_id, fields[0].id, substs);
@@ -256,8 +255,8 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
         return false;
     }
     match ty.sty {
-        ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) | ty::ty_vec(_, Some(_)) |
-        ty::ty_closure(..) => {
+        ty::TyStruct(..) | ty::TyEnum(..) | ty::TyTuple(..) | ty::TyArray(_, _) |
+        ty::TyClosure(..) => {
             let llty = sizing_type_of(ccx, ty);
             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
         }
@@ -432,13 +431,8 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
-    pub fn arg_pos(&self, arg: usize) -> usize {
-        let arg = self.env_arg_pos() + arg;
-        if self.llenv.is_some() {
-            arg + 1
-        } else {
-            arg
-        }
+    pub fn arg_offset(&self) -> usize {
+        self.env_arg_pos() + if self.llenv.is_some() { 1 } else { 0 }
     }
 
     pub fn env_arg_pos(&self) -> usize {
@@ -528,7 +522,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
     }
 
     pub fn monomorphize<T>(&self, value: &T) -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+        where T : TypeFoldable<'tcx> + HasProjectionTypes
     {
         monomorphize::apply_param_substs(self.ccx.tcx(),
                                          self.param_substs,
@@ -603,10 +597,6 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
         self.tcx().map.node_to_string(id).to_string()
     }
 
-    pub fn expr_to_string(&self, e: &ast::Expr) -> String {
-        e.repr(self.tcx())
-    }
-
     pub fn def(&self, nid: ast::NodeId) -> def::Def {
         match self.tcx().def_map.borrow().get(&nid) {
             Some(v) => v.full_def(),
@@ -625,16 +615,12 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
         self.ccx().tn().type_to_string(ty)
     }
 
-    pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
-        t.repr(self.tcx())
-    }
-
     pub fn to_str(&self) -> String {
         format!("[block {:p}]", self)
     }
 
     pub fn monomorphize<T>(&self, value: &T) -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+        where T : TypeFoldable<'tcx> + HasProjectionTypes
     {
         monomorphize::apply_param_substs(self.tcx(),
                                          self.fcx.param_substs,
@@ -919,12 +905,6 @@ pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
     }
 }
 
-pub fn is_const(v: ValueRef) -> bool {
-    unsafe {
-        llvm::LLVMIsConstant(v) == True
-    }
-}
-
 pub fn const_to_int(v: ValueRef) -> i64 {
     unsafe {
         llvm::LLVMConstIntGetSExtValue(v)
@@ -1010,13 +990,14 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // First check the cache.
     match ccx.trait_cache().borrow().get(&trait_ref) {
         Some(vtable) => {
-            info!("Cache hit: {}", trait_ref.repr(ccx.tcx()));
+            info!("Cache hit: {:?}", trait_ref);
             return (*vtable).clone();
         }
         None => { }
     }
 
-    debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
+    debug!("trans fulfill_obligation: trait_ref={:?} def_id={:?}",
+           trait_ref, trait_ref.def_id());
 
     ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
     let infcx = infer::new_infer_ctxt(tcx);
@@ -1037,9 +1018,9 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // leading to an ambiguous result. So report this as an
             // overflow bug, since I believe this is the only case
             // where ambiguity can result.
-            debug!("Encountered ambiguity selecting `{}` during trans, \
+            debug!("Encountered ambiguity selecting `{:?}` during trans, \
                     presuming due to overflow",
-                   trait_ref.repr(tcx));
+                   trait_ref);
             ccx.sess().span_fatal(
                 span,
                 "reached the recursion limit during monomorphization");
@@ -1047,22 +1028,22 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         Err(e) => {
             tcx.sess.span_bug(
                 span,
-                &format!("Encountered error `{}` selecting `{}` during trans",
-                        e.repr(tcx),
-                        trait_ref.repr(tcx)))
+                &format!("Encountered error `{:?}` selecting `{:?}` during trans",
+                        e,
+                        trait_ref))
         }
     };
 
     // Currently, we use a fulfillment context to completely resolve
     // all nested obligations. This is because they can inform the
     // inference of the impl's type parameters.
-    let mut fulfill_cx = traits::FulfillmentContext::new();
-    let vtable = selection.map_move_nested(|predicate| {
+    let mut fulfill_cx = traits::FulfillmentContext::new(true);
+    let vtable = selection.map(|predicate| {
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
     });
     let vtable = drain_fulfillment_cx_or_panic(span, &infcx, &mut fulfill_cx, &vtable);
 
-    info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
+    info!("Cache miss: {:?}", trait_ref);
     ccx.trait_cache().borrow_mut().insert(trait_ref,
                                           vtable.clone());
 
@@ -1077,14 +1058,14 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                predicates: Vec<ty::Predicate<'tcx>>)
                                                -> bool
 {
-    debug!("normalize_and_test_predicates(predicates={})",
-           predicates.repr(ccx.tcx()));
+    debug!("normalize_and_test_predicates(predicates={:?})",
+           predicates);
 
     let tcx = ccx.tcx();
     let infcx = infer::new_infer_ctxt(tcx);
     let typer = NormalizingClosureTyper::new(tcx);
     let mut selcx = traits::SelectionContext::new(&infcx, &typer);
-    let mut fulfill_cx = traits::FulfillmentContext::new();
+    let mut fulfill_cx = traits::FulfillmentContext::new(false);
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: predicates, obligations } =
         traits::normalize(&mut selcx, cause.clone(), &predicates);
@@ -1150,15 +1131,15 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
                                                 fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
                                                 result: &T)
                                                 -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
     match drain_fulfillment_cx(infcx, fulfill_cx, result) {
         Ok(v) => v,
         Err(errors) => {
             infcx.tcx.sess.span_bug(
                 span,
-                &format!("Encountered errors `{}` fulfilling during trans",
-                         errors.repr(infcx.tcx)));
+                &format!("Encountered errors `{:?}` fulfilling during trans",
+                         errors));
         }
     }
 }
@@ -1174,10 +1155,10 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
                                        fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
                                        result: &T)
                                        -> StdResult<T,Vec<traits::FulfillmentError<'tcx>>>
-    where T : TypeFoldable<'tcx> + Repr<'tcx>
+    where T : TypeFoldable<'tcx>
 {
-    debug!("drain_fulfillment_cx(result={})",
-           result.repr(infcx.tcx));
+    debug!("drain_fulfillment_cx(result={:?})",
+           result);
 
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
@@ -1225,7 +1206,7 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     if substs.types.any(|t| ty::type_needs_infer(*t)) {
             tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
-                                 node, substs.repr(tcx)));
+                                 node, substs));
         }
 
         monomorphize::apply_param_substs(tcx,
index 503bdf8dadb94635c654ec1d95a0b5b6f75d62f5..7fbc86d7a8a3efaa334f90e844054999f059075a 100644 (file)
@@ -13,7 +13,8 @@ use back::abi;
 use llvm;
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
-use middle::{check_const, const_eval, def};
+use middle::{check_const, def};
+use middle::const_eval::{self, ConstVal};
 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};
@@ -29,9 +30,10 @@ use trans::declare;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
+use middle::cast::{CastTy,IntTy};
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
-use util::ppaux::{Repr, ty_to_string};
+use util::nodemap::NodeMap;
 
 use std::iter::repeat;
 use libc::c_uint;
@@ -39,6 +41,8 @@ use syntax::{ast, ast_util};
 use syntax::parse::token;
 use syntax::ptr::P;
 
+pub type FnArgMap<'a> = Option<&'a NodeMap<ValueRef>>;
+
 pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
     -> ValueRef {
     let _icx = push_ctxt("trans_lit");
@@ -55,16 +59,16 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
         ast::LitInt(i, ast::UnsuffixedIntLit(_)) => {
             let lit_int_ty = ty::node_id_to_type(cx.tcx(), e.id);
             match lit_int_ty.sty {
-                ty::ty_int(t) => {
+                ty::TyInt(t) => {
                     C_integral(Type::int_from_ty(cx, t), i as u64, true)
                 }
-                ty::ty_uint(t) => {
+                ty::TyUint(t) => {
                     C_integral(Type::uint_from_ty(cx, t), i as u64, false)
                 }
                 _ => cx.sess().span_bug(lit.span,
-                        &format!("integer literal has type {} (expected int \
+                        &format!("integer literal has type {:?} (expected int \
                                  or usize)",
-                                ty_to_string(cx.tcx(), lit_int_ty)))
+                                lit_int_ty))
             }
         }
         ast::LitFloat(ref fs, t) => {
@@ -73,7 +77,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
         ast::LitFloatUnsuffixed(ref fs) => {
             let lit_float_ty = ty::node_id_to_type(cx.tcx(), e.id);
             match lit_float_ty.sty {
-                ty::ty_float(t) => {
+                ty::TyFloat(t) => {
                     C_floating(&fs, Type::float_from_ty(cx, t))
                 }
                 _ => {
@@ -156,9 +160,32 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
         }
         None => {
-            cx.sess().bug(&format!("unexpected dereferenceable type {}",
-                                   ty_to_string(cx.tcx(), ty)))
+            cx.sess().bug(&format!("unexpected dereferenceable type {:?}",
+                                   ty))
+        }
+    }
+}
+
+fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                           node: ExprOrMethodCall,
+                           def_id: ast::DefId,
+                           arg_vals: &[ValueRef],
+                           param_substs: &'tcx Substs<'tcx>) -> ValueRef {
+    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");
+
+    let args = &fn_like.decl().inputs;
+    assert_eq!(args.len(), arg_vals.len());
+
+    let arg_ids = args.iter().map(|arg| arg.pat.id);
+    let fn_args = arg_ids.zip(arg_vals.iter().cloned()).collect();
+
+    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)
     }
 }
 
@@ -194,6 +221,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           qualif: check_const::ConstQualif,
                                           param_substs: &'tcx Substs<'tcx>)
                                           -> ValueRef {
+    debug!("get_const_expr_as_global: {:?}", expr.id);
     // Special-case constants to cache a common global for all uses.
     match expr.node {
         ast::ExprPath(..) => {
@@ -201,6 +229,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             match def {
                 def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
+                        debug!("get_const_expr_as_global ({:?}): found const {:?}",
+                               expr.id, def_id);
                         return get_const_val(ccx, def_id, expr);
                     }
                 }
@@ -220,9 +250,9 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // references, even when only the latter are correct.
         let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
                                                   &ty::expr_ty(ccx.tcx(), expr));
-        const_expr_unadjusted(ccx, expr, ty, param_substs)
+        const_expr_unadjusted(ccx, expr, ty, param_substs, None)
     } else {
-        const_expr(ccx, expr, param_substs).0
+        const_expr(ccx, expr, param_substs, None).0
     };
 
     // boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -242,11 +272,12 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                             e: &ast::Expr,
-                            param_substs: &'tcx Substs<'tcx>)
+                            param_substs: &'tcx Substs<'tcx>,
+                            fn_args: FnArgMap)
                             -> (ValueRef, Ty<'tcx>) {
     let ety = monomorphize::apply_param_substs(cx.tcx(), param_substs,
                                                &ty::expr_ty(cx.tcx(), e));
-    let llconst = const_expr_unadjusted(cx, e, ety, param_substs);
+    let llconst = const_expr_unadjusted(cx, e, ety, param_substs, fn_args);
     let mut llconst = llconst;
     let mut ety_adjusted = monomorphize::apply_param_substs(cx.tcx(), param_substs,
                                                             &ty::expr_ty_adjusted(cx.tcx(), e));
@@ -314,9 +345,11 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let info = expr::unsized_info(cx, pointee_ty, unsized_ty,
                                               old_info, param_substs);
 
-                let prev_const = cx.const_unsized().borrow_mut()
-                                   .insert(base, llconst);
-                assert!(prev_const.is_none() || prev_const == Some(llconst));
+                if old_info.is_none() {
+                    let prev_const = cx.const_unsized().borrow_mut()
+                                       .insert(base, llconst);
+                    assert!(prev_const.is_none() || prev_const == Some(llconst));
+                }
                 assert_eq!(abi::FAT_PTR_ADDR, 0);
                 assert_eq!(abi::FAT_PTR_EXTRA, 1);
                 llconst = C_struct(cx, &[base, info], false);
@@ -335,8 +368,8 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             llvm::LLVMDumpValue(llconst);
             llvm::LLVMDumpValue(C_undef(llty));
         }
-        cx.sess().bug(&format!("const {} of type {} has size {} instead of {}",
-                         e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety_adjusted),
+        cx.sess().bug(&format!("const {:?} of type {:?} has size {} instead of {}",
+                         e, ety_adjusted,
                          csize, tsize));
     }
     (llconst, ety_adjusted)
@@ -359,7 +392,7 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
         if let ast::ExprLit(_) = inner_e.node { return; }
 
         let result = match t.sty {
-            ty::ty_int(int_type) => {
+            ty::TyInt(int_type) => {
                 let input = match const_to_opt_int(te) {
                     Some(v) => v,
                     None => return,
@@ -367,7 +400,7 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
                 const_int_checked_neg(
                     input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type)))
             }
-            ty::ty_uint(uint_type) => {
+            ty::TyUint(uint_type) => {
                 let input = match const_to_opt_uint(te) {
                     Some(v) => v,
                     None => return,
@@ -390,7 +423,7 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
     let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return };
 
     let result = match t.sty {
-        ty::ty_int(int_type) => {
+        ty::TyInt(int_type) => {
             let (lhs, rhs) = match (const_to_opt_int(te1),
                                     const_to_opt_int(te2)) {
                 (Some(v1), Some(v2)) => (v1, v2),
@@ -409,7 +442,7 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
                 _ => return,
             }
         }
-        ty::ty_uint(uint_type) => {
+        ty::TyUint(uint_type) => {
             let (lhs, rhs) = match (const_to_opt_uint(te1),
                                     const_to_opt_uint(te2)) {
                 (Some(v1), Some(v2)) => (v1, v2),
@@ -439,17 +472,19 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
 fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    e: &ast::Expr,
                                    ety: Ty<'tcx>,
-                                   param_substs: &'tcx Substs<'tcx>)
+                                   param_substs: &'tcx Substs<'tcx>,
+                                   fn_args: FnArgMap)
                                    -> ValueRef
 {
-    debug!("const_expr_unadjusted(e={}, ety={}, param_substs={})",
-           e.repr(cx.tcx()),
-           ety.repr(cx.tcx()),
-           param_substs.repr(cx.tcx()));
-
-    let map_list = |exprs: &[P<ast::Expr>]| {
-        exprs.iter().map(|e| const_expr(cx, &**e, param_substs).0)
-             .fold(Vec::new(), |mut l, val| { l.push(val); l })
+    debug!("const_expr_unadjusted(e={:?}, ety={:?}, param_substs={:?})",
+           e,
+           ety,
+           param_substs);
+
+    let map_list = |exprs: &[P<ast::Expr>]| -> Vec<ValueRef> {
+        exprs.iter()
+             .map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
+             .collect()
     };
     unsafe {
         let _icx = push_ctxt("const_expr");
@@ -460,10 +495,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::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);
-            debug!("const_expr_unadjusted: te1={}, ty={}",
+            let (te1, ty) = const_expr(cx, &**e1, param_substs, fn_args);
+            debug!("const_expr_unadjusted: te1={}, ty={:?}",
                    cx.tn().val_to_string(te1),
-                   ty.repr(cx.tcx()));
+                   ty);
             let is_simd = ty::type_is_simd(cx.tcx(), ty);
             let intype = if is_simd {
                 ty::simd_type(cx.tcx(), ty)
@@ -473,7 +508,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let is_float = ty::type_is_fp(intype);
             let signed = ty::type_is_signed(intype);
 
-            let (te2, _) = const_expr(cx, &**e2, param_substs);
+            let (te2, _) = const_expr(cx, &**e2, param_substs, fn_args);
 
             check_binary_expr_validity(cx, e, ty, te1, te2);
 
@@ -533,7 +568,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           },
           ast::ExprUnary(u, ref inner_e) => {
-            let (te, ty) = const_expr(cx, &**inner_e, param_substs);
+            let (te, ty) = const_expr(cx, &**inner_e, param_substs, fn_args);
 
             check_unary_expr_validity(cx, e, ty, te);
 
@@ -550,7 +585,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprField(ref base, field) => {
-              let (bv, bt) = const_expr(cx, &**base, param_substs);
+              let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
               let brepr = adt::represent_type(cx, bt);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
                   let ix = ty::field_idx_strict(cx.tcx(), field.node.name, field_tys);
@@ -558,7 +593,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               })
           }
           ast::ExprTupField(ref base, idx) => {
-              let (bv, bt) = const_expr(cx, &**base, param_substs);
+              let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
               let brepr = adt::represent_type(cx, bt);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, _| {
                   adt::const_get_field(cx, &*brepr, bv, discr, idx.node)
@@ -566,38 +601,38 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           }
 
           ast::ExprIndex(ref base, ref index) => {
-              let (bv, bt) = const_expr(cx, &**base, param_substs);
+              let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
               let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) {
-                  Ok(const_eval::const_int(i)) => i as u64,
-                  Ok(const_eval::const_uint(u)) => u,
+                  Ok(ConstVal::Int(i)) => i as u64,
+                  Ok(ConstVal::Uint(u)) => u,
                   _ => cx.sess().span_bug(index.span,
                                           "index is not an integer-constant expression")
               };
               let (arr, len) = match bt.sty {
-                  ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
-                  ty::ty_vec(_, None) | ty::ty_str => {
+                  ty::TyArray(_, u) => (bv, C_uint(cx, u)),
+                  ty::TySlice(_) | ty::TyStr => {
                       let e1 = const_get_elt(cx, bv, &[0]);
                       (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
                   }
-                  ty::ty_rptr(_, mt) => match mt.ty.sty {
-                      ty::ty_vec(_, Some(u)) => {
+                  ty::TyRef(_, mt) => match mt.ty.sty {
+                      ty::TyArray(_, u) => {
                           (const_deref_ptr(cx, bv), C_uint(cx, u))
                       },
                       _ => cx.sess().span_bug(base.span,
                                               &format!("index-expr base must be a vector \
-                                                       or string type, found {}",
-                                                      ty_to_string(cx.tcx(), bt)))
+                                                       or string type, found {:?}",
+                                                      bt))
                   },
                   _ => cx.sess().span_bug(base.span,
                                           &format!("index-expr base must be a vector \
-                                                   or string type, found {}",
-                                                  ty_to_string(cx.tcx(), bt)))
+                                                   or string type, found {:?}",
+                                                  bt))
               };
 
               let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
               let len = match bt.sty {
-                  ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
-                      ty::ty_str => {
+                  ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => match ty.sty {
+                      ty::TyStr => {
                           assert!(len > 0);
                           len - 1
                       }
@@ -616,53 +651,64 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               }
           }
           ast::ExprCast(ref base, _) => {
-            let llty = type_of::type_of(cx, ety);
-            let (v, basety) = const_expr(cx, &**base, param_substs);
-            if expr::cast_is_noop(basety, ety) {
+            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);
+            debug!("trans_const_cast({:?} as {:?})", t_expr, t_cast);
+            if expr::cast_is_noop(cx.tcx(), base, t_expr, t_cast) {
                 return v;
             }
-            match (expr::cast_type_kind(cx.tcx(), basety),
-                   expr::cast_type_kind(cx.tcx(), ety)) {
-
-              (expr::cast_integral, expr::cast_integral) => {
-                let s = ty::type_is_signed(basety) as Bool;
+            if type_is_fat_ptr(cx.tcx(), t_expr) {
+                // Fat pointer casts.
+                let t_cast_inner = ty::deref(t_cast, true).expect("cast to non-pointer").ty;
+                let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
+                let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
+                                   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)
+                } else {
+                    return addr;
+                }
+            }
+            match (CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"),
+                   CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast")) {
+              (CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => {
+                let repr = adt::represent_type(cx, t_expr);
+                let discr = adt::const_get_discrim(cx, &*repr, v);
+                let iv = C_integral(cx.int_type(), discr, false);
+                let s = adt::is_discr_signed(&*repr) as Bool;
+                llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
+              }
+              (CastTy::Int(_), CastTy::Int(_)) => {
+                let s = ty::type_is_signed(t_expr) as Bool;
                 llvm::LLVMConstIntCast(v, llty.to_ref(), s)
               }
-              (expr::cast_integral, expr::cast_float) => {
-                if ty::type_is_signed(basety) {
+              (CastTy::Int(_), CastTy::Float) => {
+                if ty::type_is_signed(t_expr) {
                     llvm::LLVMConstSIToFP(v, llty.to_ref())
                 } else {
                     llvm::LLVMConstUIToFP(v, llty.to_ref())
                 }
               }
-              (expr::cast_float, expr::cast_float) => {
+              (CastTy::Float, CastTy::Float) => {
                 llvm::LLVMConstFPCast(v, llty.to_ref())
               }
-              (expr::cast_float, expr::cast_integral) => {
-                if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
-                else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
+              (CastTy::Float, CastTy::Int(IntTy::I)) => {
+                llvm::LLVMConstFPToSI(v, llty.to_ref())
               }
-              (expr::cast_enum, expr::cast_integral) => {
-                let repr = adt::represent_type(cx, basety);
-                let discr = adt::const_get_discrim(cx, &*repr, v);
-                let iv = C_integral(cx.int_type(), discr, false);
-                let ety_cast = expr::cast_type_kind(cx.tcx(), ety);
-                match ety_cast {
-                    expr::cast_integral => {
-                        let s = ty::type_is_signed(ety) as Bool;
-                        llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
-                    }
-                    _ => cx.sess().bug("enum cast destination is not \
-                                        integral")
-                }
+              (CastTy::Float, CastTy::Int(_)) => {
+                llvm::LLVMConstFPToUI(v, llty.to_ref())
               }
-              (expr::cast_pointer, expr::cast_pointer) => {
+              (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_))
+                    | (CastTy::RPtr(_), CastTy::Ptr(_)) => {
                 ptrcast(v, llty)
               }
-              (expr::cast_integral, expr::cast_pointer) => {
+              (CastTy::FnPtr, CastTy::FnPtr) => ptrcast(v, llty), // isn't this a coercion?
+              (CastTy::Int(_), CastTy::Ptr(_)) => {
                 llvm::LLVMConstIntToPtr(v, llty.to_ref())
               }
-              (expr::cast_pointer, expr::cast_integral) => {
+              (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => {
                 llvm::LLVMConstPtrToInt(v, llty.to_ref())
               }
               _ => {
@@ -695,12 +741,12 @@ 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);
+                  let (v, _) = const_expr(cx, &**sub, param_substs, fn_args);
                   addr_of(cx, v, "ref")
               }
           }
           ast::ExprAddrOf(ast::MutMutable, ref sub) => {
-              let (v, _) = const_expr(cx, &**sub, param_substs);
+              let (v, _) = const_expr(cx, &**sub, param_substs, fn_args);
               addr_of_mut(cx, v, "ref_mut_slice")
           }
           ast::ExprTup(ref es) => {
@@ -712,7 +758,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               let repr = adt::represent_type(cx, ety);
 
               let base_val = match *base_opt {
-                Some(ref base) => Some(const_expr(cx, &**base, param_substs)),
+                Some(ref base) => Some(const_expr(cx, &**base, param_substs, fn_args)),
                 None => None
               };
 
@@ -720,7 +766,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                   let cs = field_tys.iter().enumerate()
                                     .map(|(ix, &field_ty)| {
                       match fs.iter().find(|f| field_ty.name == f.ident.node.name) {
-                          Some(ref f) => const_expr(cx, &*f.expr, param_substs).0,
+                          Some(ref f) => const_expr(cx, &*f.expr, param_substs, fn_args).0,
                           None => {
                               match base_val {
                                   Some((bv, _)) => {
@@ -745,7 +791,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprVec(ref es) => {
             let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
             let llunitty = type_of::type_of(cx, unit_ty);
-            let vs = es.iter().map(|e| const_expr(cx, &**e, param_substs).0)
+            let vs = es.iter().map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
                               .collect::<Vec<_>>();
             // If the vector contains enums, an LLVM array won't work.
             if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
@@ -758,7 +804,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
             let llunitty = type_of::type_of(cx, unit_ty);
             let n = ty::eval_repeat_count(cx.tcx(), count);
-            let unit_val = const_expr(cx, &**elem, param_substs).0;
+            let unit_val = const_expr(cx, &**elem, param_substs, fn_args).0;
             let vs: Vec<_> = repeat(unit_val).take(n).collect();
             if val_ty(unit_val) != llunitty {
                 C_struct(cx, &vs[..], false)
@@ -769,6 +815,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprPath(..) => {
             let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
+                def::DefLocal(id) => {
+                    if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
+                        val
+                    } else {
+                        cx.sess().span_bug(e.span, "const fn argument not found")
+                    }
+                }
                 def::DefFn(..) | def::DefMethod(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
@@ -789,7 +842,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     }
                 }
                 def::DefStruct(_) => {
-                    if let ty::ty_bare_fn(..) = ety.sty {
+                    if let ty::TyBareFn(..) = ety.sty {
                         // Tuple struct.
                         expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                     } else {
@@ -804,10 +857,24 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprCall(ref callee, ref args) => {
-              let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def());
-              let arg_vals = map_list(&args[..]);
-              match opt_def {
-                  Some(def::DefStruct(_)) => {
+              let mut callee = &**callee;
+              loop {
+                  callee = match callee.node {
+                      ast::ExprParen(ref inner) => &**inner,
+                      ast::ExprBlock(ref block) => match block.expr {
+                          Some(ref tail) => &**tail,
+                          None => break
+                      },
+                      _ => break
+                  };
+              }
+              let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
+              let arg_vals = map_list(args);
+              match def {
+                  def::DefFn(did, _) | def::DefMethod(did, _) => {
+                      const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs)
+                  }
+                  def::DefStruct(_) => {
                       if ty::type_is_simd(cx.tcx(), ety) {
                           C_vector(&arg_vals[..])
                       } else {
@@ -815,7 +882,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                           adt::trans_const(cx, &*repr, 0, &arg_vals[..])
                       }
                   }
-                  Some(def::DefVariant(enum_did, variant_did, _)) => {
+                  def::DefVariant(enum_did, variant_did, _) => {
                       let repr = adt::represent_type(cx, ety);
                       let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                            enum_did,
@@ -825,19 +892,31 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                        vinfo.disr_val,
                                        &arg_vals[..])
                   }
-                  _ => cx.sess().span_bug(e.span, "expected a struct or variant def")
+                  _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def")
               }
           }
-          ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs).0,
+          ast::ExprMethodCall(_, _, ref args) => {
+              let arg_vals = map_list(args);
+              let method_call = ty::MethodCall::expr(e.id);
+              let method_did = match cx.tcx().method_map.borrow()[&method_call].origin {
+                  ty::MethodStatic(did) => did,
+                  _ => cx.sess().span_bug(e.span, "expected a const method def")
+              };
+              const_fn_call(cx, MethodCallKey(method_call),
+                            method_did, &arg_vals, param_substs)
+          }
+          ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0,
           ast::ExprBlock(ref block) => {
             match block.expr {
-                Some(ref expr) => const_expr(cx, &**expr, param_substs).0,
+                Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0,
                 None => C_nil(cx)
             }
           }
           ast::ExprClosure(_, ref decl, ref body) => {
             closure::trans_closure_expr(closure::Dest::Ignore(cx),
-                                        &**decl, &**body, e.id,
+                                        decl,
+                                        body,
+                                        e.id,
                                         param_substs);
             C_null(type_of::type_of(cx, ety))
           }
index 41ef566f2fd7f8e916c7af0039a62e28d91dc9c4..0ae69682f914ac591276604014a3ec698dea5ebf 100644 (file)
@@ -28,7 +28,6 @@ use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use session::config::NoDebugInfo;
 use session::Session;
-use util::ppaux::Repr;
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
 
@@ -57,7 +56,7 @@ pub struct Stats {
 /// per crate.  The data here is shared between all compilation units of the
 /// crate, so it must not contain references to any LLVM data structures
 /// (aside from metadata-related ones).
-pub struct SharedCrateContext<'tcx> {
+pub struct SharedCrateContext<'a, 'tcx: 'a> {
     local_ccxs: Vec<LocalCrateContext<'tcx>>,
 
     metadata_llmod: ModuleRef,
@@ -68,13 +67,13 @@ pub struct SharedCrateContext<'tcx> {
     item_symbols: RefCell<NodeMap<String>>,
     link_meta: LinkMeta,
     symbol_hasher: RefCell<Sha256>,
-    tcx: ty::ctxt<'tcx>,
+    tcx: &'a ty::ctxt<'tcx>,
     stats: Stats,
     check_overflow: bool,
     check_drop_flag_for_sanity: bool,
 
-    available_monomorphizations: RefCell<FnvHashSet<String>>,
     available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
+    use_dll_storage_attrs: bool,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -99,6 +98,7 @@ pub struct LocalCrateContext<'tcx> {
     /// Cache instances of monomorphized functions
     monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
     monomorphizing: RefCell<DefIdMap<usize>>,
+    available_monomorphizations: RefCell<FnvHashSet<String>>,
     /// Cache generated vtables
     vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
     /// Cache of constant strings,
@@ -158,7 +158,7 @@ pub struct LocalCrateContext<'tcx> {
 }
 
 pub struct CrateContext<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'tcx>,
+    shared: &'a SharedCrateContext<'a, 'tcx>,
     local: &'a LocalCrateContext<'tcx>,
     /// The index of `local` in `shared.local_ccxs`.  This is used in
     /// `maybe_iter(true)` to identify the original `LocalCrateContext`.
@@ -166,7 +166,7 @@ pub struct CrateContext<'a, 'tcx: 'a> {
 }
 
 pub struct CrateContextIterator<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'tcx>,
+    shared: &'a SharedCrateContext<'a, 'tcx>,
     index: usize,
 }
 
@@ -191,7 +191,7 @@ impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
 
 /// The iterator produced by `CrateContext::maybe_iter`.
 pub struct CrateContextMaybeIterator<'a, 'tcx: 'a> {
-    shared: &'a SharedCrateContext<'tcx>,
+    shared: &'a SharedCrateContext<'a, 'tcx>,
     index: usize,
     single: bool,
     origin: usize,
@@ -236,21 +236,66 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
     (llcx, llmod)
 }
 
-impl<'tcx> SharedCrateContext<'tcx> {
+impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
     pub fn new(crate_name: &str,
                local_count: usize,
-               tcx: ty::ctxt<'tcx>,
+               tcx: &'b ty::ctxt<'tcx>,
                export_map: ExportMap,
                symbol_hasher: Sha256,
                link_meta: LinkMeta,
                reachable: NodeSet,
                check_overflow: bool,
                check_drop_flag_for_sanity: bool)
-               -> SharedCrateContext<'tcx> {
+               -> SharedCrateContext<'b, 'tcx> {
         let (metadata_llcx, metadata_llmod) = unsafe {
             create_context_and_module(&tcx.sess, "metadata")
         };
 
+        // An interesting part of Windows which MSVC forces our hand on (and
+        // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
+        // attributes in LLVM IR as well as native dependencies (in C these
+        // correspond to `__declspec(dllimport)`).
+        //
+        // Whenever a dynamic library is built by MSVC it must have its public
+        // interface specified by functions tagged with `dllexport` or otherwise
+        // they're not available to be linked against. This poses a few problems
+        // for the compiler, some of which are somewhat fundamental, but we use
+        // the `use_dll_storage_attrs` variable below to attach the `dllexport`
+        // attribute to all LLVM functions that are reachable (e.g. they're
+        // already tagged with external linkage). This is suboptimal for a few
+        // reasons:
+        //
+        // * If an object file will never be included in a dynamic library,
+        //   there's no need to attach the dllexport attribute. Most object
+        //   files in Rust are not destined to become part of a dll as binaries
+        //   are statically linked by default.
+        // * If the compiler is emitting both an rlib and a dylib, the same
+        //   source object file is currently used but with MSVC this may be less
+        //   feasible. The compiler may be able to get around this, but it may
+        //   involve some invasive changes to deal with this.
+        //
+        // The flipside of this situation is that whenever you link to a dll and
+        // you import a function from it, the import should be tagged with
+        // `dllimport`. At this time, however, the compiler does not emit
+        // `dllimport` for any declarations other than constants (where it is
+        // required), which is again suboptimal for even more reasons!
+        //
+        // * Calling a function imported from another dll without using
+        //   `dllimport` causes the linker/compiler to have extra overhead (one
+        //   `jmp` instruction on x86) when calling the function.
+        // * The same object file may be used in different circumstances, so a
+        //   function may be imported from a dll if the object is linked into a
+        //   dll, but it may be just linked against if linked into an rlib.
+        // * The compiler has no knowledge about whether native functions should
+        //   be tagged dllimport or not.
+        //
+        // For now the compiler takes the perf hit (I do not have any numbers to
+        // this effect) by marking very little as `dllimport` and praying the
+        // linker will take care of everything. Fixing this problem will likely
+        // require adding a few attributes to Rust itself (feature gated at the
+        // start) and then strongly recommending static linkage on MSVC!
+        let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
+
         let mut shared_ccx = SharedCrateContext {
             local_ccxs: Vec::with_capacity(local_count),
             metadata_llmod: metadata_llmod,
@@ -275,8 +320,8 @@ impl<'tcx> SharedCrateContext<'tcx> {
             },
             check_overflow: check_overflow,
             check_drop_flag_for_sanity: check_drop_flag_for_sanity,
-            available_monomorphizations: RefCell::new(FnvHashSet()),
             available_drop_glues: RefCell::new(FnvHashMap()),
+            use_dll_storage_attrs: use_dll_storage_attrs,
         };
 
         for i in 0..local_count {
@@ -351,10 +396,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
     }
 
     pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
-        &self.tcx
-    }
-
-    pub fn take_tcx(self) -> ty::ctxt<'tcx> {
         self.tcx
     }
 
@@ -365,10 +406,14 @@ impl<'tcx> SharedCrateContext<'tcx> {
     pub fn stats<'a>(&'a self) -> &'a Stats {
         &self.stats
     }
+
+    pub fn use_dll_storage_attrs(&self) -> bool {
+        self.use_dll_storage_attrs
+    }
 }
 
 impl<'tcx> LocalCrateContext<'tcx> {
-    fn new(shared: &SharedCrateContext<'tcx>,
+    fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
            name: &str)
            -> LocalCrateContext<'tcx> {
         unsafe {
@@ -401,6 +446,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
                 external_srcs: RefCell::new(NodeMap()),
                 monomorphized: RefCell::new(FnvHashMap()),
                 monomorphizing: RefCell::new(DefIdMap()),
+                available_monomorphizations: RefCell::new(FnvHashSet()),
                 vtables: RefCell::new(FnvHashMap()),
                 const_cstr_cache: RefCell::new(FnvHashMap()),
                 const_unsized: RefCell::new(FnvHashMap()),
@@ -454,7 +500,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
     /// This is used in the `LocalCrateContext` constructor to allow calling
     /// functions that expect a complete `CrateContext`, even before the local
     /// portion is fully initialized and attached to the `SharedCrateContext`.
-    fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext<'tcx>)
+    fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext<'a, 'tcx>)
                      -> CrateContext<'a, 'tcx> {
         CrateContext {
             shared: shared,
@@ -465,7 +511,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
 }
 
 impl<'b, 'tcx> CrateContext<'b, 'tcx> {
-    pub fn shared(&self) -> &'b SharedCrateContext<'tcx> {
+    pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
         self.shared
     }
 
@@ -497,7 +543,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
 
 
     pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
-        &self.shared.tcx
+        self.shared.tcx
     }
 
     pub fn sess<'a>(&'a self) -> &'a Session {
@@ -658,7 +704,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
     }
 
     pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
-        &self.shared.available_monomorphizations
+        &self.local.available_monomorphizations
     }
 
     pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
@@ -719,8 +765,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
 
     pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! {
         self.sess().fatal(
-            &format!("the type `{}` is too big for the current architecture",
-                    obj.repr(self.tcx())))
+            &format!("the type `{:?}` is too big for the current architecture",
+                    obj))
     }
 
     pub fn check_overflow(&self) -> bool {
@@ -733,6 +779,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         // values.
         self.shared.check_drop_flag_for_sanity
     }
+
+    pub fn use_dll_storage_attrs(&self) -> bool {
+        self.shared.use_dll_storage_attrs()
+    }
 }
 
 /// Declare any llvm intrinsics that you might need
@@ -815,6 +865,11 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
     ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
     ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
 
+    ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
+    ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
+    ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
+    ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
+
     ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
     ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
     ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
@@ -873,22 +928,48 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
     ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);
 
     ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
-    ifn!("llvm.assume", fn(i1) -> void);
 
     // Some intrinsics were introduced in later versions of LLVM, but they have
-    // fallbacks in libc or libm and such. Currently, all of these intrinsics
-    // were introduced in LLVM 3.4, so we case on that.
+    // fallbacks in libc or libm and such.
     macro_rules! compatible_ifn {
-        ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
-            ifn!($name, fn($($arg),*) -> $ret);
+        ($name:expr, noop($cname:ident ($($arg:expr),*) -> void), $llvm_version:expr) => (
+            if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } {
+                // The `if key == $name` is already in ifn!
+                ifn!($name, fn($($arg),*) -> void);
+            } else if *key == $name {
+                let f = declare::declare_cfn(ccx, stringify!($cname),
+                                             Type::func(&[$($arg),*], &void),
+                                             ty::mk_nil(ccx.tcx()));
+                llvm::SetLinkage(f, llvm::InternalLinkage);
+
+                let bld = ccx.builder();
+                let llbb = unsafe {
+                    llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), f,
+                                                        "entry-block\0".as_ptr() as *const _)
+                };
+
+                bld.position_at_end(llbb);
+                bld.ret_void();
+
+                ccx.intrinsics().borrow_mut().insert($name, f.clone());
+                return Some(f);
+            }
+        );
+        ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr, $llvm_version:expr) => (
+            if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } {
+                // The `if key == $name` is already in ifn!
+                ifn!($name, fn($($arg),*) -> $ret);
+            } else if *key == $name {
+                let f = declare::declare_cfn(ccx, stringify!($cname),
+                                             Type::func(&[$($arg),*], &$ret),
+                                             ty::mk_nil(ccx.tcx()));
+                ccx.intrinsics().borrow_mut().insert($name, f.clone());
+                return Some(f);
+            }
         )
     }
 
-    compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32);
-    compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64);
-    compatible_ifn!("llvm.round.f32", roundf(t_f32) -> t_f32);
-    compatible_ifn!("llvm.round.f64", round(t_f64) -> t_f64);
-
+    compatible_ifn!("llvm.assume", noop(llvmcompat_assume(i1) -> void), 6);
 
     if ccx.sess().opts.debuginfo != NoDebugInfo {
         ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
index 8cecc39ec3900093cdc329552d5d268d0e70cad7..ceef07207acb837f92a38ea58a66027d63156d4e 100644 (file)
@@ -24,27 +24,25 @@ use trans::debuginfo::{DebugLoc, ToDebugLoc};
 use trans::expr;
 use trans;
 use middle::ty;
-use util::ppaux::Repr;
 
 use syntax::ast;
 use syntax::ast_util;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
-use syntax::visit::Visitor;
 
 pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                               s: &ast::Stmt)
                               -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt");
     let fcx = cx.fcx;
-    debug!("trans_stmt({})", s.repr(cx.tcx()));
+    debug!("trans_stmt({:?})", s);
 
     if cx.unreachable.get() {
         return cx;
     }
 
     if cx.sess().asm_comments() {
-        add_span_comment(cx, s.span, &s.repr(cx.tcx()));
+        add_span_comment(cx, s.span, &format!("{:?}", s));
     }
 
     let mut bcx = cx;
@@ -152,8 +150,8 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             els: Option<&ast::Expr>,
                             dest: expr::Dest)
                             -> Block<'blk, 'tcx> {
-    debug!("trans_if(bcx={}, if_id={}, cond={}, thn={}, dest={})",
-           bcx.to_str(), if_id, bcx.expr_to_string(cond), thn.id,
+    debug!("trans_if(bcx={}, if_id={}, cond={:?}, thn={}, dest={})",
+           bcx.to_str(), if_id, cond, thn.id,
            dest.to_string(bcx.ccx()));
     let _icx = push_ctxt("trans_if");
 
@@ -166,31 +164,15 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let cond_val = unpack_result!(bcx, expr::trans(bcx, cond).to_llbool());
 
     // Drop branches that are known to be impossible
-    if is_const(cond_val) && !is_undef(cond_val) {
-        if const_to_uint(cond_val) == 1 {
-            match els {
-                Some(elexpr) => {
-                    let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx };
-                    trans.visit_expr(&*elexpr);
-                }
-                None => {}
-            }
+    if let Some(cv) = const_to_opt_uint(cond_val) {
+        if cv == 1 {
             // if true { .. } [else { .. }]
             bcx = trans_block(bcx, &*thn, dest);
             trans::debuginfo::clear_source_location(bcx.fcx);
         } else {
-            let mut trans = TransItemVisitor { ccx: bcx.fcx.ccx } ;
-            trans.visit_block(&*thn);
-
-            match els {
-                // if false { .. } else { .. }
-                Some(elexpr) => {
-                    bcx = expr::trans_into(bcx, &*elexpr, dest);
-                    trans::debuginfo::clear_source_location(bcx.fcx);
-                }
-
-                // if false { .. }
-                None => { }
+            if let Some(elexpr) = els {
+                bcx = expr::trans_into(bcx, &*elexpr, dest);
+                trans::debuginfo::clear_source_location(bcx.fcx);
             }
         }
 
index a736a9fe88a1408de7da76457766aa7ca8fa8f52..e60e4e4abe05336712dda9d90333015cb4a68833 100644 (file)
 //! `&foo()` or `match foo() { ref x => ... }`, where the user is
 //! implicitly requesting a temporary.
 //!
-//! Somewhat surprisingly, not all lvalue expressions yield lvalue datums
-//! when trans'd. Ultimately the reason for this is to micro-optimize
-//! the resulting LLVM. For example, consider the following code:
-//!
-//!     fn foo() -> Box<int> { ... }
-//!     let x = *foo();
-//!
-//! The expression `*foo()` is an lvalue, but if you invoke `expr::trans`,
-//! it will return an rvalue datum. See `deref_once` in expr.rs for
-//! more details.
-//!
 //! ### Rvalues in detail
 //!
 //! Rvalues datums are values with no cleanup scheduled. One must be
@@ -113,7 +102,6 @@ use trans::expr;
 use trans::tvec;
 use trans::type_of;
 use middle::ty::{self, Ty};
-use util::ppaux::ty_to_string;
 
 use std::fmt;
 use syntax::ast;
@@ -625,9 +613,9 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> {
 
     #[allow(dead_code)] // useful for debugging
     pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
-        format!("Datum({}, {}, {:?})",
+        format!("Datum({}, {:?}, {:?})",
                 ccx.tn().val_to_string(self.val),
-                ty_to_string(ccx.tcx(), self.ty),
+                self.ty,
                 self.kind)
     }
 
index 9af22b788b77beaf0160dfa8cabe2f5e82762937..304906a666e63f2ad612a836d819466f5d12fc4e 100644 (file)
@@ -257,7 +257,7 @@ fn walk_pattern(cx: &CrateContext,
             for &codemap::Spanned {
                 node: ast::FieldPat { pat: ref sub_pat, .. },
                 ..
-            } in field_pats.iter() {
+            } in field_pats {
                 walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
             }
         }
index ab86cd7cdde5996a7db24362341e8cde6818a2f2..7660f59e1d08b0061bd79a92b0164083f8354cbe 100644 (file)
@@ -26,6 +26,7 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
 use metadata::csearch;
 use middle::pat_util;
 use middle::subst::{self, Substs};
+use rustc::ast_map;
 use trans::{type_of, adt, machine, monomorphize};
 use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
 use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
@@ -33,7 +34,6 @@ use trans::type_::Type;
 use middle::ty::{self, Ty, ClosureTyper};
 use session::config::{self, FullDebugInfo};
 use util::nodemap::FnvHashMap;
-use util::ppaux;
 use util::common::path2cstr;
 
 use libc::{c_uint, c_longlong};
@@ -43,7 +43,7 @@ use std::ptr;
 use std::rc::Rc;
 use syntax::util::interner::Interner;
 use syntax::codemap::Span;
-use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::{ast, codemap, ast_util};
 use syntax::parse::token::{self, special_idents};
 
 
@@ -104,7 +104,7 @@ impl<'tcx> TypeMap<'tcx> {
                                        metadata: DIType) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
             cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
-                                   ppaux::ty_to_string(cx.tcx(), type_)));
+                                   type_));
         }
     }
 
@@ -170,26 +170,26 @@ impl<'tcx> TypeMap<'tcx> {
         unique_type_id.push('{');
 
         match type_.sty {
-            ty::ty_bool     |
-            ty::ty_char     |
-            ty::ty_str      |
-            ty::ty_int(_)   |
-            ty::ty_uint(_)  |
-            ty::ty_float(_) => {
+            ty::TyBool     |
+            ty::TyChar     |
+            ty::TyStr      |
+            ty::TyInt(_)   |
+            ty::TyUint(_)  |
+            ty::TyFloat(_) => {
                 push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
             },
-            ty::ty_enum(def_id, substs) => {
+            ty::TyEnum(def_id, substs) => {
                 unique_type_id.push_str("enum ");
                 from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
             },
-            ty::ty_struct(def_id, substs) => {
+            ty::TyStruct(def_id, substs) => {
                 unique_type_id.push_str("struct ");
                 from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
             },
-            ty::ty_tup(ref component_types) if component_types.is_empty() => {
+            ty::TyTuple(ref component_types) if component_types.is_empty() => {
                 push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
             },
-            ty::ty_tup(ref component_types) => {
+            ty::TyTuple(ref component_types) => {
                 unique_type_id.push_str("tuple ");
                 for &component_type in component_types {
                     let component_type_id =
@@ -199,13 +199,13 @@ impl<'tcx> TypeMap<'tcx> {
                     unique_type_id.push_str(&component_type_id[..]);
                 }
             },
-            ty::ty_uniq(inner_type) => {
+            ty::TyBox(inner_type) => {
                 unique_type_id.push_str("box ");
                 let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
                 let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
                 unique_type_id.push_str(&inner_type_id[..]);
             },
-            ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+            ty::TyRawPtr(ty::mt { ty: inner_type, mutbl } ) => {
                 unique_type_id.push('*');
                 if mutbl == ast::MutMutable {
                     unique_type_id.push_str("mut");
@@ -215,7 +215,7 @@ impl<'tcx> TypeMap<'tcx> {
                 let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
                 unique_type_id.push_str(&inner_type_id[..]);
             },
-            ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+            ty::TyRef(_, ty::mt { ty: inner_type, mutbl }) => {
                 unique_type_id.push('&');
                 if mutbl == ast::MutMutable {
                     unique_type_id.push_str("mut");
@@ -225,21 +225,21 @@ impl<'tcx> TypeMap<'tcx> {
                 let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
                 unique_type_id.push_str(&inner_type_id[..]);
             },
-            ty::ty_vec(inner_type, optional_length) => {
-                match optional_length {
-                    Some(len) => {
-                        unique_type_id.push_str(&format!("[{}]", len));
-                    }
-                    None => {
-                        unique_type_id.push_str("[]");
-                    }
-                };
+            ty::TyArray(inner_type, len) => {
+                unique_type_id.push_str(&format!("[{}]", len));
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(&inner_type_id[..]);
+            },
+            ty::TySlice(inner_type) => {
+                unique_type_id.push_str("[]");
 
                 let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
                 let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
                 unique_type_id.push_str(&inner_type_id[..]);
             },
-            ty::ty_trait(ref trait_data) => {
+            ty::TyTrait(ref trait_data) => {
                 unique_type_id.push_str("trait ");
 
                 let principal =
@@ -252,7 +252,7 @@ impl<'tcx> TypeMap<'tcx> {
                                        principal.substs,
                                        &mut unique_type_id);
             },
-            ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+            ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
                 if unsafety == ast::Unsafety::Unsafe {
                     unique_type_id.push_str("unsafe ");
                 }
@@ -288,7 +288,7 @@ impl<'tcx> TypeMap<'tcx> {
                     }
                 }
             },
-            ty::ty_closure(def_id, substs) => {
+            ty::TyClosure(def_id, substs) => {
                 let typer = NormalizingClosureTyper::new(cx.tcx());
                 let closure_ty = typer.closure_type(def_id, substs);
                 self.get_unique_type_id_of_closure_type(cx,
@@ -296,9 +296,8 @@ impl<'tcx> TypeMap<'tcx> {
                                                         &mut unique_type_id);
             },
             _ => {
-                cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
-                                      &ppaux::ty_to_string(cx.tcx(), type_),
-                                      type_.sty))
+                cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {:?}",
+                                       type_))
             }
         };
 
@@ -488,8 +487,8 @@ impl<'tcx> RecursiveTypeDescription<'tcx> {
                     if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
                        type_map.find_metadata_for_type(unfinished_type).is_none() {
                         cx.sess().bug(&format!("Forward declaration of potentially recursive type \
-                                              '{}' was not found in TypeMap!",
-                                              ppaux::ty_to_string(cx.tcx(), unfinished_type))
+                                              '{:?}' was not found in TypeMap!",
+                                              unfinished_type)
                                       );
                     }
                 }
@@ -634,7 +633,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // return type
     signature_metadata.push(match signature.output {
         ty::FnConverging(ret_ty) => match ret_ty.sty {
-            ty::ty_tup(ref tys) if tys.is_empty() => ptr::null_mut(),
+            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
             _ => type_metadata(cx, ret_ty, span)
         },
         ty::FnDiverging => diverging_type_metadata(cx)
@@ -673,12 +672,11 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // But it does not describe the trait's methods.
 
     let def_id = match trait_type.sty {
-        ty::ty_trait(ref data) => data.principal_def_id(),
+        ty::TyTrait(ref data) => data.principal_def_id(),
         _ => {
-            let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
             cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
-                                   trait_pointer_metadata(): {}",
-                                   &pp_type_name[..]));
+                                   trait_pointer_metadata(): {:?}",
+                                   trait_type));
         }
     };
 
@@ -741,39 +739,42 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let sty = &t.sty;
     let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
-        ty::ty_bool     |
-        ty::ty_char     |
-        ty::ty_int(_)   |
-        ty::ty_uint(_)  |
-        ty::ty_float(_) => {
+        ty::TyBool     |
+        ty::TyChar     |
+        ty::TyInt(_)   |
+        ty::TyUint(_)  |
+        ty::TyFloat(_) => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::ty_tup(ref elements) if elements.is_empty() => {
+        ty::TyTuple(ref elements) if elements.is_empty() => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::ty_enum(def_id, _) => {
+        ty::TyEnum(def_id, _) => {
             prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
         }
-        ty::ty_vec(typ, len) => {
-            fixed_vec_metadata(cx, unique_type_id, typ, len.map(|x| x as u64), usage_site_span)
+        ty::TyArray(typ, len) => {
+            fixed_vec_metadata(cx, unique_type_id, typ, Some(len as u64), usage_site_span)
+        }
+        ty::TySlice(typ) => {
+            fixed_vec_metadata(cx, unique_type_id, typ, None, usage_site_span)
         }
-        ty::ty_str => {
+        ty::TyStr => {
             fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
         }
-        ty::ty_trait(..) => {
+        ty::TyTrait(..) => {
             MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, None, unique_type_id),
             false)
         }
-        ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+        ty::TyBox(ty) | ty::TyRawPtr(ty::mt{ty, ..}) | ty::TyRef(_, ty::mt{ty, ..}) => {
             match ty.sty {
-                ty::ty_vec(typ, None) => {
+                ty::TySlice(typ) => {
                     vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
                 }
-                ty::ty_str => {
+                ty::TyStr => {
                     vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
                 }
-                ty::ty_trait(..) => {
+                ty::TyTrait(..) => {
                     MetadataCreationResult::new(
                         trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
                         false)
@@ -793,15 +794,15 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ty::ty_bare_fn(_, ref barefnty) => {
+        ty::TyBareFn(_, ref barefnty) => {
             subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
         }
-        ty::ty_closure(def_id, substs) => {
+        ty::TyClosure(def_id, substs) => {
             let typer = NormalizingClosureTyper::new(cx.tcx());
             let sig = typer.closure_type(def_id, substs).sig;
             subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
         }
-        ty::ty_struct(def_id, substs) => {
+        ty::TyStruct(def_id, substs) => {
             prepare_struct_metadata(cx,
                                     t,
                                     def_id,
@@ -809,7 +810,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                     unique_type_id,
                                     usage_site_span).finalize(cx)
         }
-        ty::ty_tup(ref elements) => {
+        ty::TyTuple(ref elements) => {
             prepare_tuple_metadata(cx,
                                    t,
                                    &elements[..],
@@ -837,7 +838,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                  the debuginfo::TypeMap but it \
                                                  was not. (Ty = {})",
                                                 &unique_type_id_str[..],
-                                                ppaux::ty_to_string(cx.tcx(), t));
+                                                t);
                     cx.sess().span_bug(usage_site_span, &error_message[..]);
                 }
             };
@@ -852,7 +853,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                      debuginfo::TypeMap. \
                                                      UniqueTypeId={}, Ty={}",
                             &unique_type_id_str[..],
-                            ppaux::ty_to_string(cx.tcx(), t));
+                            t);
                         cx.sess().span_bug(usage_site_span, &error_message[..]);
                     }
                 }
@@ -935,25 +936,25 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     debug!("basic_type_metadata: {:?}", t);
 
     let (name, encoding) = match t.sty {
-        ty::ty_tup(ref elements) if elements.is_empty() =>
+        ty::TyTuple(ref elements) if elements.is_empty() =>
             ("()".to_string(), DW_ATE_unsigned),
-        ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
-        ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
-        ty::ty_int(int_ty) => match int_ty {
+        ty::TyBool => ("bool".to_string(), DW_ATE_boolean),
+        ty::TyChar => ("char".to_string(), DW_ATE_unsigned_char),
+        ty::TyInt(int_ty) => match int_ty {
             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::ty_uint(uint_ty) => match uint_ty {
+        ty::TyUint(uint_ty) => match uint_ty {
             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::ty_float(float_ty) => match float_ty {
+        ty::TyFloat(float_ty) => match float_ty {
             ast::TyF32 => ("f32".to_string(), DW_ATE_float),
             ast::TyF64 => ("f64".to_string(), DW_ATE_float),
         },
@@ -1178,7 +1179,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let mut fields = ty::struct_fields(cx.tcx(), def_id, substs);
 
     // The `Ty` values returned by `ty::struct_fields` can still contain
-    // `ty_projection` variants, so normalize those away.
+    // `TyProjection` variants, so normalize those away.
     for field in &mut fields {
         field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty);
     }
@@ -1556,7 +1557,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     // Build an array of (field name, field type) pairs to be captured in the factory closure.
     let args: Vec<(String, Ty)> = arg_names.iter()
-        .zip(struct_def.fields.iter())
+        .zip(&struct_def.fields)
         .map(|(s, &t)| (s.to_string(), t))
         .collect();
 
@@ -1673,7 +1674,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         DIB(cx),
         containing_scope,
         enum_name.as_ptr(),
-        UNKNOWN_FILE_METADATA,
+        file_metadata,
         UNKNOWN_LINE_NUMBER,
         bytes_to_bits(enum_type_size),
         bytes_to_bits(enum_type_align),
index e4312b669ad98d2cce97fbb5b57944cddb729033..06f1a56c6ef1f8a351bf4573a1fda3df2da7ae82 100644 (file)
@@ -26,6 +26,7 @@ use llvm::{ModuleRef, ContextRef, ValueRef};
 use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
                       DIDescriptor, FlagPrototyped};
 use middle::subst::{self, Substs};
+use rustc::ast_map;
 use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
 use trans;
 use trans::monomorphize;
@@ -39,7 +40,7 @@ use std::ffi::CString;
 use std::ptr;
 use std::rc::Rc;
 use syntax::codemap::{Span, Pos};
-use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::{ast, codemap, ast_util};
 use syntax::parse::token::{self, special_idents};
 
 pub mod gdb;
@@ -193,7 +194,7 @@ pub fn finalize(cx: &CrateContext) {
         // Prevent bitcode readers from deleting the debug info.
         let ptr = "Debug Info Version\0".as_ptr();
         llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
-                                    llvm::LLVMRustDebugMetadataVersion);
+                                    llvm::LLVMRustDebugMetadataVersion());
     };
 }
 
@@ -232,7 +233,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
 
             match item.node {
-                ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => {
+                ast::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
                     (item.ident.name, fn_decl, generics, top_level_block, item.span, true)
                 }
                 _ => {
@@ -331,7 +332,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     // Get_template_parameters() will append a `<...>` clause to the function
     // name if necessary.
-    let mut function_name = String::from_str(&token::get_name(name));
+    let mut function_name = String::from(&*token::get_name(name));
     let template_parameters = get_template_parameters(cx,
                                                       generics,
                                                       param_substs,
@@ -484,10 +485,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let param_metadata = unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
-                        file_metadata,
+                        ptr::null_mut(),
                         name.as_ptr(),
                         actual_self_type_metadata,
-                        ptr::null_mut(),
+                        file_metadata,
                         0,
                         0)
                 };
@@ -518,10 +519,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let param_metadata = unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
-                        file_metadata,
+                        ptr::null_mut(),
                         name.as_ptr(),
                         actual_type_metadata,
-                        ptr::null_mut(),
+                        file_metadata,
                         0,
                         0)
                 };
@@ -580,12 +581,14 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                                           loc.line,
                                                                           loc.col.to_usize()));
             unsafe {
+                let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
                 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
                     DIB(cx),
                     alloca,
                     metadata,
                     address_operations.as_ptr(),
                     address_operations.len() as c_uint,
+                    debug_loc,
                     bcx.llbb);
 
                 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
index 0aa0408c0ef33c31a89fd1566901207dfa7b56cb..e6fe674f22057f521688d75fba1195092d6e8742 100644 (file)
@@ -14,13 +14,14 @@ use super::utils::{DIB, debug_context};
 
 use llvm;
 use llvm::debuginfo::DIScope;
+use rustc::ast_map;
 use trans::common::CrateContext;
 use middle::ty::{self, ClosureTyper};
 
 use std::ffi::CString;
 use std::ptr;
 use std::rc::{Rc, Weak};
-use syntax::{ast, ast_map};
+use syntax::ast;
 use syntax::parse::token;
 
 pub struct NamespaceTreeNode {
@@ -41,7 +42,7 @@ impl NamespaceTreeNode {
             output.push_str(&string);
         }
 
-        let mut name = String::from_str("_ZN");
+        let mut name = String::from("_ZN");
         fill_nested(self, &mut name);
         name.push_str(&format!("{}", item_name.len()));
         name.push_str(item_name);
index 2d0003d93a5d25a8a63e332fc42418331e8973a8..5ba5ecb02c024c1b9f51cd63d0b78fc77bf527df 100644 (file)
@@ -15,9 +15,9 @@ use super::namespace::crate_root_namespace;
 use trans::common::CrateContext;
 use middle::subst::{self, Substs};
 use middle::ty::{self, Ty, ClosureTyper};
+
 use syntax::ast;
 use syntax::parse::token;
-use util::ppaux;
 
 
 // Compute the name of the type as it should be stored in debuginfo. Does not do
@@ -40,27 +40,27 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                           qualified: bool,
                                           output: &mut String) {
     match t.sty {
-        ty::ty_bool              => output.push_str("bool"),
-        ty::ty_char              => output.push_str("char"),
-        ty::ty_str               => output.push_str("str"),
-        ty::ty_int(ast::TyIs)     => output.push_str("isize"),
-        ty::ty_int(ast::TyI8)    => output.push_str("i8"),
-        ty::ty_int(ast::TyI16)   => output.push_str("i16"),
-        ty::ty_int(ast::TyI32)   => output.push_str("i32"),
-        ty::ty_int(ast::TyI64)   => output.push_str("i64"),
-        ty::ty_uint(ast::TyUs)    => output.push_str("usize"),
-        ty::ty_uint(ast::TyU8)   => output.push_str("u8"),
-        ty::ty_uint(ast::TyU16)  => output.push_str("u16"),
-        ty::ty_uint(ast::TyU32)  => output.push_str("u32"),
-        ty::ty_uint(ast::TyU64)  => output.push_str("u64"),
-        ty::ty_float(ast::TyF32) => output.push_str("f32"),
-        ty::ty_float(ast::TyF64) => output.push_str("f64"),
-        ty::ty_struct(def_id, substs) |
-        ty::ty_enum(def_id, substs) => {
+        ty::TyBool              => output.push_str("bool"),
+        ty::TyChar              => output.push_str("char"),
+        ty::TyStr               => output.push_str("str"),
+        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_id, substs) |
+        ty::TyEnum(def_id, substs) => {
             push_item_name(cx, def_id, qualified, output);
             push_type_params(cx, substs, output);
         },
-        ty::ty_tup(ref component_types) => {
+        ty::TyTuple(ref component_types) => {
             output.push('(');
             for &component_type in component_types {
                 push_debuginfo_type_name(cx, component_type, true, output);
@@ -72,12 +72,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
             output.push(')');
         },
-        ty::ty_uniq(inner_type) => {
+        ty::TyBox(inner_type) => {
             output.push_str("Box<");
             push_debuginfo_type_name(cx, inner_type, true, output);
             output.push('>');
         },
-        ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+        ty::TyRawPtr(ty::mt { ty: inner_type, mutbl } ) => {
             output.push('*');
             match mutbl {
                 ast::MutImmutable => output.push_str("const "),
@@ -86,7 +86,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             push_debuginfo_type_name(cx, inner_type, true, output);
         },
-        ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+        ty::TyRef(_, ty::mt { ty: inner_type, mutbl }) => {
             output.push('&');
             if mutbl == ast::MutMutable {
                 output.push_str("mut ");
@@ -94,25 +94,23 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             push_debuginfo_type_name(cx, inner_type, true, output);
         },
-        ty::ty_vec(inner_type, optional_length) => {
+        ty::TyArray(inner_type, len) => {
+            output.push('[');
+            push_debuginfo_type_name(cx, inner_type, true, output);
+            output.push_str(&format!("; {}", len));
+            output.push(']');
+        },
+        ty::TySlice(inner_type) => {
             output.push('[');
             push_debuginfo_type_name(cx, inner_type, true, output);
-
-            match optional_length {
-                Some(len) => {
-                    output.push_str(&format!("; {}", len));
-                }
-                None => { /* nothing to do */ }
-            };
-
             output.push(']');
         },
-        ty::ty_trait(ref trait_data) => {
+        ty::TyTrait(ref trait_data) => {
             let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal);
             push_item_name(cx, principal.def_id, false, output);
             push_type_params(cx, principal.substs, output);
         },
-        ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+        ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
             if unsafety == ast::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
@@ -156,15 +154,15 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         },
-        ty::ty_closure(..) => {
+        ty::TyClosure(..) => {
             output.push_str("closure");
         }
-        ty::ty_err |
-        ty::ty_infer(_) |
-        ty::ty_projection(..) |
-        ty::ty_param(_) => {
+        ty::TyError |
+        ty::TyInfer(_) |
+        ty::TyProjection(..) |
+        ty::TyParam(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
-                unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)));
+                unexpected type: {:?}", t));
         }
     }
 
@@ -216,7 +214,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
         output.push('<');
 
-        for &type_parameter in substs.types.iter() {
+        for &type_parameter in &substs.types {
             push_debuginfo_type_name(cx, type_parameter, true, output);
             output.push_str(", ");
         }
index 7849235fdbee5b9e044eeeafef632edf2c6063f9..8bc3326d30093ea598f9b11f0ed6dcde339faf5f 100644 (file)
@@ -9,14 +9,14 @@
 // except according to those terms.
 //! Declare various LLVM values.
 //!
-//! Prefer using functions and methods from this module rather than calling LLVM functions
-//! directly. These functions do some additional work to ensure we do the right thing given
-//! the preconceptions of trans.
+//! Prefer using functions and methods from this module rather than calling LLVM
+//! functions directly. These functions do some additional work to ensure we do
+//! the right thing given the preconceptions of trans.
 //!
 //! Some useful guidelines:
 //!
-//! * Use declare_* family of methods if you are declaring, but are not interested in defining the
-//! ValueRef they return.
+//! * Use declare_* family of methods if you are declaring, but are not
+//!   interested in defining the ValueRef they return.
 //! * Use define_* family of methods when you might be defining the ValueRef.
 //! * When in doubt, define.
 use llvm::{self, ValueRef};
@@ -29,7 +29,6 @@ use trans::context::CrateContext;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
-use util::ppaux::Repr;
 
 use std::ffi::CString;
 use libc::c_uint;
@@ -37,8 +36,8 @@ use libc::c_uint;
 
 /// Declare a global value.
 ///
-/// If there’s a value with the same name already declared, the function will return its ValueRef
-/// instead.
+/// If there’s a value with the same name already declared, the function will
+/// return its ValueRef instead.
 pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef {
     debug!("declare_global(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
@@ -54,10 +53,10 @@ pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRe
 ///
 /// For rust functions use `declare_rust_fn` instead.
 ///
-/// If there’s a value with the same name already declared, the function will update the
-/// declaration and return existing ValueRef instead.
-pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type,
-                  output: ty::FnOutput) -> ValueRef {
+/// If there’s a value with the same name already declared, the function will
+/// update the declaration and return existing ValueRef instead.
+pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
+                  ty: Type, output: ty::FnOutput) -> ValueRef {
     debug!("declare_fn(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
         ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))
@@ -67,7 +66,8 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
-    // Function addresses in Rust are never significant, allowing functions to be merged.
+    // Function addresses in Rust are never significant, allowing functions to
+    // be merged.
     llvm::SetUnnamedAddr(llfn, true);
 
     if output == ty::FnDiverging {
@@ -88,50 +88,53 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
 
 /// Declare a C ABI function.
 ///
-/// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn`
-/// instead.
+/// Only use this for foreign function ABIs and glue. For Rust functions use
+/// `declare_rust_fn` instead.
 ///
-/// If there’s a value with the same name already declared, the function will update the
-/// declaration and return existing ValueRef instead.
-pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type, output: ty::Ty) -> ValueRef {
+/// If there’s a value with the same name already declared, the function will
+/// update the declaration and return existing ValueRef instead.
+pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type,
+                   output: ty::Ty) -> ValueRef {
     declare_fn(ccx, name, llvm::CCallConv, fn_type, ty::FnConverging(output))
 }
 
 
 /// Declare a Rust function.
 ///
-/// If there’s a value with the same name already declared, the function will update the
-/// declaration and return existing ValueRef instead.
+/// If there’s a value with the same name already declared, the function will
+/// update the declaration and return existing ValueRef instead.
 pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
                                  fn_type: ty::Ty<'tcx>) -> ValueRef {
-    debug!("declare_rust_fn(name={:?}, fn_type={})", name, fn_type.repr(ccx.tcx()));
+    debug!("declare_rust_fn(name={:?}, fn_type={:?})", name,
+           fn_type);
     let fn_type = monomorphize::normalize_associated_type(ccx.tcx(), &fn_type);
-    debug!("declare_rust_fn (after normalised associated types) fn_type={}",
-           fn_type.repr(ccx.tcx()));
+    debug!("declare_rust_fn (after normalised associated types) fn_type={:?}",
+           fn_type);
 
     let function_type; // placeholder so that the memory ownership works out ok
     let (sig, abi, env) = match fn_type.sty {
-        ty::ty_bare_fn(_, ref f) => {
+        ty::TyBareFn(_, ref f) => {
             (&f.sig, f.abi, None)
         }
-        ty::ty_closure(closure_did, substs) => {
+        ty::TyClosure(closure_did, substs) => {
             let typer = common::NormalizingClosureTyper::new(ccx.tcx());
             function_type = typer.closure_type(closure_did, substs);
             let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
             let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
-            debug!("declare_rust_fn function_type={} self_type={}",
-                   function_type.repr(ccx.tcx()), self_type.repr(ccx.tcx()));
+            debug!("declare_rust_fn function_type={:?} self_type={:?}",
+                   function_type, self_type);
             (&function_type.sig, abi::RustCall, Some(llenvironment_type))
         }
         _ => ccx.sess().bug("expected closure or fn")
     };
 
     let sig = ty::Binder(ty::erase_late_bound_regions(ccx.tcx(), sig));
-    debug!("declare_rust_fn (after region erasure) sig={}", sig.repr(ccx.tcx()));
+    debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
     let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi);
     debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty));
 
-    // it is ok to directly access sig.0.output because we erased all late-bound-regions above
+    // it is ok to directly access sig.0.output because we erased all
+    // late-bound-regions above
     let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output);
     attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn);
     llfn
@@ -140,8 +143,8 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
 
 /// Declare a Rust function with internal linkage.
 ///
-/// If there’s a value with the same name already declared, the function will update the
-/// declaration and return existing ValueRef instead.
+/// If there’s a value with the same name already declared, the function will
+/// update the declaration and return existing ValueRef instead.
 pub fn declare_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
                                           fn_type: ty::Ty<'tcx>) -> ValueRef {
     let llfn = declare_rust_fn(ccx, name, fn_type);
@@ -152,10 +155,10 @@ pub fn declare_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &s
 
 /// Declare a global with an intention to define it.
 ///
-/// Use this function when you intend to define a global. This function will return None if the
-/// name already has a definition associated with it. In that case an error should be reported to
-/// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or
-/// #[export_name] attributes).
+/// Use this function when you intend to define a global. This function will
+/// return None if the name already has a definition associated with it. In that
+/// case an error should be reported to the user, because it usually happens due
+/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
 pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> {
     if get_defined_value(ccx, name).is_some() {
         None
@@ -169,10 +172,10 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
 ///
 /// For rust functions use `define_rust_fn` instead.
 ///
-/// Use this function when you intend to define a function. This function will return None if the
-/// name already has a definition associated with it. In that case an error should be reported to
-/// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or
-/// #[export_name] attributes).
+/// Use this function when you intend to define a function. This function will
+/// return None if the name already has a definition associated with it. In that
+/// case an error should be reported to the user, because it usually happens due
+/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
 pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, fn_type: Type,
                  output: ty::FnOutput) -> Option<ValueRef> {
     if get_defined_value(ccx, name).is_some() {
@@ -185,13 +188,13 @@ pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, fn_ty
 
 /// Declare a C ABI function with an intention to define it.
 ///
-/// Use this function when you intend to define a function. This function will return None if the
-/// name already has a definition associated with it. In that case an error should be reported to
-/// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or
-/// #[export_name] attributes).
+/// Use this function when you intend to define a function. This function will
+/// return None if the name already has a definition associated with it. In that
+/// case an error should be reported to the user, because it usually happens due
+/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
 ///
-/// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn`
-/// instead.
+/// Only use this for foreign function ABIs and glue. For Rust functions use
+/// `declare_rust_fn` instead.
 pub fn define_cfn(ccx: &CrateContext, name: &str, fn_type: Type,
                   output: ty::Ty) -> Option<ValueRef> {
     if get_defined_value(ccx, name).is_some() {
@@ -204,10 +207,10 @@ pub fn define_cfn(ccx: &CrateContext, name: &str, fn_type: Type,
 
 /// Declare a Rust function with an intention to define it.
 ///
-/// Use this function when you intend to define a function. This function will return None if the
-/// name already has a definition associated with it. In that case an error should be reported to
-/// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or
-/// #[export_name] attributes).
+/// Use this function when you intend to define a function. This function will
+/// return None if the name already has a definition associated with it. In that
+/// case an error should be reported to the user, because it usually happens due
+/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
 pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
                                 fn_type: ty::Ty<'tcx>) -> Option<ValueRef> {
     if get_defined_value(ccx, name).is_some() {
@@ -220,10 +223,10 @@ pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
 
 /// Declare a Rust function with an intention to define it.
 ///
-/// Use this function when you intend to define a function. This function will return None if the
-/// name already has a definition associated with it. In that case an error should be reported to
-/// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or
-/// #[export_name] attributes).
+/// Use this function when you intend to define a function. This function will
+/// return None if the name already has a definition associated with it. In that
+/// case an error should be reported to the user, because it usually happens due
+/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
 pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
                                          fn_type: ty::Ty<'tcx>) -> Option<ValueRef> {
     if get_defined_value(ccx, name).is_some() {
@@ -250,8 +253,8 @@ fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
             (llvm::LLVMIsDeclaration(val) != 0,
              linkage == llvm::AvailableExternallyLinkage as c_uint)
         };
-        debug!("get_defined_value: found {:?} value (declaration: {}, aext_link: {})", name,
-               declaration, aext_link);
+        debug!("get_defined_value: found {:?} value (declaration: {}, \
+                aext_link: {})", name, declaration, aext_link);
         if !declaration || aext_link {
             Some(val)
         } else {
index 270aacfe143df2ac3846dc06ddca4ab9d5957bb5..5ee7159493534dcedc202ca3c45faf8adc044f2e 100644 (file)
 
 #![allow(non_camel_case_types)]
 
-pub use self::cast_kind::*;
 pub use self::Dest::*;
 use self::lazy_binop_ty::*;
 
 use back::abi;
-use llvm::{self, ValueRef};
+use llvm::{self, ValueRef, TypeKind};
 use middle::check_const;
 use middle::def;
 use middle::lang_items::CoerceUnsizedTraitLangItem;
@@ -73,12 +72,12 @@ use trans::meth;
 use trans::monomorphize;
 use trans::tvec;
 use trans::type_of;
+use middle::cast::{CastKind, CastTy};
 use middle::ty::{struct_fields, tup_fields};
 use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustUnsafeFnPointer};
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 use util::common::indenter;
-use util::ppaux::Repr;
 use trans::machine::{llsize_of, llsize_of_alloc};
 use trans::type_::Type;
 
@@ -139,9 +138,12 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // have different types.
                 let lldest = PointerCast(bcx, lldest, val_ty(global));
                 memcpy_ty(bcx, lldest, global, expr_ty_adjusted(bcx, expr));
+                return bcx;
             }
-            // Don't do anything in the Ignore case, consts don't need drop.
-            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
+            // body of any closures.
+            // FIXME: Find a better way of handling this case.
         } else {
             // The only way we're going to see a `const` at this point is if
             // it prefers in-place instantiation, likely because it contains
@@ -178,7 +180,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
     }
 
-    debug!("trans_into() expr={}", expr.repr(bcx.tcx()));
+    debug!("trans_into() expr={:?}", expr);
 
     let cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(bcx.ccx(),
                                                                           expr.id,
@@ -186,15 +188,15 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                                           false);
     bcx.fcx.push_ast_cleanup_scope(cleanup_debug_loc);
 
-    let kind = ty::expr_kind(bcx.tcx(), expr);
+    let kind = expr_kind(bcx.tcx(), expr);
     bcx = match kind {
-        ty::LvalueExpr | ty::RvalueDatumExpr => {
+        ExprKind::Lvalue | ExprKind::RvalueDatum => {
             trans_unadjusted(bcx, expr).store_to_dest(dest, expr.id)
         }
-        ty::RvalueDpsExpr => {
+        ExprKind::RvalueDps => {
             trans_rvalue_dps_unadjusted(bcx, expr, dest)
         }
-        ty::RvalueStmtExpr => {
+        ExprKind::RvalueStmt => {
             trans_rvalue_stmt_unadjusted(bcx, expr)
         }
     };
@@ -208,7 +210,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                          expr: &ast::Expr)
                          -> DatumBlock<'blk, 'tcx, Expr> {
-    debug!("trans(expr={})", bcx.expr_to_string(expr));
+    debug!("trans(expr={:?})", expr);
 
     let mut bcx = bcx;
     let fcx = bcx.fcx;
@@ -291,6 +293,9 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
     GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
 }
 
+pub fn make_fat_ptr(bcx: Block, ty: Type, data: ValueRef, extra: ValueRef) -> ValueRef {
+    InsertValue(bcx, InsertValue(bcx, C_undef(ty), data, 0), extra, 1)
+}
 pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
     Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
     Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));
@@ -310,14 +315,14 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
                                 -> ValueRef {
     let (source, target) = ty::struct_lockstep_tails(ccx.tcx(), source, target);
     match (&source.sty, &target.sty) {
-        (&ty::ty_vec(_, Some(len)), &ty::ty_vec(_, None)) => C_uint(ccx, len),
-        (&ty::ty_trait(_), &ty::ty_trait(_)) => {
+        (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len),
+        (&ty::TyTrait(_), &ty::TyTrait(_)) => {
             // For now, upcasts are limited to changes in marker
             // traits, and hence never actually require an actual
             // change to the vtable.
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
-        (_, &ty::ty_trait(box ty::TyTrait { ref principal, .. })) => {
+        (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => {
             // Note that we preserve binding levels here:
             let substs = principal.0.substs.with_self_ty(source).erase_regions();
             let substs = ccx.tcx().mk_substs(substs);
@@ -326,9 +331,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
             consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs),
                             Type::vtable_ptr(ccx))
         }
-        _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {} -> {}",
-                                     source.repr(ccx.tcx()),
-                                     target.repr(ccx.tcx())))
+        _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {:?} -> {:?}",
+                                     source,
+                                     target))
     }
 }
 
@@ -347,8 +352,8 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         Some(adj) => { adj }
     };
-    debug!("unadjusted datum for expr {}: {} adjustment={:?}",
-           expr.repr(bcx.tcx()),
+    debug!("unadjusted datum for expr {:?}: {} adjustment={:?}",
+           expr,
            datum.to_string(bcx.ccx()),
            adjustment);
     match adjustment {
@@ -366,7 +371,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // a different region or mutability, but we don't care here).
                 match datum.ty.sty {
                     // Don't skip a conversion from Box<T> to &T, etc.
-                    ty::ty_rptr(..) => {
+                    ty::TyRef(..) => {
                         let method_call = MethodCall::autoderef(expr.id, 0);
                         if bcx.tcx().method_map.borrow().contains_key(&method_call) {
                             // Don't skip an overloaded deref.
@@ -439,10 +444,10 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            target.to_string(bcx.ccx()));
 
     match (&source.ty.sty, &target.ty.sty) {
-        (&ty::ty_uniq(a), &ty::ty_uniq(b)) |
-        (&ty::ty_rptr(_, ty::mt { ty: a, .. }), &ty::ty_rptr(_, ty::mt { ty: b, .. })) |
-        (&ty::ty_rptr(_, ty::mt { ty: a, .. }), &ty::ty_ptr(ty::mt { ty: b, .. })) |
-        (&ty::ty_ptr(ty::mt { ty: a, .. }), &ty::ty_ptr(ty::mt { ty: b, .. })) => {
+        (&ty::TyBox(a), &ty::TyBox(b)) |
+        (&ty::TyRef(_, ty::mt { ty: a, .. }), &ty::TyRef(_, ty::mt { ty: b, .. })) |
+        (&ty::TyRef(_, ty::mt { ty: a, .. }), &ty::TyRawPtr(ty::mt { ty: b, .. })) |
+        (&ty::TyRawPtr(ty::mt { ty: a, .. }), &ty::TyRawPtr(ty::mt { ty: b, .. })) => {
             let (inner_source, inner_target) = (a, b);
 
             let (base, old_info) = if !type_is_sized(bcx.tcx(), inner_source) {
@@ -476,8 +481,8 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
 
         // This can be extended to enums and tuples in the future.
-        // (&ty::ty_enum(def_id_a, _), &ty::ty_enum(def_id_b, _)) |
-        (&ty::ty_struct(def_id_a, _), &ty::ty_struct(def_id_b, _)) => {
+        // (&ty::TyEnum(def_id_a, _), &ty::TyEnum(def_id_b, _)) |
+        (&ty::TyStruct(def_id_a, _), &ty::TyStruct(def_id_b, _)) => {
             assert_eq!(def_id_a, def_id_b);
 
             // The target is already by-ref because it's to be written to.
@@ -498,8 +503,8 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     ty::custom_coerce_unsized_kind(bcx.tcx(), impl_def_id)
                 }
                 vtable => {
-                    bcx.sess().span_bug(span, &format!("invalid CoerceUnsized vtable: {}",
-                                                       vtable.repr(bcx.tcx())));
+                    bcx.sess().span_bug(span, &format!("invalid CoerceUnsized vtable: {:?}",
+                                                       vtable));
                 }
             };
 
@@ -523,7 +528,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             assert!(coerce_index < src_fields.len() && src_fields.len() == target_fields.len());
 
-            let iter = src_fields.iter().zip(target_fields.iter()).enumerate();
+            let iter = src_fields.iter().zip(target_fields).enumerate();
             for (i, (src_ty, target_ty)) in iter {
                 let ll_source = adt::trans_field_ptr(bcx, &repr_source, source.val, 0, i);
                 let ll_target = adt::trans_field_ptr(bcx, &repr_target, target.val, 0, i);
@@ -542,9 +547,9 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        _ => bcx.sess().bug(&format!("coerce_unsized: invalid coercion {} -> {}",
-                                     source.ty.repr(bcx.tcx()),
-                                     target.ty.repr(bcx.tcx())))
+        _ => bcx.sess().bug(&format!("coerce_unsized: invalid coercion {:?} -> {:?}",
+                                     source.ty,
+                                     target.ty))
     }
     bcx
 }
@@ -572,13 +577,13 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 -> DatumBlock<'blk, 'tcx, Expr> {
     let mut bcx = bcx;
 
-    debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr));
+    debug!("trans_unadjusted(expr={:?})", expr);
     let _indenter = indenter();
 
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
-    return match ty::expr_kind(bcx.tcx(), expr) {
-        ty::LvalueExpr | ty::RvalueDatumExpr => {
+    return match expr_kind(bcx.tcx(), expr) {
+        ExprKind::Lvalue | ExprKind::RvalueDatum => {
             let datum = unpack_datum!(bcx, {
                 trans_datum_unadjusted(bcx, expr)
             });
@@ -586,12 +591,12 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             DatumBlock {bcx: bcx, datum: datum}
         }
 
-        ty::RvalueStmtExpr => {
+        ExprKind::RvalueStmt => {
             bcx = trans_rvalue_stmt_unadjusted(bcx, expr);
             nil(bcx, expr_ty(bcx, expr))
         }
 
-        ty::RvalueDpsExpr => {
+        ExprKind::RvalueDps => {
             let ty = expr_ty(bcx, expr);
             if type_is_zero_size(bcx.ccx(), ty) {
                 bcx = trans_rvalue_dps_unadjusted(bcx, expr, Ignore);
@@ -654,7 +659,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let box_ty = expr_ty(bcx, expr);
             let contents_ty = expr_ty(bcx, &**contents);
             match box_ty.sty {
-                ty::ty_uniq(..) => {
+                ty::TyBox(..) => {
                     trans_uniq_expr(bcx, expr, box_ty, &**contents, contents_ty)
                 }
                 _ => bcx.sess().span_bug(expr.span,
@@ -730,8 +735,9 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             let info = Load(bcx, get_len(bcx, base_datum.val));
             Store(bcx, info, get_len(bcx, scratch.val));
 
-            DatumBlock::new(bcx, scratch.to_expr_datum())
-
+            // Always generate an lvalue datum, because this pointer doesn't own
+            // the data and cleanup is scheduled elsewhere.
+            DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr))
         }
     })
 
@@ -1144,7 +1150,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
             };
-            closure::trans_closure_expr(dest, &**decl, &**body, expr.id, bcx.fcx.param_substs)
+            closure::trans_closure_expr(dest, decl, body, expr.id, bcx.fcx.param_substs)
                 .unwrap_or(bcx)
         }
         ast::ExprCall(ref f, ref args) => {
@@ -1241,7 +1247,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         def::DefStruct(_) => {
             let ty = expr_ty(bcx, ref_expr);
             match ty.sty {
-                ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
+                ty::TyStruct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
                     adt::trans_set_discr(bcx, &*repr, lldest, 0);
                 }
@@ -1277,9 +1283,9 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         _ => {
             ccx.tcx().sess.span_bug(ref_expr.span, &format!(
-                    "trans_def_fn_unadjusted invoked on: {:?} for {}",
+                    "trans_def_fn_unadjusted invoked on: {:?} for {:?}",
                     def,
-                    ref_expr.repr(ccx.tcx())));
+                    ref_expr));
         }
     }
 }
@@ -1313,7 +1319,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             };
             debug!("take_local(nid={}, v={}, ty={})",
-                   nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty));
+                   nid, bcx.val_to_string(datum.val), datum.ty);
             datum
         }
         _ => {
@@ -1335,24 +1341,24 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
     F: FnOnce(ty::Disr, &[ty::field<'tcx>]) -> R,
 {
     match ty.sty {
-        ty::ty_struct(did, substs) => {
+        ty::TyStruct(did, substs) => {
             let fields = struct_fields(tcx, did, substs);
             let fields = monomorphize::normalize_associated_type(tcx, &fields);
             op(0, &fields[..])
         }
 
-        ty::ty_tup(ref v) => {
+        ty::TyTuple(ref v) => {
             op(0, &tup_fields(&v[..]))
         }
 
-        ty::ty_enum(_, substs) => {
+        ty::TyEnum(_, substs) => {
             // We want the *variant* ID here, not the enum ID.
             match node_id_opt {
                 None => {
                     tcx.sess.bug(&format!(
-                        "cannot get field types from the enum type {} \
+                        "cannot get field types from the enum type {:?} \
                          without a node ID",
-                        ty.repr(tcx)));
+                        ty));
                 }
                 Some(node_id) => {
                     let def = tcx.def_map.borrow().get(&node_id).unwrap().full_def();
@@ -1374,8 +1380,8 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
 
         _ => {
             tcx.sess.bug(&format!(
-                "cannot get field types from the type {}",
-                ty.repr(tcx)));
+                "cannot get field types from the type {:?}",
+                ty));
         }
     }
 }
@@ -1525,11 +1531,13 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         // Second, trans the base to the dest.
         assert_eq!(discr, 0);
 
-        match ty::expr_kind(bcx.tcx(), &*base.expr) {
-            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !bcx.fcx.type_needs_drop(ty) => {
+        match expr_kind(bcx.tcx(), &*base.expr) {
+            ExprKind::RvalueDps | ExprKind::RvalueDatum if !bcx.fcx.type_needs_drop(ty) => {
                 bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
             },
-            ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
+            ExprKind::RvalueStmt => {
+                bcx.tcx().sess.bug("unexpected expr kind for struct base expr")
+            }
             _ => {
                 let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
                 for &(i, t) in &base.fields {
@@ -1543,7 +1551,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
 
         // Finally, move scratch field values into actual field locations
-        for (i, datum) in scratch_vals.into_iter() {
+        for (i, datum) in scratch_vals {
             let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
             bcx = datum.store_to(bcx, dest);
         }
@@ -1955,6 +1963,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                          args: &'a [P<ast::Expr>],
                                          dest: Option<Dest>)
                                          -> Block<'blk, 'tcx> {
+    debug!("trans_overloaded_call {}", expr.id);
     let method_call = MethodCall::expr(expr.id);
     let method_type = bcx.tcx()
                          .method_map
@@ -1981,177 +1990,147 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     bcx
 }
 
-fn int_cast(bcx: Block,
-            lldsttype: Type,
-            llsrctype: Type,
-            llsrc: ValueRef,
-            signed: bool)
-            -> ValueRef {
-    let _icx = push_ctxt("int_cast");
-    let srcsz = llsrctype.int_width();
-    let dstsz = lldsttype.int_width();
-    return if dstsz == srcsz {
-        BitCast(bcx, llsrc, lldsttype)
-    } else if srcsz > dstsz {
-        TruncOrBitCast(bcx, llsrc, lldsttype)
-    } else if signed {
-        SExtOrBitCast(bcx, llsrc, lldsttype)
-    } else {
-        ZExtOrBitCast(bcx, llsrc, lldsttype)
+pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
+                          expr: &ast::Expr,
+                          t_in: Ty<'tcx>,
+                          t_out: Ty<'tcx>)
+                          -> bool {
+    if let Some(&CastKind::CoercionCast) = tcx.cast_kinds.borrow().get(&expr.id) {
+        return true;
     }
-}
-
-fn float_cast(bcx: Block,
-              lldsttype: Type,
-              llsrctype: Type,
-              llsrc: ValueRef)
-              -> ValueRef {
-    let _icx = push_ctxt("float_cast");
-    let srcsz = llsrctype.float_width();
-    let dstsz = lldsttype.float_width();
-    return if dstsz > srcsz {
-        FPExt(bcx, llsrc, lldsttype)
-    } else if srcsz > dstsz {
-        FPTrunc(bcx, llsrc, lldsttype)
-    } else { llsrc };
-}
-
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum cast_kind {
-    cast_pointer,
-    cast_fat_ptr,
-    cast_integral,
-    cast_float,
-    cast_enum,
-    cast_other,
-}
 
-pub fn cast_type_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> cast_kind {
-    match t.sty {
-        ty::ty_char        => cast_integral,
-        ty::ty_float(..)   => cast_float,
-        ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => {
-            if type_is_sized(tcx, mt.ty) {
-                cast_pointer
-            } else {
-                cast_fat_ptr
-            }
-        }
-        ty::ty_bare_fn(..) => cast_pointer,
-        ty::ty_int(..)     => cast_integral,
-        ty::ty_uint(..)    => cast_integral,
-        ty::ty_bool        => cast_integral,
-        ty::ty_enum(..)    => cast_enum,
-        _                  => cast_other
-    }
-}
-
-pub fn cast_is_noop<'tcx>(t_in: Ty<'tcx>, t_out: Ty<'tcx>) -> bool {
     match (ty::deref(t_in, true), ty::deref(t_out, true)) {
         (Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
             t_in == t_out
         }
-        _ => false
+        _ => {
+            // This condition isn't redundant with the check for CoercionCast:
+            // different types can be substituted into the same type, and
+            // == equality can be overconservative if there are regions.
+            t_in == t_out
+        }
     }
 }
 
 fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                               expr: &ast::Expr,
                               id: ast::NodeId)
-                              -> DatumBlock<'blk, 'tcx, Expr> {
+                              -> DatumBlock<'blk, 'tcx, Expr>
+{
+    use middle::cast::CastTy::*;
+    use middle::cast::IntTy::*;
+
+    fn int_cast(bcx: Block,
+                lldsttype: Type,
+                llsrctype: Type,
+                llsrc: ValueRef,
+                signed: bool)
+                -> ValueRef
+    {
+        let _icx = push_ctxt("int_cast");
+        let srcsz = llsrctype.int_width();
+        let dstsz = lldsttype.int_width();
+        return if dstsz == srcsz {
+            BitCast(bcx, llsrc, lldsttype)
+        } else if srcsz > dstsz {
+            TruncOrBitCast(bcx, llsrc, lldsttype)
+        } else if signed {
+            SExtOrBitCast(bcx, llsrc, lldsttype)
+        } else {
+            ZExtOrBitCast(bcx, llsrc, lldsttype)
+        }
+    }
+
+    fn float_cast(bcx: Block,
+                  lldsttype: Type,
+                  llsrctype: Type,
+                  llsrc: ValueRef)
+                  -> ValueRef
+    {
+        let _icx = push_ctxt("float_cast");
+        let srcsz = llsrctype.float_width();
+        let dstsz = lldsttype.float_width();
+        return if dstsz > srcsz {
+            FPExt(bcx, llsrc, lldsttype)
+        } else if srcsz > dstsz {
+            FPTrunc(bcx, llsrc, lldsttype)
+        } else { llsrc };
+    }
+
     let _icx = push_ctxt("trans_cast");
     let mut bcx = bcx;
     let ccx = bcx.ccx();
 
     let t_in = expr_ty_adjusted(bcx, expr);
     let t_out = node_id_type(bcx, id);
-    let k_in = cast_type_kind(bcx.tcx(), t_in);
-    let k_out = cast_type_kind(bcx.tcx(), t_out);
-    let s_in = k_in == cast_integral && ty::type_is_signed(t_in);
-    let ll_t_in = type_of::arg_type_of(ccx, t_in);
-    let ll_t_out = type_of::arg_type_of(ccx, t_out);
 
+    debug!("trans_cast({:?} as {:?})", t_in, t_out);
+    let mut ll_t_in = type_of::arg_type_of(ccx, t_in);
+    let ll_t_out = type_of::arg_type_of(ccx, t_out);
     // Convert the value to be cast into a ValueRef, either by-ref or
     // by-value as appropriate given its type:
     let mut datum = unpack_datum!(bcx, trans(bcx, expr));
 
     let datum_ty = monomorphize_type(bcx, datum.ty);
-    if cast_is_noop(datum_ty, t_out) {
+
+    if cast_is_noop(bcx.tcx(), expr, datum_ty, t_out) {
         datum.ty = t_out;
         return DatumBlock::new(bcx, datum);
     }
 
-    let newval = match (k_in, k_out) {
-        (cast_integral, cast_integral) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            int_cast(bcx, ll_t_out, ll_t_in, llexpr, s_in)
-        }
-        (cast_float, cast_float) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            float_cast(bcx, ll_t_out, ll_t_in, llexpr)
-        }
-        (cast_integral, cast_float) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            if s_in {
-                SIToFP(bcx, llexpr, ll_t_out)
-            } else { UIToFP(bcx, llexpr, ll_t_out) }
-        }
-        (cast_float, cast_integral) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            if ty::type_is_signed(t_out) {
-                FPToSI(bcx, llexpr, ll_t_out)
-            } else { FPToUI(bcx, llexpr, ll_t_out) }
-        }
-        (cast_integral, cast_pointer) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            IntToPtr(bcx, llexpr, ll_t_out)
-        }
-        (cast_pointer, cast_integral) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            PtrToInt(bcx, llexpr, ll_t_out)
-        }
-        (cast_fat_ptr, cast_integral) => {
-            let data_ptr = Load(bcx, get_dataptr(bcx, datum.val));
-            PtrToInt(bcx, data_ptr, ll_t_out)
-        }
-        (cast_pointer, cast_pointer) => {
-            let llexpr = datum.to_llscalarish(bcx);
-            PointerCast(bcx, llexpr, ll_t_out)
-        }
-        (cast_fat_ptr, cast_pointer) => {
-            let data_ptr = Load(bcx, get_dataptr(bcx, datum.val));
-            PointerCast(bcx, data_ptr, ll_t_out)
+    if type_is_fat_ptr(bcx.tcx(), t_in) {
+        assert!(datum.kind.is_by_ref());
+        if type_is_fat_ptr(bcx.tcx(), t_out) {
+            return DatumBlock::new(bcx, Datum::new(
+                PointerCast(bcx, datum.val, ll_t_out.ptr_to()),
+                t_out,
+                Rvalue::new(ByRef)
+            )).to_expr_datumblock();
+        } else {
+            // Return the address
+            return immediate_rvalue_bcx(bcx,
+                                        PointerCast(bcx,
+                                                    Load(bcx, get_dataptr(bcx, datum.val)),
+                                                    ll_t_out),
+                                        t_out).to_expr_datumblock();
         }
-        (cast_enum, cast_integral) |
-        (cast_enum, cast_float) => {
-            let mut bcx = bcx;
-            let repr = adt::represent_type(ccx, t_in);
-            let datum = unpack_datum!(
-                bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
-            let llexpr_ptr = datum.to_llref();
-            let lldiscrim_a =
-                adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
-            match k_out {
-                cast_integral => int_cast(bcx, ll_t_out,
-                                          val_ty(lldiscrim_a),
-                                          lldiscrim_a, true),
-                cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out),
-                _ => {
-                    ccx.sess().bug(&format!("translating unsupported cast: \
-                                            {} ({:?}) -> {} ({:?})",
-                                            t_in.repr(bcx.tcx()),
-                                            k_in,
-                                            t_out.repr(bcx.tcx()),
-                                            k_out))
-                }
-            }
+    }
+
+    let r_t_in = CastTy::from_ty(bcx.tcx(), t_in).expect("bad input type for cast");
+    let r_t_out = CastTy::from_ty(bcx.tcx(), t_out).expect("bad output type for cast");
+
+    let (llexpr, signed) = if let Int(CEnum) = r_t_in {
+        let repr = adt::represent_type(ccx, t_in);
+        let datum = unpack_datum!(
+            bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
+        let llexpr_ptr = datum.to_llref();
+        let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
+        ll_t_in = val_ty(discr);
+        (discr, adt::is_discr_signed(&*repr))
+    } else {
+        (datum.to_llscalarish(bcx), ty::type_is_signed(t_in))
+    };
+
+    let newval = match (r_t_in, r_t_out) {
+        (Ptr(_), Ptr(_)) | (FnPtr, Ptr(_)) | (RPtr(_), Ptr(_)) => {
+            PointerCast(bcx, llexpr, ll_t_out)
         }
-        _ => ccx.sess().bug(&format!("translating unsupported cast: \
-                                    {} ({:?}) -> {} ({:?})",
-                                    t_in.repr(bcx.tcx()),
-                                    k_in,
-                                    t_out.repr(bcx.tcx()),
-                                    k_out))
+        (Ptr(_), Int(_)) | (FnPtr, Int(_)) => PtrToInt(bcx, llexpr, ll_t_out),
+        (Int(_), Ptr(_)) => IntToPtr(bcx, llexpr, ll_t_out),
+
+        (Int(_), Int(_)) => int_cast(bcx, ll_t_out, ll_t_in, llexpr, signed),
+        (Float, Float) => float_cast(bcx, ll_t_out, ll_t_in, llexpr),
+        (Int(_), Float) if signed => SIToFP(bcx, llexpr, ll_t_out),
+        (Int(_), Float) => UIToFP(bcx, llexpr, ll_t_out),
+        (Float, Int(I)) => FPToSI(bcx, llexpr, ll_t_out),
+        (Float, Int(_)) => FPToUI(bcx, llexpr, ll_t_out),
+
+        _ => ccx.sess().span_bug(expr.span,
+                                  &format!("translating unsupported cast: \
+                                            {:?} -> {:?}",
+                                           t_in,
+                                           t_out)
+                                 )
     };
     return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
 }
@@ -2165,7 +2144,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_assign_op");
     let mut bcx = bcx;
 
-    debug!("trans_assign_op(expr={})", bcx.expr_to_string(expr));
+    debug!("trans_assign_op(expr={:?})", expr);
 
     // User-defined operator methods cannot be used with `+=` etc right now
     assert!(!bcx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
@@ -2209,7 +2188,9 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // Construct the resulting datum, using what was the "by ref"
     // ValueRef of type `referent_ty` to be the "by value" ValueRef
     // of type `&referent_ty`.
-    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, RvalueExpr(Rvalue::new(ByValue))))
+    // Pointers to DST types are non-immediate, and therefore still use ByRef.
+    let kind  = if type_is_sized(bcx.tcx(), referent_ty) { ByValue } else { ByRef };
+    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, RvalueExpr(Rvalue::new(kind))))
 }
 
 fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -2233,8 +2214,8 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                           -> DatumBlock<'blk, 'tcx, Expr> {
     let ccx = bcx.ccx();
 
-    debug!("deref_once(expr={}, datum={}, method_call={:?})",
-           expr.repr(bcx.tcx()),
+    debug!("deref_once(expr={:?}, datum={}, method_call={:?})",
+           expr,
            datum.to_string(ccx),
            method_call);
 
@@ -2276,25 +2257,29 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     let r = match datum.ty.sty {
-        ty::ty_uniq(content_ty) => {
+        ty::TyBox(content_ty) => {
+            // Make sure we have an lvalue datum here to get the
+            // proper cleanups scheduled
+            let datum = unpack_datum!(
+                bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
+
             if type_is_sized(bcx.tcx(), content_ty) {
-                deref_owned_pointer(bcx, expr, datum, content_ty)
+                let ptr = load_ty(bcx, datum.val, datum.ty);
+                DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
             } else {
                 // A fat pointer and a DST lvalue have the same representation
                 // just different types. Since there is no temporary for `*e`
                 // here (because it is unsized), we cannot emulate the sized
                 // object code path for running drop glue and free. Instead,
                 // we schedule cleanup for `e`, turning it into an lvalue.
-                let datum = unpack_datum!(
-                    bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
 
                 let datum = Datum::new(datum.val, content_ty, LvalueExpr);
                 DatumBlock::new(bcx, datum)
             }
         }
 
-        ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
-        ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
+        ty::TyRawPtr(ty::mt { ty: content_ty, .. }) |
+        ty::TyRef(_, ty::mt { ty: content_ty, .. }) => {
             if type_is_sized(bcx.tcx(), content_ty) {
                 let ptr = datum.to_llscalarish(bcx);
 
@@ -2314,8 +2299,8 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => {
             bcx.tcx().sess.span_bug(
                 expr.span,
-                &format!("deref invoked on expr of illegal type {}",
-                        datum.ty.repr(bcx.tcx())));
+                &format!("deref invoked on expr of illegal type {:?}",
+                        datum.ty));
         }
     };
 
@@ -2323,53 +2308,6 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            expr.id, method_call, r.datum.to_string(ccx));
 
     return r;
-
-    /// We microoptimize derefs of owned pointers a bit here. Basically, the idea is to make the
-    /// deref of an rvalue result in an rvalue. This helps to avoid intermediate stack slots in the
-    /// resulting LLVM. The idea here is that, if the `Box<T>` pointer is an rvalue, then we can
-    /// schedule a *shallow* free of the `Box<T>` pointer, and then return a ByRef rvalue into the
-    /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that
-    /// the contents are not yet scheduled to be freed. The language rules ensure that the contents
-    /// will be used (or moved) before the free occurs.
-    fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       expr: &ast::Expr,
-                                       datum: Datum<'tcx, Expr>,
-                                       content_ty: Ty<'tcx>)
-                                       -> DatumBlock<'blk, 'tcx, Expr> {
-        match datum.kind {
-            RvalueExpr(Rvalue { mode: ByRef }) => {
-                let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
-                let ptr = Load(bcx, datum.val);
-                if !type_is_zero_size(bcx.ccx(), content_ty) {
-                    bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange, content_ty);
-                }
-            }
-            RvalueExpr(Rvalue { mode: ByValue }) => {
-                let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
-                if !type_is_zero_size(bcx.ccx(), content_ty) {
-                    bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange,
-                                                content_ty);
-                }
-            }
-            LvalueExpr => { }
-        }
-
-        // If we had an rvalue in, we produce an rvalue out.
-        let (llptr, kind) = match datum.kind {
-            LvalueExpr => {
-                (Load(bcx, datum.val), LvalueExpr)
-            }
-            RvalueExpr(Rvalue { mode: ByRef }) => {
-                (Load(bcx, datum.val), RvalueExpr(Rvalue::new(ByRef)))
-            }
-            RvalueExpr(Rvalue { mode: ByValue }) => {
-                (datum.val, RvalueExpr(Rvalue::new(ByRef)))
-            }
-        };
-
-        let datum = Datum { ty: content_ty, val: llptr, kind: kind };
-        DatumBlock { bcx: bcx, datum: datum }
-    }
 }
 
 #[derive(Debug)]
@@ -2413,61 +2351,61 @@ impl OverflowOpViaIntrinsic {
     fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
         use syntax::ast::IntTy::*;
         use syntax::ast::UintTy::*;
-        use middle::ty::{ty_int, ty_uint};
+        use middle::ty::{TyInt, TyUint};
 
         let new_sty = match ty.sty {
-            ty_int(TyIs) => match &tcx.sess.target.target.target_pointer_width[..] {
-                "32" => ty_int(TyI32),
-                "64" => ty_int(TyI64),
+            TyInt(TyIs) => match &tcx.sess.target.target.target_pointer_width[..] {
+                "32" => TyInt(TyI32),
+                "64" => TyInt(TyI64),
                 _ => panic!("unsupported target word size")
             },
-            ty_uint(TyUs) => match &tcx.sess.target.target.target_pointer_width[..] {
-                "32" => ty_uint(TyU32),
-                "64" => ty_uint(TyU64),
+            TyUint(TyUs) => match &tcx.sess.target.target.target_pointer_width[..] {
+                "32" => TyUint(TyU32),
+                "64" => TyUint(TyU64),
                 _ => panic!("unsupported target word size")
             },
-            ref t @ ty_uint(_) | ref t @ ty_int(_) => t.clone(),
+            ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(),
             _ => panic!("tried to get overflow intrinsic for {:?} applied to non-int type",
                         *self)
         };
 
         match *self {
             OverflowOpViaIntrinsic::Add => match new_sty {
-                ty_int(TyI8) => "llvm.sadd.with.overflow.i8",
-                ty_int(TyI16) => "llvm.sadd.with.overflow.i16",
-                ty_int(TyI32) => "llvm.sadd.with.overflow.i32",
-                ty_int(TyI64) => "llvm.sadd.with.overflow.i64",
+                TyInt(TyI8) => "llvm.sadd.with.overflow.i8",
+                TyInt(TyI16) => "llvm.sadd.with.overflow.i16",
+                TyInt(TyI32) => "llvm.sadd.with.overflow.i32",
+                TyInt(TyI64) => "llvm.sadd.with.overflow.i64",
 
-                ty_uint(TyU8) => "llvm.uadd.with.overflow.i8",
-                ty_uint(TyU16) => "llvm.uadd.with.overflow.i16",
-                ty_uint(TyU32) => "llvm.uadd.with.overflow.i32",
-                ty_uint(TyU64) => "llvm.uadd.with.overflow.i64",
+                TyUint(TyU8) => "llvm.uadd.with.overflow.i8",
+                TyUint(TyU16) => "llvm.uadd.with.overflow.i16",
+                TyUint(TyU32) => "llvm.uadd.with.overflow.i32",
+                TyUint(TyU64) => "llvm.uadd.with.overflow.i64",
 
                 _ => unreachable!(),
             },
             OverflowOpViaIntrinsic::Sub => match new_sty {
-                ty_int(TyI8) => "llvm.ssub.with.overflow.i8",
-                ty_int(TyI16) => "llvm.ssub.with.overflow.i16",
-                ty_int(TyI32) => "llvm.ssub.with.overflow.i32",
-                ty_int(TyI64) => "llvm.ssub.with.overflow.i64",
+                TyInt(TyI8) => "llvm.ssub.with.overflow.i8",
+                TyInt(TyI16) => "llvm.ssub.with.overflow.i16",
+                TyInt(TyI32) => "llvm.ssub.with.overflow.i32",
+                TyInt(TyI64) => "llvm.ssub.with.overflow.i64",
 
-                ty_uint(TyU8) => "llvm.usub.with.overflow.i8",
-                ty_uint(TyU16) => "llvm.usub.with.overflow.i16",
-                ty_uint(TyU32) => "llvm.usub.with.overflow.i32",
-                ty_uint(TyU64) => "llvm.usub.with.overflow.i64",
+                TyUint(TyU8) => "llvm.usub.with.overflow.i8",
+                TyUint(TyU16) => "llvm.usub.with.overflow.i16",
+                TyUint(TyU32) => "llvm.usub.with.overflow.i32",
+                TyUint(TyU64) => "llvm.usub.with.overflow.i64",
 
                 _ => unreachable!(),
             },
             OverflowOpViaIntrinsic::Mul => match new_sty {
-                ty_int(TyI8) => "llvm.smul.with.overflow.i8",
-                ty_int(TyI16) => "llvm.smul.with.overflow.i16",
-                ty_int(TyI32) => "llvm.smul.with.overflow.i32",
-                ty_int(TyI64) => "llvm.smul.with.overflow.i64",
+                TyInt(TyI8) => "llvm.smul.with.overflow.i8",
+                TyInt(TyI16) => "llvm.smul.with.overflow.i16",
+                TyInt(TyI32) => "llvm.smul.with.overflow.i32",
+                TyInt(TyI64) => "llvm.smul.with.overflow.i64",
 
-                ty_uint(TyU8) => "llvm.umul.with.overflow.i8",
-                ty_uint(TyU16) => "llvm.umul.with.overflow.i16",
-                ty_uint(TyU32) => "llvm.umul.with.overflow.i32",
-                ty_uint(TyU64) => "llvm.umul.with.overflow.i64",
+                TyUint(TyU8) => "llvm.umul.with.overflow.i8",
+                TyUint(TyU16) => "llvm.umul.with.overflow.i16",
+                TyUint(TyU32) => "llvm.umul.with.overflow.i32",
+                TyUint(TyU64) => "llvm.umul.with.overflow.i64",
 
                 _ => unreachable!(),
             },
@@ -2522,12 +2460,10 @@ impl OverflowOpViaInputCheck {
         // (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)
-        let invert_mask = !shift_mask_val(lhs_llty);
-        let invert_mask = C_integral(rhs_llty, invert_mask, true);
+        let invert_mask = shift_mask_val(bcx, lhs_llty, rhs_llty, true);
 
         let outer_bits = And(bcx, rhs, invert_mask, binop_debug_loc);
-        let cond = ICmp(bcx, llvm::IntNE, outer_bits,
-                        C_integral(rhs_llty, 0, false), binop_debug_loc);
+        let cond = build_nonzero_check(bcx, outer_bits, binop_debug_loc);
         let result = match *self {
             OverflowOpViaInputCheck::Shl =>
                 build_unchecked_lshift(bcx, lhs, rhs, binop_debug_loc),
@@ -2543,9 +2479,46 @@ impl OverflowOpViaInputCheck {
     }
 }
 
-fn shift_mask_val(llty: Type) -> u64 {
-    // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
-    llty.int_width() - 1
+fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                              llty: Type,
+                              mask_llty: Type,
+                              invert: bool) -> ValueRef {
+    let kind = llty.kind();
+    match kind {
+        TypeKind::Integer => {
+            // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
+            let val = llty.int_width() - 1;
+            if invert {
+                C_integral(mask_llty, !val, true)
+            } else {
+                C_integral(mask_llty, val, false)
+            }
+        },
+        TypeKind::Vector => {
+            let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert);
+            VectorSplat(bcx, mask_llty.vector_length(), mask)
+        },
+        _ => panic!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
+    }
+}
+
+// Check if an integer or vector contains a nonzero element.
+fn build_nonzero_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                   value: ValueRef,
+                                   binop_debug_loc: DebugLoc) -> ValueRef {
+    let llty = val_ty(value);
+    let kind = llty.kind();
+    match kind {
+        TypeKind::Integer => ICmp(bcx, llvm::IntNE, value, C_null(llty), binop_debug_loc),
+        TypeKind::Vector => {
+            // Check if any elements of the vector are nonzero by treating
+            // it as a wide integer and checking if the integer is nonzero.
+            let width = llty.vector_length() as u64 * llty.element_type().int_width();
+            let int_value = BitCast(bcx, value, Type::ix(bcx.ccx(), width));
+            build_nonzero_check(bcx, int_value, binop_debug_loc)
+        },
+        _ => panic!("build_nonzero_check: expected Integer or Vector, found {:?}", kind),
+    }
 }
 
 // To avoid UB from LLVM, these two functions mask RHS with an
@@ -2571,7 +2544,14 @@ fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShr, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
-    let is_signed = ty::type_is_signed(lhs_t);
+    let tcx = bcx.tcx();
+    let is_simd = ty::type_is_simd(tcx, lhs_t);
+    let intype = if is_simd {
+        ty::simd_type(tcx, lhs_t)
+    } else {
+        lhs_t
+    };
+    let is_signed = ty::type_is_signed(intype);
     if is_signed {
         AShr(bcx, lhs, rhs, binop_debug_loc)
     } else {
@@ -2583,8 +2563,7 @@ fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                               rhs: ValueRef,
                               debug_loc: DebugLoc) -> ValueRef {
     let rhs_llty = val_ty(rhs);
-    let mask = shift_mask_val(rhs_llty);
-    And(bcx, rhs, C_integral(rhs_llty, mask, false), debug_loc)
+    And(bcx, rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false), debug_loc)
 }
 
 fn with_overflow_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, oop: OverflowOp, info: NodeIdAndSpan,
@@ -2615,3 +2594,155 @@ fn with_overflow_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, oop: OverflowOp, info
         (bcx, res)
     }
 }
+
+/// We categorize expressions into three kinds.  The distinction between
+/// lvalue/rvalue is fundamental to the language.  The distinction between the
+/// two kinds of rvalues is an artifact of trans which reflects how we will
+/// generate code for that kind of expression.  See trans/expr.rs for more
+/// information.
+#[derive(Copy, Clone)]
+enum ExprKind {
+    Lvalue,
+    RvalueDps,
+    RvalueDatum,
+    RvalueStmt
+}
+
+fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
+    if tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)) {
+        // Overloaded operations are generally calls, and hence they are
+        // generated via DPS, but there are a few exceptions:
+        return match expr.node {
+            // `a += b` has a unit result.
+            ast::ExprAssignOp(..) => ExprKind::RvalueStmt,
+
+            // the deref method invoked for `*a` always yields an `&T`
+            ast::ExprUnary(ast::UnDeref, _) => ExprKind::Lvalue,
+
+            // the index method invoked for `a[i]` always yields an `&T`
+            ast::ExprIndex(..) => ExprKind::Lvalue,
+
+            // in the general case, result could be any type, use DPS
+            _ => ExprKind::RvalueDps
+        };
+    }
+
+    match expr.node {
+        ast::ExprPath(..) => {
+            match ty::resolve_expr(tcx, expr) {
+                def::DefStruct(_) | def::DefVariant(..) => {
+                    if let ty::TyBareFn(..) = ty::node_id_to_type(tcx, expr.id).sty {
+                        // ctor function
+                        ExprKind::RvalueDatum
+                    } else {
+                        ExprKind::RvalueDps
+                    }
+                }
+
+                // Special case: A unit like struct's constructor must be called without () at the
+                // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
+                // of unit structs this is should not be interpreted as function pointer but as
+                // call to the constructor.
+                def::DefFn(_, true) => ExprKind::RvalueDps,
+
+                // Fn pointers are just scalar values.
+                def::DefFn(..) | def::DefMethod(..) => ExprKind::RvalueDatum,
+
+                // Note: there is actually a good case to be made that
+                // DefArg's, particularly those of immediate type, ought to
+                // considered rvalues.
+                def::DefStatic(..) |
+                def::DefUpvar(..) |
+                def::DefLocal(..) => ExprKind::Lvalue,
+
+                def::DefConst(..) |
+                def::DefAssociatedConst(..) => ExprKind::RvalueDatum,
+
+                def => {
+                    tcx.sess.span_bug(
+                        expr.span,
+                        &format!("uncategorized def for expr {}: {:?}",
+                                expr.id,
+                                def));
+                }
+            }
+        }
+
+        ast::ExprUnary(ast::UnDeref, _) |
+        ast::ExprField(..) |
+        ast::ExprTupField(..) |
+        ast::ExprIndex(..) => {
+            ExprKind::Lvalue
+        }
+
+        ast::ExprCall(..) |
+        ast::ExprMethodCall(..) |
+        ast::ExprStruct(..) |
+        ast::ExprRange(..) |
+        ast::ExprTup(..) |
+        ast::ExprIf(..) |
+        ast::ExprMatch(..) |
+        ast::ExprClosure(..) |
+        ast::ExprBlock(..) |
+        ast::ExprRepeat(..) |
+        ast::ExprVec(..) => {
+            ExprKind::RvalueDps
+        }
+
+        ast::ExprIfLet(..) => {
+            tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
+        }
+        ast::ExprWhileLet(..) => {
+            tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
+        }
+
+        ast::ExprForLoop(..) => {
+            tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
+        }
+
+        ast::ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {
+            ExprKind::RvalueDps
+        }
+
+        ast::ExprBreak(..) |
+        ast::ExprAgain(..) |
+        ast::ExprRet(..) |
+        ast::ExprWhile(..) |
+        ast::ExprLoop(..) |
+        ast::ExprAssign(..) |
+        ast::ExprInlineAsm(..) |
+        ast::ExprAssignOp(..) => {
+            ExprKind::RvalueStmt
+        }
+
+        ast::ExprLit(_) | // Note: LitStr is carved out above
+        ast::ExprUnary(..) |
+        ast::ExprBox(None, _) |
+        ast::ExprAddrOf(..) |
+        ast::ExprBinary(..) |
+        ast::ExprCast(..) => {
+            ExprKind::RvalueDatum
+        }
+
+        ast::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
+            }
+        }
+
+        ast::ExprParen(ref e) => expr_kind(tcx, &**e),
+
+        ast::ExprMac(..) => {
+            tcx.sess.span_bug(
+                expr.span,
+                "macro expression remains after expansion");
+        }
+    }
+}
index 95c93d76585bfc5a7348b992b32ebc01bd10c053..4f3f13e4bed2424438561bd3c1687a6cfffa39b1 100644 (file)
@@ -9,10 +9,11 @@
 // except according to those terms.
 
 
-use back::link;
+use back::{abi, link};
 use llvm::{ValueRef, CallConv, get_param};
 use llvm;
 use middle::weak_lang_items;
+use rustc::ast_map;
 use trans::attributes;
 use trans::base::{llvm_linkage_by_name, push_ctxt};
 use trans::base;
@@ -21,6 +22,7 @@ use trans::cabi;
 use trans::common::*;
 use trans::debuginfo::DebugLoc;
 use trans::declare;
+use trans::expr;
 use trans::machine;
 use trans::monomorphize;
 use trans::type_::Type;
@@ -37,9 +39,8 @@ use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::parse::token;
 use syntax::ast;
-use syntax::{attr, ast_map};
+use syntax::attr;
 use syntax::print::pprust;
-use util::ppaux::Repr;
 
 ///////////////////////////////////////////////////////////////////////////
 // Type definitions
@@ -128,7 +129,7 @@ pub fn register_static(ccx: &CrateContext,
                 }
             };
             let llty2 = match ty.sty {
-                ty::ty_ptr(ref mt) => type_of::type_of(ccx, mt.ty),
+                ty::TyRawPtr(ref mt) => type_of::type_of(ccx, mt.ty),
                 _ => {
                     ccx.sess().span_fatal(foreign_item.span,
                                           "must have type `*T` or `*mut T`");
@@ -182,11 +183,11 @@ 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) -> ValueRef {
-    debug!("register_foreign_item_fn(abi={}, \
-            ty={}, \
+    debug!("register_foreign_item_fn(abi={:?}, \
+            ty={:?}, \
             name={})",
-           abi.repr(ccx.tcx()),
-           fty.repr(ccx.tcx()),
+           abi,
+           fty,
            name);
 
     let cc = llvm_calling_convention(ccx, abi);
@@ -232,17 +233,16 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      -> Block<'blk, 'tcx>
 {
     let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
 
-    debug!("trans_native_call(callee_ty={}, \
+    debug!("trans_native_call(callee_ty={:?}, \
             llfn={}, \
             llretptr={})",
-           callee_ty.repr(tcx),
+           callee_ty,
            ccx.tn().val_to_string(llfn),
            ccx.tn().val_to_string(llretptr));
 
     let (fn_abi, fn_sig) = match callee_ty.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
+        ty::TyBareFn(_, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
         _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
@@ -273,10 +273,11 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
     }
 
-    for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
-        let mut llarg_rust = llarg_rust;
+    let mut offset = 0;
+    for (i, arg_ty) in arg_tys.iter().enumerate() {
+        let mut llarg_rust = llargs_rust[i + offset];
 
-        if arg_tys[i].is_ignore() {
+        if arg_ty.is_ignore() {
             continue;
         }
 
@@ -287,7 +288,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                i,
                ccx.tn().val_to_string(llarg_rust),
                rust_indirect,
-               ccx.tn().type_to_string(arg_tys[i].ty));
+               ccx.tn().type_to_string(arg_ty.ty));
 
         // Ensure that we always have the Rust value indirectly,
         // because it makes bitcasting easier.
@@ -296,7 +297,13 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 base::alloca(bcx,
                              type_of::type_of(ccx, passed_arg_tys[i]),
                              "__arg");
-            base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
+            if type_is_fat_ptr(ccx.tcx(), passed_arg_tys[i]) {
+                Store(bcx, llargs_rust[i + offset], expr::get_dataptr(bcx, scratch));
+                Store(bcx, llargs_rust[i + offset + 1], expr::get_len(bcx, scratch));
+                offset += 1;
+            } else {
+                base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
+            }
             llarg_rust = scratch;
         }
 
@@ -304,7 +311,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                ccx.tn().val_to_string(llarg_rust));
 
         // Check whether we need to do any casting
-        match arg_tys[i].cast {
+        match arg_ty.cast {
             Some(ty) => llarg_rust = BitCast(bcx, llarg_rust, ty.ptr_to()),
             None => ()
         }
@@ -313,7 +320,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                ccx.tn().val_to_string(llarg_rust));
 
         // Finally, load the value if needed for the foreign ABI
-        let foreign_indirect = arg_tys[i].is_indirect();
+        let foreign_indirect = arg_ty.is_indirect();
         let llarg_foreign = if foreign_indirect {
             llarg_rust
         } else {
@@ -329,7 +336,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                i, ccx.tn().val_to_string(llarg_foreign));
 
         // fill padding with undef value
-        match arg_tys[i].pad {
+        match arg_ty.pad {
             Some(ty) => llargs_foreign.push(C_undef(ty)),
             None => ()
         }
@@ -453,7 +460,7 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
             }
         };
         let sig = &ty.sig.0;
-        for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) {
+        for (input, ty) in decl.inputs.iter().zip(&sig.inputs) {
             check(&*input.ty, *ty)
         }
         if let ast::Return(ref ty) = decl.output {
@@ -473,7 +480,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
                 abi => {
                     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
                     match ty.sty {
-                        ty::ty_bare_fn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
+                        ty::TyBareFn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
                         _ => ccx.tcx().sess.span_bug(foreign_item.span,
                                                      "foreign fn's sty isn't a bare_fn_ty?")
                     }
@@ -525,7 +532,7 @@ pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let tys = foreign_types_for_fn_ty(ccx, t);
     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let cconv = match t.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => {
+        ty::TyBareFn(_, ref fn_ty) => {
             llvm_calling_convention(ccx, fn_ty.abi)
         }
         _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
@@ -549,7 +556,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let t = ty::node_id_to_type(ccx.tcx(), node_id);
     let cconv = match t.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => {
+        ty::TyBareFn(_, ref fn_ty) => {
             llvm_calling_convention(ccx, fn_ty.abi)
         }
         _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
@@ -599,26 +606,26 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         let ps = ccx.tcx().map.with_path(id, |path| {
             let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
-            link::mangle(path.chain(abi.into_iter()), hash)
+            link::mangle(path.chain(abi), 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.
         match t.sty {
-            ty::ty_bare_fn(_, ref f) => {
+            ty::TyBareFn(_, ref f) => {
                 assert!(f.abi != Rust && f.abi != RustIntrinsic);
             }
             _ => {
-                ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {}, \
+                ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {:?}, \
                                         expected a bare fn ty",
                                        ccx.tcx().map.path_to_string(id),
-                                       t.repr(tcx)));
+                                       t));
             }
         };
 
-        debug!("build_rust_fn: path={} id={} t={}",
+        debug!("build_rust_fn: path={} id={} t={:?}",
                ccx.tcx().map.path_to_string(id),
-               id, t.repr(tcx));
+               id, t);
 
         let llfn = declare::define_internal_rust_fn(ccx, &ps[..], t).unwrap_or_else(||{
             ccx.sess().bug(&format!("symbol `{}` already defined", ps));
@@ -635,12 +642,11 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                       t: Ty<'tcx>) {
         let _icx = push_ctxt(
             "foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
-        let tcx = ccx.tcx();
 
-        debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
+        debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={:?})",
                ccx.tn().val_to_string(llrustfn),
                ccx.tn().val_to_string(llwrapfn),
-               t.repr(ccx.tcx()));
+               t);
 
         // Avoid all the Rust generation stuff and just generate raw
         // LLVM here.
@@ -722,10 +728,10 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     debug!("out pointer, \
                             allocad={}, \
                             llrust_ret_ty={}, \
-                            return_ty={}",
+                            return_ty={:?}",
                            ccx.tn().val_to_string(slot),
                            ccx.tn().type_to_string(llrust_ret_ty),
-                           tys.fn_sig.output.repr(tcx));
+                           tys.fn_sig.output);
                     llrust_args.push(slot);
                     return_alloca = Some(slot);
                 }
@@ -785,12 +791,12 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // If the types in the ABI and the Rust types don't match,
             // bitcast the llforeign_arg pointer so it matches the types
             // Rust expects.
-            if llforeign_arg_ty.cast.is_some() {
+            if llforeign_arg_ty.cast.is_some() && !type_is_fat_ptr(ccx.tcx(), rust_ty){
                 assert!(!foreign_indirect);
                 llforeign_arg = builder.bitcast(llforeign_arg, llrust_ty.ptr_to());
             }
 
-            let llrust_arg = if rust_indirect {
+            let llrust_arg = if rust_indirect || type_is_fat_ptr(ccx.tcx(), rust_ty) {
                 llforeign_arg
             } else {
                 if ty::type_is_bool(rust_ty) {
@@ -812,12 +818,20 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
             debug!("llrust_arg {}{}: {}", "#",
                    i, ccx.tn().val_to_string(llrust_arg));
-            llrust_args.push(llrust_arg);
+            if type_is_fat_ptr(ccx.tcx(), rust_ty) {
+                let next_llrust_ty = rust_param_tys.next().expect("Not enough parameter types!");
+                llrust_args.push(builder.load(builder.bitcast(builder.gepi(
+                                llrust_arg, &[0, abi::FAT_PTR_ADDR]), llrust_ty.ptr_to())));
+                llrust_args.push(builder.load(builder.bitcast(builder.gepi(
+                                llrust_arg, &[0, abi::FAT_PTR_EXTRA]), next_llrust_ty.ptr_to())));
+            } else {
+                llrust_args.push(llrust_arg);
+            }
         }
 
         // Perform the call itself
-        debug!("calling llrustfn = {}, t = {}",
-               ccx.tn().val_to_string(llrustfn), t.repr(ccx.tcx()));
+        debug!("calling llrustfn = {}, t = {:?}",
+               ccx.tn().val_to_string(llrustfn), t);
         let attributes = attributes::from_fn_type(ccx, t);
         let llrust_ret_val = builder.call(llrustfn, &llrust_args, Some(attributes));
 
@@ -925,7 +939,7 @@ fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
     let fn_sig = match ty.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => &fn_ty.sig,
+        ty::TyBareFn(_, ref fn_ty) => &fn_ty.sig,
         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
@@ -935,11 +949,11 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                        llsig.llret_ty,
                                        llsig.ret_def);
     debug!("foreign_types_for_fn_ty(\
-           ty={}, \
+           ty={:?}, \
            llsig={} -> {}, \
            fn_ty={} -> {}, \
            ret_def={}",
-           ty.repr(ccx.tcx()),
+           ty,
            ccx.tn().types_to_str(&llsig.llarg_tys),
            ccx.tn().type_to_string(llsig.llret_ty),
            ccx.tn().types_to_str(&fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>()),
index 264957d36513b9ecd19b8fc485b4e5486d036200..b84475d915a4f40ee114f82babf88a058f2adab7 100644 (file)
@@ -39,8 +39,6 @@ use trans::machine::*;
 use trans::monomorphize;
 use trans::type_of::{type_of, type_of_dtor, sizing_type_of, align_of};
 use trans::type_::Type;
-use util::ppaux;
-use util::ppaux::{ty_to_short_str, Repr};
 
 use arena::TypedArena;
 use libc::c_uint;
@@ -114,7 +112,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         return tcx.types.i8;
     }
     match t.sty {
-        ty::ty_uniq(typ) if !type_needs_drop(tcx, typ)
+        ty::TyBox(typ) if !type_needs_drop(tcx, typ)
                          && type_is_sized(tcx, typ) => {
             let llty = sizing_type_of(ccx, typ);
             // `Box<ZeroSizeType>` does not allocate.
@@ -141,7 +139,7 @@ pub fn drop_ty_core<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 debug_loc: DebugLoc,
                                 skip_dtor: bool) -> Block<'blk, 'tcx> {
     // NB: v is an *alias* of type t here, not a direct value.
-    debug!("drop_ty_core(t={}, skip_dtor={})", t.repr(bcx.tcx()), skip_dtor);
+    debug!("drop_ty_core(t={:?}, skip_dtor={})", t, skip_dtor);
     let _icx = push_ctxt("drop_ty");
     if bcx.fcx.type_needs_drop(t) {
         let ccx = bcx.ccx();
@@ -204,21 +202,13 @@ impl<'tcx> DropGlueKind<'tcx> {
             DropGlueKind::TyContents(t) => DropGlueKind::TyContents(f(t)),
         }
     }
-
-    fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
-        let t_str = ppaux::ty_to_string(ccx.tcx(), self.ty());
-        match *self {
-            DropGlueKind::Ty(_) => format!("DropGlueKind::Ty({})", t_str),
-            DropGlueKind::TyContents(_) => format!("DropGlueKind::TyContents({})", t_str),
-        }
-    }
 }
 
 fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 g: DropGlueKind<'tcx>) -> ValueRef {
-    debug!("make drop glue for {}", g.to_string(ccx));
+    debug!("make drop glue for {:?}", g);
     let g = g.map_ty(|t| get_drop_glue_type(ccx, t));
-    debug!("drop glue type {}", g.to_string(ccx));
+    debug!("drop glue type {:?}", g);
     match ccx.drop_glues().borrow().get(&g) {
         Some(&glue) => return glue,
         _ => { }
@@ -247,7 +237,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     });
     ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
 
-    let _s = StatRecorder::new(ccx, format!("drop {}", ty_to_short_str(ccx.tcx(), t)));
+    let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
 
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
     let (arena, fcx): (TypedArena<_>, FunctionContext);
@@ -269,7 +259,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // llfn is expected be declared to take a parameter of the appropriate
     // type, so we don't need to explicitly cast the function parameter.
 
-    let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
+    let llrawptr0 = get_param(llfn, fcx.arg_offset() as c_uint);
     let bcx = make_drop_glue(bcx, llrawptr0, g);
     finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
 
@@ -355,7 +345,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  substs: &subst::Substs<'tcx>)
                                  -> Block<'blk, 'tcx>
 {
-    debug!("trans_struct_drop t: {}", bcx.ty_to_string(t));
+    debug!("trans_struct_drop t: {}", t);
 
     // Find and call the actual destructor
     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t, class_did, substs);
@@ -390,7 +380,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: ValueRef)
                                          -> (ValueRef, ValueRef) {
     debug!("calculate size of DST: {}; with lost info: {}",
-           bcx.ty_to_string(t), bcx.val_to_string(info));
+           t, bcx.val_to_string(info));
     if type_is_sized(bcx.tcx(), t) {
         let sizing_type = sizing_type_of(bcx.ccx(), t);
         let size = C_uint(bcx.ccx(), llsize_of_alloc(bcx.ccx(), sizing_type));
@@ -398,7 +388,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
         return (size, align);
     }
     match t.sty {
-        ty::ty_struct(id, substs) => {
+        ty::TyStruct(id, substs) => {
             let ccx = bcx.ccx();
             // First get the size of all statically known fields.
             // Don't use type_of::sizing_type_of because that expects t to be sized.
@@ -427,7 +417,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
                                unsized_align);
             (size, align)
         }
-        ty::ty_trait(..) => {
+        ty::TyTrait(..) => {
             // info points to the vtable and the second entry in the vtable is the
             // dynamic size of the object.
             let info = PointerCast(bcx, info, Type::int(bcx.ccx()).ptr_to());
@@ -435,7 +425,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
             let align_ptr = GEPi(bcx, info, &[2]);
             (Load(bcx, size_ptr), Load(bcx, align_ptr))
         }
-        ty::ty_vec(_, None) | ty::ty_str => {
+        ty::TySlice(_) | ty::TyStr => {
             let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
@@ -445,8 +435,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
             (Mul(bcx, info, C_uint(bcx.ccx(), unit_size), DebugLoc::None),
              C_uint(bcx.ccx(), unit_align))
         }
-        _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}",
-                                    bcx.ty_to_string(t)))
+        _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}", t))
     }
 }
 
@@ -466,10 +455,10 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
     let dropped_pattern = C_integral(inttype, adt::dtor_done_usize(bcx.fcx.ccx) as u64, false);
 
     match t.sty {
-        ty::ty_uniq(content_ty) => {
-            // Support for ty_uniq is built-in and its drop glue is
+        ty::TyBox(content_ty) => {
+            // Support for TyBox is built-in and its drop glue is
             // special. It may move to library and have Drop impl. As
-            // a safe-guard, assert ty_uniq not used with TyContents.
+            // a safe-guard, assert TyBox not used with TyContents.
             assert!(!skip_dtor);
             if !type_is_sized(bcx.tcx(), content_ty) {
                 let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
@@ -505,7 +494,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
                 })
             }
         }
-        ty::ty_struct(did, substs) | ty::ty_enum(did, substs) => {
+        ty::TyStruct(did, substs) | ty::TyEnum(did, substs) => {
             let tcx = bcx.tcx();
             match (ty::ty_dtor(tcx, did), skip_dtor) {
                 (ty::TraitDtor(dtor, true), false) => {
@@ -520,8 +509,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
                         // stupid and dangerous.
                         bcx.sess().warn(&format!("Ignoring drop flag in destructor for {}\
                                                  because the struct is unsized. See issue\
-                                                 #16758",
-                                                bcx.ty_to_string(t)));
+                                                 #16758", t));
                         trans_struct_drop(bcx, t, v0, dtor, did, substs)
                     }
                 }
@@ -534,7 +522,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
                 }
             }
         }
-        ty::ty_trait(..) => {
+        ty::TyTrait(..) => {
             // No support in vtable for distinguishing destroying with
             // versus without calling Drop::drop. Assert caller is
             // okay with always calling the Drop impl, if any.
index 3f44bc40f356b7f51362525272d4123adade4c39..f860fe44f28e78f073e6170c38731ab1db103801 100644 (file)
@@ -21,11 +21,13 @@ use syntax::ast_util::local_def;
 
 fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
     -> Option<ast::DefId> {
-    let _icx = push_ctxt("maybe_instantiate_inline");
+    debug!("instantiate_inline({:?})", fn_id);
+    let _icx = push_ctxt("instantiate_inline");
+
     match ccx.external().borrow().get(&fn_id) {
         Some(&Some(node_id)) => {
             // Already inline
-            debug!("maybe_instantiate_inline({}): already inline as node id {}",
+            debug!("instantiate_inline({}): already inline as node id {}",
                    ty::item_path_str(ccx.tcx(), fn_id), node_id);
             return Some(local_def(node_id));
         }
@@ -52,10 +54,10 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
 
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-            trans_item(ccx, &**item);
+            trans_item(ccx, item);
 
             let linkage = match item.node {
-                ast::ItemFn(_, _, _, ref generics, _) => {
+                ast::ItemFn(_, _, _, _, ref generics, _) => {
                     if generics.is_type_parameterized() {
                         // Generics have no symbol, so they can't be given any
                         // linkage.
@@ -118,7 +120,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
                 }
               }
             }
-            _ => ccx.sess().bug("maybe_instantiate_inline: item has a \
+            _ => ccx.sess().bug("instantiate_inline: item has a \
                                  non-enum, non-struct parent")
           }
           trans_item(ccx, &**item);
@@ -126,7 +128,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
         }
         csearch::FoundAst::FoundParent(_, _) => {
             ccx.sess().bug("maybe_get_item_ast returned a FoundParent \
-             with a non-item parent");
+                            with a non-item parent");
         }
         csearch::FoundAst::Found(&ast::IITraitItem(_, ref trait_item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
@@ -167,8 +169,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
                              empty_substs,
                              impl_item.id,
                              &[]);
-                    // Use InternalLinkage so LLVM can optimize more aggressively.
-                    SetLinkage(llfn, InternalLinkage);
+                    // See linkage comments on items.
+                    if ccx.sess().opts.cg.codegen_units == 1 {
+                        SetLinkage(llfn, InternalLinkage);
+                    } else {
+                        SetLinkage(llfn, AvailableExternallyLinkage);
+                    }
                 }
             }
 
index 951d30c4fb8db3fab13d3c25fcd958f5addee67d..dd97265e428edecc43c3e162c1641dcd1a546cc7 100644 (file)
@@ -34,7 +34,6 @@ use middle::ty::{self, Ty};
 use syntax::abi::RustIntrinsic;
 use syntax::ast;
 use syntax::parse::token;
-use util::ppaux::{Repr, ty_to_string};
 
 pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
     let name = match &token::get_ident(item.ident)[..] {
@@ -93,7 +92,7 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
 /// the only intrinsic that needs such verification is `transmute`.
 pub fn check_intrinsics(ccx: &CrateContext) {
     let mut last_failing_id = None;
-    for transmute_restriction in &*ccx.tcx().transmute_restrictions.borrow() {
+    for transmute_restriction in ccx.tcx().transmute_restrictions.borrow().iter() {
         // Sometimes, a single call to transmute will push multiple
         // type pairs to test in order to exhaustively test the
         // possibility around a type parameter. If one of those fails,
@@ -102,7 +101,7 @@ pub fn check_intrinsics(ccx: &CrateContext) {
             continue;
         }
 
-        debug!("transmute_restriction: {}", transmute_restriction.repr(ccx.tcx()));
+        debug!("transmute_restriction: {:?}", transmute_restriction);
 
         assert!(!ty::type_has_params(transmute_restriction.substituted_from));
         assert!(!ty::type_has_params(transmute_restriction.substituted_to));
@@ -121,10 +120,10 @@ pub fn check_intrinsics(ccx: &CrateContext) {
                     transmute_restriction.span,
                     &format!("transmute called on types with potentially different sizes: \
                               {} (could be {} bit{}) to {} (could be {} bit{})",
-                             ty_to_string(ccx.tcx(), transmute_restriction.original_from),
+                             transmute_restriction.original_from,
                              from_type_size as usize,
                              if from_type_size == 1 {""} else {"s"},
-                             ty_to_string(ccx.tcx(), transmute_restriction.original_to),
+                             transmute_restriction.original_to,
                              to_type_size as usize,
                              if to_type_size == 1 {""} else {"s"}));
             } else {
@@ -132,10 +131,10 @@ pub fn check_intrinsics(ccx: &CrateContext) {
                     transmute_restriction.span,
                     &format!("transmute called on types with different sizes: \
                               {} ({} bit{}) to {} ({} bit{})",
-                             ty_to_string(ccx.tcx(), transmute_restriction.original_from),
+                             transmute_restriction.original_from,
                              from_type_size as usize,
                              if from_type_size == 1 {""} else {"s"},
-                             ty_to_string(ccx.tcx(), transmute_restriction.original_to),
+                             transmute_restriction.original_to,
                              to_type_size as usize,
                              if to_type_size == 1 {""} else {"s"}));
             }
@@ -163,7 +162,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_intrinsic_call");
 
     let ret_ty = match callee_ty.sty {
-        ty::ty_bare_fn(_, ref f) => {
+        ty::TyBareFn(_, ref f) => {
             ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output())
         }
         _ => panic!("expected bare_fn in trans_intrinsic_call")
@@ -223,7 +222,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     let val = if datum.kind.is_by_ref() {
                         load_ty(bcx, datum.val, datum.ty)
                     } else {
-                        datum.val
+                        from_arg_ty(bcx, datum.val, datum.ty)
                     };
 
                     let cast_val = BitCast(bcx, val, llret_ty);
@@ -265,6 +264,44 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
     }
 
+    // For `move_val_init` we can evaluate the destination address
+    // (the first argument) and then trans the source value (the
+    // second argument) directly into the resulting destination
+    // address.
+    if &name[..] == "move_val_init" {
+        if let callee::ArgExprs(ref exprs) = args {
+            let (dest_expr, source_expr) = if exprs.len() != 2 {
+                ccx.sess().bug("expected two exprs as arguments for `move_val_init` intrinsic");
+            } else {
+                (&exprs[0], &exprs[1])
+            };
+
+            // evaluate destination address
+            let dest_datum = unpack_datum!(bcx, expr::trans(bcx, dest_expr));
+            let dest_datum = unpack_datum!(
+                bcx, dest_datum.to_rvalue_datum(bcx, "arg"));
+            let dest_datum = unpack_datum!(
+                bcx, dest_datum.to_appropriate_datum(bcx));
+
+            // `expr::trans_into(bcx, expr, dest)` is equiv to
+            //
+            //    `trans(bcx, expr).store_to_dest(dest)`,
+            //
+            // which for `dest == expr::SaveIn(addr)`, is equivalent to:
+            //
+            //    `trans(bcx, expr).store_to(bcx, addr)`.
+            let lldest = expr::Dest::SaveIn(dest_datum.val);
+            bcx = expr::trans_into(bcx, source_expr, lldest);
+
+            let llresult = C_nil(ccx);
+            fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
+
+            return Result::new(bcx, llresult);
+        } else {
+            ccx.sess().bug("expected two exprs as arguments for `move_val_init` intrinsic");
+        }
+    }
+
     // Push the arguments.
     let mut llargs = Vec::new();
     bcx = callee::trans_args(bcx,
@@ -329,8 +366,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, "size_of_val") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             if !type_is_sized(tcx, tp_ty) {
-                let info = Load(bcx, expr::get_len(bcx, llargs[0]));
-                let (llsize, _) = glue::size_and_align_of_dst(bcx, tp_ty, info);
+                let (llsize, _) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
                 llsize
             } else {
                 let lltp_ty = type_of::type_of(ccx, tp_ty);
@@ -344,8 +380,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, "min_align_of_val") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             if !type_is_sized(tcx, tp_ty) {
-                let info = Load(bcx, expr::get_len(bcx, llargs[0]));
-                let (_, llalign) = glue::size_and_align_of_dst(bcx, tp_ty, info);
+                let (_, llalign) = glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
                 llalign
             } else {
                 C_uint(ccx, type_of::align_of(ccx, tp_ty))
@@ -356,30 +391,23 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty))
         }
-        (_, "move_val_init") => {
-            // Create a datum reflecting the value being moved.
-            // Use `appropriate_mode` so that the datum is by ref
-            // if the value is non-immediate. Note that, with
-            // intrinsics, there are no argument cleanups to
-            // concern ourselves with, so we can use an rvalue datum.
-            let tp_ty = *substs.types.get(FnSpace, 0);
-            let mode = appropriate_rvalue_mode(ccx, tp_ty);
-            let src = Datum {
-                val: llargs[1],
-                ty: tp_ty,
-                kind: Rvalue::new(mode)
-            };
-            bcx = src.store_to(bcx, llargs[0]);
-            C_nil(ccx)
-        }
         (_, "drop_in_place") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
-            glue::drop_ty(bcx, llargs[0], tp_ty, call_debug_location);
+            let ptr = if type_is_sized(tcx, tp_ty) {
+                llargs[0]
+            } else {
+                let scratch = rvalue_scratch_datum(bcx, tp_ty, "tmp");
+                Store(bcx, llargs[0], expr::get_dataptr(bcx, scratch.val));
+                Store(bcx, llargs[1], expr::get_len(bcx, scratch.val));
+                fcx.schedule_lifetime_end(cleanup::CustomScope(cleanup_scope), scratch.val);
+                scratch.val
+            };
+            glue::drop_ty(bcx, ptr, tp_ty, call_debug_location);
             C_nil(ccx)
         }
         (_, "type_name") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
-            let ty_name = token::intern_and_get_ident(&ty_to_string(ccx.tcx(), tp_ty));
+            let ty_name = token::intern_and_get_ident(&tp_ty.to_string());
             C_str_slice(ccx, ty_name)
         }
         (_, "type_id") => {
@@ -418,6 +446,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let offset = llargs[1];
             InBoundsGEP(bcx, ptr, &[offset])
         }
+        (_, "arith_offset") => {
+            let ptr = llargs[0];
+            let offset = llargs[1];
+            GEP(bcx, ptr, &[offset])
+        }
 
         (_, "copy_nonoverlapping") => {
             copy_intrinsic(bcx,
@@ -485,12 +518,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             unsafe {
                 llvm::LLVMSetAlignment(load, type_of::align_of(ccx, tp_ty));
             }
-            from_arg_ty(bcx, load, tp_ty)
+            to_arg_ty(bcx, load, tp_ty)
         },
         (_, "volatile_store") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-            let val = to_arg_ty(bcx, llargs[1], tp_ty);
+            let val = from_arg_ty(bcx, llargs[1], tp_ty);
             let store = VolatileStore(bcx, val, ptr);
             unsafe {
                 llvm::LLVMSetAlignment(store, type_of::align_of(ccx, tp_ty));
@@ -724,7 +757,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, "discriminant_value") => {
             let val_ty = substs.types.get(FnSpace, 0);
             match val_ty.sty {
-                ty::ty_enum(..) => {
+                ty::TyEnum(..) => {
                     let repr = adt::represent_type(ccx, *val_ty);
                     adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
                 }
@@ -772,8 +805,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-                    let cmp = to_arg_ty(bcx, llargs[1], tp_ty);
-                    let src = to_arg_ty(bcx, llargs[2], tp_ty);
+                    let cmp = from_arg_ty(bcx, llargs[1], tp_ty);
+                    let src = from_arg_ty(bcx, llargs[2], tp_ty);
                     let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
                                             strongest_failure_ordering);
                     ExtractValue(bcx, res, 0)
@@ -782,12 +815,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 "load" => {
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-                    from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
+                    to_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
                 }
                 "store" => {
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    let val = from_arg_ty(bcx, llargs[1], tp_ty);
                     AtomicStore(bcx, val, ptr, order);
                     C_nil(ccx)
                 }
@@ -821,7 +854,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    let val = from_arg_ty(bcx, llargs[1], tp_ty);
                     AtomicRMW(bcx, atom_op, ptr, val, order)
                 }
             }
@@ -950,7 +983,7 @@ fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let ret = C_undef(type_of::type_of(bcx.ccx(), t));
     let ret = InsertValue(bcx, ret, result, 0);
     let ret = InsertValue(bcx, ret, overflow, 1);
-    if type_is_immediate(bcx.ccx(), t) {
+    if !arg_is_indirect(bcx.ccx(), t) {
         let tmp = alloc_ty(bcx, t, "tmp");
         Store(bcx, ret, tmp);
         load_ty(bcx, tmp, t)
index 7039968b029ac776284dfcc55ec7449f0c5c884e..e61770768db22e5d6bcc786e55c0f098df10a0db 100644 (file)
 use arena::TypedArena;
 use back::abi;
 use back::link;
-use llvm::{ValueRef, get_param};
+use llvm::{ValueRef, get_params};
 use metadata::csearch;
 use middle::subst::{Subst, Substs};
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
 use middle::ty::ClosureTyper;
+use rustc::ast_map;
 use trans::base::*;
 use trans::build::*;
 use trans::callee::*;
@@ -38,11 +39,10 @@ use trans::type_::Type;
 use trans::type_of::*;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
-use util::ppaux::Repr;
 
 use syntax::abi::{Rust, RustCall};
 use syntax::parse::token;
-use syntax::{ast, ast_map, attr, visit};
+use syntax::{ast, attr, visit};
 use syntax::codemap::DUMMY_SP;
 use syntax::ptr::P;
 
@@ -61,7 +61,7 @@ pub fn trans_impl(ccx: &CrateContext,
     let _icx = push_ctxt("meth::trans_impl");
     let tcx = ccx.tcx();
 
-    debug!("trans_impl(name={}, id={})", name.repr(tcx), id);
+    debug!("trans_impl(name={}, id={})", name, id);
 
     let mut v = TransItemVisitor { ccx: ccx };
 
@@ -118,6 +118,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match origin {
         ty::MethodStatic(did) |
         ty::MethodStaticClosure(did) => {
+            debug!("trans_method_callee: static, {:?}", did);
             Callee {
                 bcx: bcx,
                 data: Fn(callee::trans_fn_ref(bcx.ccx(),
@@ -134,13 +135,15 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }) => {
             let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
             let span = bcx.tcx().map.span(method_call.expr_id);
-            debug!("method_call={:?} trait_ref={}",
+            debug!("method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}",
                    method_call,
-                   trait_ref.repr(bcx.tcx()));
+                   trait_ref,
+                   trait_ref.0.def_id,
+                   trait_ref.0.substs);
             let origin = fulfill_obligation(bcx.ccx(),
                                             span,
                                             trait_ref.clone());
-            debug!("origin = {}", origin.repr(bcx.tcx()));
+            debug!("origin = {:?}", origin);
             trans_monomorphized_callee(bcx,
                                        method_call,
                                        trait_ref.def_id(),
@@ -230,7 +233,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                              rcvr_self,
                                              Vec::new()));
     let trait_substs = tcx.mk_substs(trait_substs);
-    debug!("trait_substs={}", trait_substs.repr(tcx));
+    debug!("trait_substs={:?}", trait_substs);
     let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
                                               substs: trait_substs });
     let vtbl = fulfill_obligation(ccx,
@@ -292,8 +295,8 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             immediate_rvalue(llfn, ty)
         }
         _ => {
-            tcx.sess.bug(&format!("static call to invalid vtable: {}",
-                                 vtbl.repr(tcx)));
+            tcx.sess.bug(&format!("static call to invalid vtable: {:?}",
+                                 vtbl));
         }
     }
 }
@@ -355,13 +358,13 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
             Callee { bcx: bcx, data: Fn(llfn) }
         }
-        traits::VtableClosure(closure_def_id, substs) => {
+        traits::VtableClosure(vtable_closure) => {
             // The substitutions should have no type parameters remaining
             // after passing through fulfill_obligation
             let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
             let llfn = closure::trans_closure_method(bcx.ccx(),
-                                                     closure_def_id,
-                                                     substs,
+                                                     vtable_closure.closure_def_id,
+                                                     vtable_closure.substs,
                                                      MethodCallKey(method_call),
                                                      bcx.fcx.param_substs,
                                                      trait_closure_kind);
@@ -386,8 +389,8 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         traits::VtableDefaultImpl(..) |
         traits::VtableParam(..) => {
             bcx.sess().bug(
-                &format!("resolved vtable bad vtable {} in trans",
-                        vtable.repr(bcx.tcx())));
+                &format!("resolved vtable bad vtable {:?} in trans",
+                        vtable));
         }
     }
 }
@@ -411,8 +414,8 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let node_substs = node_id_substs(ccx, node, bcx.fcx.param_substs);
 
-    debug!("rcvr_substs={}", rcvr_substs.repr(ccx.tcx()));
-    debug!("node_substs={}", node_substs.repr(ccx.tcx()));
+    debug!("rcvr_substs={:?}", rcvr_substs);
+    debug!("node_substs={:?}", node_substs);
 
     // Break apart the type parameters from the node and type
     // parameters from the receiver.
@@ -465,7 +468,9 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         self_datum.val
     };
 
-    trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llval)
+    let llself = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
+    let llvtable = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
+    trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llself, llvtable)
 }
 
 /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object
@@ -473,23 +478,22 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                  callee_ty: Ty<'tcx>,
                                                  vtable_index: usize,
-                                                 llpair: ValueRef)
+                                                 llself: ValueRef,
+                                                 llvtable: ValueRef)
                                                  -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("meth::trans_trait_callee");
     let ccx = bcx.ccx();
 
     // Load the data pointer from the object.
-    debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llpair={})",
-           callee_ty.repr(ccx.tcx()),
+    debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llself={}, llvtable={})",
+           callee_ty,
            vtable_index,
-           bcx.val_to_string(llpair));
-    let llboxptr = GEPi(bcx, llpair, &[0, abi::FAT_PTR_ADDR]);
-    let llbox = Load(bcx, llboxptr);
-    let llself = PointerCast(bcx, llbox, Type::i8p(ccx));
+           bcx.val_to_string(llself),
+           bcx.val_to_string(llvtable));
 
     // Replace the self type (&Self or Box<Self>) with an opaque pointer.
     let llcallee_ty = match callee_ty.sty {
-        ty::ty_bare_fn(_, ref f) if f.abi == Rust || f.abi == RustCall => {
+        ty::TyBareFn(_, ref f) if f.abi == Rust || f.abi == RustCall => {
             let fake_sig =
                 ty::Binder(ty::FnSig {
                     inputs: f.sig.0.inputs[1..].to_vec(),
@@ -502,19 +506,13 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn");
         }
     };
-    let llvtable = Load(bcx,
-                        PointerCast(bcx,
-                                    GEPi(bcx, llpair,
-                                         &[0, abi::FAT_PTR_EXTRA]),
-                                    Type::vtable(ccx).ptr_to().ptr_to()));
-    let mptr = Load(bcx, GEPi(bcx, llvtable, &[0, vtable_index + VTABLE_OFFSET]));
-    let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
+    let mptr = Load(bcx, GEPi(bcx, llvtable, &[vtable_index + VTABLE_OFFSET]));
 
     return Callee {
         bcx: bcx,
         data: TraitItem(MethodData {
-            llfn: mptr,
-            llself: llself,
+            llfn: PointerCast(bcx, mptr, llcallee_ty.ptr_to()),
+            llself: PointerCast(bcx, llself, Type::i8p(ccx)),
         })
     };
 }
@@ -552,26 +550,26 @@ pub fn trans_object_shim<'a, 'tcx>(
     let tcx = ccx.tcx();
     let trait_id = upcast_trait_ref.def_id();
 
-    debug!("trans_object_shim(object_ty={}, upcast_trait_ref={}, method_offset_in_trait={})",
-           object_ty.repr(tcx),
-           upcast_trait_ref.repr(tcx),
+    debug!("trans_object_shim(object_ty={:?}, upcast_trait_ref={:?}, method_offset_in_trait={})",
+           object_ty,
+           upcast_trait_ref,
            method_offset_in_trait);
 
     let object_trait_ref =
         match object_ty.sty {
-            ty::ty_trait(ref data) => {
+            ty::TyTrait(ref data) => {
                 data.principal_trait_ref_with_self_ty(tcx, object_ty)
             }
             _ => {
-                tcx.sess.bug(&format!("trans_object_shim() called on non-object: {}",
-                                      object_ty.repr(tcx)));
+                tcx.sess.bug(&format!("trans_object_shim() called on non-object: {:?}",
+                                      object_ty));
             }
         };
 
     // Upcast to the trait in question and extract out the substitutions.
     let upcast_trait_ref = ty::erase_late_bound_regions(tcx, &upcast_trait_ref);
     let object_substs = upcast_trait_ref.substs.clone().erase_regions();
-    debug!("trans_object_shim: object_substs={}", object_substs.repr(tcx));
+    debug!("trans_object_shim: object_substs={:?}", object_substs);
 
     // Lookup the type of this method as declared in the trait and apply substitutions.
     let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
@@ -583,7 +581,7 @@ pub fn trans_object_shim<'a, 'tcx>(
     let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
     let fty = tcx.mk_bare_fn(fty);
     let method_ty = opaque_method_ty(tcx, fty);
-    debug!("trans_object_shim: fty={} method_ty={}", fty.repr(tcx), method_ty.repr(tcx));
+    debug!("trans_object_shim: fty={:?} method_ty={:?}", fty, method_ty);
 
     //
     let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty);
@@ -608,42 +606,14 @@ pub fn trans_object_shim<'a, 'tcx>(
                       &block_arena);
     let mut bcx = init_function(&fcx, false, sig.output);
 
-    // the first argument (`self`) will be a trait object
-    let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
-
-    debug!("trans_object_shim: llobject={}",
-           bcx.val_to_string(llobject));
-
-    // the remaining arguments will be, well, whatever they are
-    let input_tys =
-        match fty.abi {
-            RustCall => {
-                // unpack the tuple to extract the input type arguments:
-                match sig.inputs[1].sty {
-                    ty::ty_tup(ref tys) => &**tys,
-                    _ => {
-                        bcx.sess().bug(
-                            &format!("rust-call expects a tuple not {}",
-                                     sig.inputs[1].repr(tcx)));
-                    }
-                }
-            }
-            _ => {
-                // skip the self parameter:
-                &sig.inputs[1..]
-            }
-        };
+    let llargs = get_params(fcx.llfn);
 
-    let llargs: Vec<_> =
-        input_tys.iter()
-        .enumerate()
-        .map(|(i, _)| {
-            let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
-            debug!("trans_object_shim: input #{} == {}",
-                   i, bcx.val_to_string(llarg));
-            llarg
-        })
-        .collect();
+    let self_idx = fcx.arg_offset();
+    let llself = llargs[self_idx];
+    let llvtable = llargs[self_idx + 1];
+
+    debug!("trans_object_shim: llself={}, llvtable={}",
+           bcx.val_to_string(llself), bcx.val_to_string(llvtable));
 
     assert!(!fcx.needs_ret_allocas);
 
@@ -665,8 +635,8 @@ pub fn trans_object_shim<'a, 'tcx>(
                            |bcx, _| trans_trait_callee_from_llval(bcx,
                                                                   method_bare_fn_ty,
                                                                   method_offset_in_vtable,
-                                                                  llobject),
-                           ArgVals(&llargs),
+                                                                  llself, llvtable),
+                           ArgVals(&llargs[(self_idx + 2)..]),
                            dest).bcx;
 
     finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
@@ -688,7 +658,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let tcx = ccx.tcx();
     let _icx = push_ctxt("meth::get_vtable");
 
-    debug!("get_vtable(trait_ref={})", trait_ref.repr(tcx));
+    debug!("get_vtable(trait_ref={:?})", trait_ref);
 
     // Check the cache.
     match ccx.vtables().borrow().get(&trait_ref) {
@@ -712,7 +682,11 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     nested: _ }) => {
                 emit_vtable_methods(ccx, id, substs, param_substs).into_iter()
             }
-            traits::VtableClosure(closure_def_id, substs) => {
+            traits::VtableClosure(
+                traits::VtableClosureData {
+                    closure_def_id,
+                    substs,
+                    nested: _ }) => {
                 let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
                 let llfn = closure::trans_closure_method(ccx,
                                                          closure_def_id,
@@ -731,14 +705,14 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 // an object type; this cannot happen because we
                 // cannot cast an unsized type into a trait object
                 tcx.sess.bug(
-                    &format!("cannot get vtable for an object type: {}",
-                            data.repr(tcx)));
+                    &format!("cannot get vtable for an object type: {:?}",
+                            data));
             }
             traits::VtableParam(..) => {
                 tcx.sess.bug(
-                    &format!("resolved vtable for {} to bad vtable {} in trans",
-                            trait_ref.repr(tcx),
-                            vtable.repr(tcx)));
+                    &format!("resolved vtable for {:?} to bad vtable {:?} in trans",
+                            trait_ref,
+                            vtable));
             }
         }
     });
@@ -768,10 +742,10 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 {
     let tcx = ccx.tcx();
 
-    debug!("emit_vtable_methods(impl_id={}, substs={}, param_substs={})",
-           impl_id.repr(tcx),
-           substs.repr(tcx),
-           param_substs.repr(tcx));
+    debug!("emit_vtable_methods(impl_id={:?}, substs={:?}, param_substs={:?})",
+           impl_id,
+           substs,
+           param_substs);
 
     let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
         Some(t_id) => t_id.def_id,
@@ -798,8 +772,8 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // method could never be called from this object, just supply
         // null.
         .map(|trait_method_def_id| {
-            debug!("emit_vtable_methods: trait_method_def_id={}",
-                   trait_method_def_id.repr(tcx));
+            debug!("emit_vtable_methods: trait_method_def_id={:?}",
+                   trait_method_def_id);
 
             let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) {
                 ty::MethodTraitItem(m) => m,
@@ -813,8 +787,8 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 return nullptr;
             }
 
-            debug!("emit_vtable_methods: trait_method_type={}",
-                   trait_method_type.repr(tcx));
+            debug!("emit_vtable_methods: trait_method_type={:?}",
+                   trait_method_type);
 
             // The substitutions we have are on the impl, so we grab
             // the method type from the impl to substitute into.
@@ -824,8 +798,8 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
 
-            debug!("emit_vtable_methods: impl_method_type={}",
-                   impl_method_type.repr(tcx));
+            debug!("emit_vtable_methods: impl_method_type={:?}",
+                   impl_method_type);
 
             // If this is a default method, it's possible that it
             // relies on where clauses that do not hold for this
index 03fdd0c45c16ae6aa37d19e01b8673ca26956ed5..f4bad313bafb1c95e2772b3655a6e8250d096a7d 100644 (file)
@@ -17,6 +17,7 @@ use middle::subst;
 use middle::subst::{Subst, Substs};
 use middle::traits;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
+use rustc::ast_map;
 use trans::attributes;
 use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use trans::base::trans_fn;
@@ -25,11 +26,9 @@ use trans::common::*;
 use trans::declare;
 use trans::foreign;
 use middle::ty::{self, HasProjectionTypes, Ty};
-use util::ppaux::Repr;
 
 use syntax::abi;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util::local_def;
 use syntax::attr;
 use syntax::codemap::DUMMY_SP;
@@ -41,11 +40,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 ref_id: Option<ast::NodeId>)
     -> (ValueRef, Ty<'tcx>, bool) {
     debug!("monomorphic_fn(\
-            fn_id={}, \
-            real_substs={}, \
+            fn_id={:?}, \
+            real_substs={:?}, \
             ref_id={:?})",
-           fn_id.repr(ccx.tcx()),
-           psubsts.repr(ccx.tcx()),
+           fn_id,
+           psubsts,
            ref_id);
 
     assert!(psubsts.types.all(|t| {
@@ -60,6 +59,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     };
 
     let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
+
+    debug!("monomorphic_fn about to subst into {:?}", item_ty);
     let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
 
     match ccx.monomorphized().borrow().get(&hash_id) {
@@ -72,11 +73,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 
     debug!("monomorphic_fn(\
-            fn_id={}, \
-            psubsts={}, \
+            fn_id={:?}, \
+            psubsts={:?}, \
             hash_id={:?})",
-           fn_id.repr(ccx.tcx()),
-           psubsts.repr(ccx.tcx()),
+           fn_id,
+           psubsts,
            hash_id);
 
 
@@ -97,12 +98,10 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     }
 
-    debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
-
-    debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
+    debug!("mono_ty = {:?} (post-substitution)", mono_ty);
 
     let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);
-    debug!("mono_ty = {} (post-normalization)", mono_ty.repr(ccx.tcx()));
+    debug!("mono_ty = {:?} (post-normalization)", mono_ty);
 
     ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1);
 
@@ -177,7 +176,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ast_map::NodeItem(i) => {
             match *i {
               ast::Item {
-                  node: ast::ItemFn(ref decl, _, abi, _, ref body),
+                  node: ast::ItemFn(ref decl, _, _, abi, _, ref body),
                   ..
               } => {
                   let d = mk_lldecl(abi);
@@ -303,7 +302,7 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
                                   param_substs: &Substs<'tcx>,
                                   value: &T)
                                   -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
     let substituted = value.subst(tcx, param_substs);
     normalize_associated_type(tcx, &substituted)
@@ -314,9 +313,9 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
 /// and hence we can be sure that all associated types will be
 /// completely normalized away.
 pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
-    where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
-    debug!("normalize_associated_type(t={})", value.repr(tcx));
+    debug!("normalize_associated_type(t={:?})", value);
 
     let value = erase_regions(tcx, value);
 
@@ -333,11 +332,11 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
     let traits::Normalized { value: result, obligations } =
         traits::normalize(&mut selcx, cause, &value);
 
-    debug!("normalize_associated_type: result={} obligations={}",
-           result.repr(tcx),
-           obligations.repr(tcx));
+    debug!("normalize_associated_type: result={:?} obligations={:?}",
+           result,
+           obligations);
 
-    let mut fulfill_cx = traits::FulfillmentContext::new();
+    let mut fulfill_cx = traits::FulfillmentContext::new(true);
     for obligation in obligations {
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
index b02fcb6cf0c535062c539f61a73561436116e6a9..bba0f6d26083a6d04e4fd1e7c72a7dd4c0540835 100644 (file)
@@ -28,7 +28,6 @@ use trans::machine::llsize_of_alloc;
 use trans::type_::Type;
 use trans::type_of;
 use middle::ty::{self, Ty};
-use util::ppaux::ty_to_string;
 
 use syntax::ast;
 use syntax::parse::token::InternedString;
@@ -42,7 +41,7 @@ struct VecTypes<'tcx> {
 impl<'tcx> VecTypes<'tcx> {
     pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
         format!("VecTypes {{unit_ty={}, llunit_ty={}}}",
-                ty_to_string(ccx.tcx(), self.unit_ty),
+                self.unit_ty,
                 ccx.tn().type_to_string(self.llunit_ty))
     }
 }
@@ -58,8 +57,8 @@ pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // to store the array of the suitable size, so all we have to do is
     // generate the content.
 
-    debug!("trans_fixed_vstore(expr={}, dest={})",
-           bcx.expr_to_string(expr), dest.to_string(bcx.ccx()));
+    debug!("trans_fixed_vstore(expr={:?}, dest={})",
+           expr, dest.to_string(bcx.ccx()));
 
     let vt = vec_types_from_expr(bcx, expr);
 
@@ -85,8 +84,8 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let ccx = fcx.ccx;
     let mut bcx = bcx;
 
-    debug!("trans_slice_vec(slice_expr={})",
-           bcx.expr_to_string(slice_expr));
+    debug!("trans_slice_vec(slice_expr={:?})",
+           slice_expr);
 
     let vec_ty = node_id_type(bcx, slice_expr.id);
 
@@ -139,8 +138,8 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  str_lit: InternedString,
                                  dest: Dest)
                                  -> Block<'blk, 'tcx> {
-    debug!("trans_lit_str(lit_expr={}, dest={})",
-           bcx.expr_to_string(lit_expr),
+    debug!("trans_lit_str(lit_expr={:?}, dest={})",
+           lit_expr,
            dest.to_string(bcx.ccx()));
 
     match dest {
@@ -167,10 +166,10 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let fcx = bcx.fcx;
     let mut bcx = bcx;
 
-    debug!("write_content(vt={}, dest={}, vstore_expr={})",
+    debug!("write_content(vt={}, dest={}, vstore_expr={:?})",
            vt.to_string(bcx.ccx()),
            dest.to_string(bcx.ccx()),
-           bcx.expr_to_string(vstore_expr));
+           vstore_expr);
 
     match content_expr.node {
         ast::ExprLit(ref lit) => {
@@ -310,15 +309,15 @@ pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let ccx = bcx.ccx();
 
     match vec_ty.sty {
-        ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
-        ty::ty_vec(_, None) | ty::ty_str => {
+        ty::TyArray(_, n) => get_fixed_base_and_len(bcx, llval, n),
+        ty::TySlice(_) | ty::TyStr => {
             let base = Load(bcx, expr::get_dataptr(bcx, llval));
             let len = Load(bcx, expr::get_len(bcx, llval));
             (base, len)
         }
 
         // Only used for pattern matching.
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+        ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => {
             let inner = if type_is_sized(bcx.tcx(), ty) {
                 Load(bcx, llval)
             } else {
index 339b4734ee4b1b82da3ed88cf46794314666ade2..b80b2b8266a2cfe43c71165f8e2bf43d7423d0ee 100644 (file)
@@ -171,10 +171,6 @@ impl Type {
         Type::struct_(ccx, &[], false)
     }
 
-    pub fn vtable(ccx: &CrateContext) -> Type {
-        Type::array(&Type::i8p(ccx).ptr_to(), 1)
-    }
-
     pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
         Type::func(&[t], &Type::void(ccx))
     }
index 9f01521313633360909b34399635ecc7049b589d..49601ac6fe94dd85e5f713beecc42aa9f07303d4 100644 (file)
@@ -16,8 +16,6 @@ use trans::common::*;
 use trans::foreign;
 use trans::machine;
 use middle::ty::{self, RegionEscape, Ty};
-use util::ppaux;
-use util::ppaux::Repr;
 
 use trans::type_::Type;
 
@@ -38,12 +36,12 @@ fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn arg_is_indirect<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                  arg_ty: Ty<'tcx>) -> bool {
-    !type_is_immediate(ccx, arg_ty)
+    !type_is_immediate(ccx, arg_ty) && !type_is_fat_ptr(ccx.tcx(), arg_ty)
 }
 
 pub fn return_uses_outptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     ty: Ty<'tcx>) -> bool {
-    !type_is_immediate(ccx, ty)
+    arg_is_indirect(ccx, ty)
 }
 
 pub fn type_of_explicit_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -79,7 +77,7 @@ pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 
     match inputs[inputs.len() - 1].sty {
-        ty::ty_tup(ref tupled_arguments) => {
+        ty::TyTuple(ref tupled_arguments) => {
             debug!("untuple_arguments_if_necessary(): untupling arguments");
             for &tupled_argument in tupled_arguments {
                 result.push(tupled_argument);
@@ -100,8 +98,8 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                  abi: abi::Abi)
                                  -> Type
 {
-    debug!("type_of_rust_fn(sig={},abi={:?})",
-           sig.repr(cx.tcx()),
+    debug!("type_of_rust_fn(sig={:?},abi={:?})",
+           sig,
            abi);
 
     let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
@@ -138,8 +136,15 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     // ... then explicit args.
-    let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
-    atys.extend(input_tys);
+    for input in &inputs {
+        let arg_ty = type_of_explicit_arg(cx, input);
+
+        if type_is_fat_ptr(cx.tcx(), input) {
+            atys.extend(arg_ty.field_types());
+        } else {
+            atys.push(arg_ty);
+        }
+    }
 
     Type::func(&atys[..], &lloutputtype)
 }
@@ -147,7 +152,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 // Given a function type and a count of ty params, construct an llvm type
 pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) -> Type {
     match fty.sty {
-        ty::ty_bare_fn(_, ref f) => {
+        ty::TyBareFn(_, ref f) => {
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
             if f.abi == abi::Rust || f.abi == abi::RustCall {
@@ -184,13 +189,13 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
         }
 
-        ty::ty_bool => Type::bool(cx),
-        ty::ty_char => Type::char(cx),
-        ty::ty_int(t) => Type::int_from_ty(cx, t),
-        ty::ty_uint(t) => Type::uint_from_ty(cx, t),
-        ty::ty_float(t) => Type::float_from_ty(cx, t),
+        ty::TyBool => Type::bool(cx),
+        ty::TyChar => Type::char(cx),
+        ty::TyInt(t) => Type::int_from_ty(cx, t),
+        ty::TyUint(t) => Type::uint_from_ty(cx, t),
+        ty::TyFloat(t) => Type::float_from_ty(cx, t),
 
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
+        ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) | ty::TyRawPtr(ty::mt{ty, ..}) => {
             if type_is_sized(cx.tcx(), ty) {
                 Type::i8p(cx)
             } else {
@@ -198,25 +203,25 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::ty_bare_fn(..) => Type::i8p(cx),
+        ty::TyBareFn(..) => Type::i8p(cx),
 
-        ty::ty_vec(ty, Some(size)) => {
+        ty::TyArray(ty, size) => {
             let llty = sizing_type_of(cx, ty);
             let size = size as u64;
             ensure_array_fits_in_address_space(cx, llty, size, t);
             Type::array(&llty, size)
         }
 
-        ty::ty_tup(ref tys) if tys.is_empty() => {
+        ty::TyTuple(ref tys) if tys.is_empty() => {
             Type::nil(cx)
         }
 
-        ty::ty_tup(..) | ty::ty_enum(..) | ty::ty_closure(..) => {
+        ty::TyTuple(..) | ty::TyEnum(..) | ty::TyClosure(..) => {
             let repr = adt::represent_type(cx, t);
             adt::sizing_type_of(cx, &*repr, false)
         }
 
-        ty::ty_struct(..) => {
+        ty::TyStruct(..) => {
             if ty::type_is_simd(cx.tcx(), t) {
                 let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
                 let n = ty::simd_size(cx.tcx(), t) as u64;
@@ -228,11 +233,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
-            cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
-                                  ppaux::ty_to_string(cx.tcx(), t)))
+        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError(..) => {
+            cx.sess().bug(&format!("fictitious type {:?} in sizing_type_of()",
+                                   t))
         }
-        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
+        ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => unreachable!()
     };
 
     cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@@ -299,7 +304,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
         None => ()
     }
 
-    debug!("type_of {} {:?}", t.repr(cx.tcx()), t.sty);
+    debug!("type_of {:?}", t);
 
     assert!(!t.has_escaping_regions());
 
@@ -312,10 +317,10 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
 
     if t != t_norm {
         let llty = in_memory_type_of(cx, t_norm);
-        debug!("--> normalized {} {:?} to {} {:?} llty={}",
-                t.repr(cx.tcx()),
+        debug!("--> normalized {:?} {:?} to {:?} {:?} llty={}",
                 t,
-                t_norm.repr(cx.tcx()),
+                t,
+                t_norm,
                 t_norm,
                 cx.tn().type_to_string(llty));
         cx.lltypes().borrow_mut().insert(t, llty);
@@ -323,12 +328,12 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
     }
 
     let mut llty = match t.sty {
-      ty::ty_bool => Type::bool(cx),
-      ty::ty_char => Type::char(cx),
-      ty::ty_int(t) => Type::int_from_ty(cx, t),
-      ty::ty_uint(t) => Type::uint_from_ty(cx, t),
-      ty::ty_float(t) => Type::float_from_ty(cx, t),
-      ty::ty_enum(did, ref substs) => {
+      ty::TyBool => Type::bool(cx),
+      ty::TyChar => Type::char(cx),
+      ty::TyInt(t) => Type::int_from_ty(cx, t),
+      ty::TyUint(t) => Type::uint_from_ty(cx, t),
+      ty::TyFloat(t) => Type::float_from_ty(cx, t),
+      ty::TyEnum(did, ref substs) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache. This
           // avoids creating more than one copy of the enum when one
@@ -338,7 +343,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           let name = llvm_type_name(cx, did, tps);
           adt::incomplete_type_of(cx, &*repr, &name[..])
       }
-      ty::ty_closure(..) => {
+      ty::TyClosure(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache.
           let repr = adt::represent_type(cx, t);
@@ -349,9 +354,9 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           adt::incomplete_type_of(cx, &*repr, "closure")
       }
 
-      ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
+      ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) | ty::TyRawPtr(ty::mt{ty, ..}) => {
           if !type_is_sized(cx.tcx(), ty) {
-              if let ty::ty_str = ty.sty {
+              if let ty::TyStr = ty.sty {
                   // This means we get a nicer name in the output (str is always
                   // unsized).
                   cx.tn().find_type("str_slice").unwrap()
@@ -359,13 +364,13 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
                   let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
                   let unsized_part = ty::struct_tail(cx.tcx(), ty);
                   let info_ty = match unsized_part.sty {
-                      ty::ty_str | ty::ty_vec(..) => {
+                      ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
                           Type::uint_from_ty(cx, ast::TyUs)
                       }
-                      ty::ty_trait(_) => Type::vtable_ptr(cx),
+                      ty::TyTrait(_) => Type::vtable_ptr(cx),
                       _ => panic!("Unexpected type returned from \
-                                   struct_tail: {} for ty={}",
-                                  unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
+                                   struct_tail: {:?} for ty={:?}",
+                                  unsized_part, ty)
                   };
                   Type::struct_(cx, &[ptr_ty, info_ty], false)
               }
@@ -374,7 +379,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           }
       }
 
-      ty::ty_vec(ty, Some(size)) => {
+      ty::TyArray(ty, size) => {
           let size = size as u64;
           let llty = in_memory_type_of(cx, ty);
           ensure_array_fits_in_address_space(cx, llty, size, t);
@@ -385,18 +390,18 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
       // traits have the type of u8. This is so that the data pointer inside
       // fat pointers is of the right type (e.g. for array accesses), even
       // when taking the address of an unsized field in a struct.
-      ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
-      ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
+      ty::TySlice(ty) => in_memory_type_of(cx, ty),
+      ty::TyStr | ty::TyTrait(..) => Type::i8(cx),
 
-      ty::ty_bare_fn(..) => {
+      ty::TyBareFn(..) => {
           type_of_fn_from_ty(cx, t).ptr_to()
       }
-      ty::ty_tup(ref tys) if tys.is_empty() => Type::nil(cx),
-      ty::ty_tup(..) => {
+      ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
+      ty::TyTuple(..) => {
           let repr = adt::represent_type(cx, t);
           adt::type_of(cx, &*repr)
       }
-      ty::ty_struct(did, ref substs) => {
+      ty::TyStruct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
               let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
               let n = ty::simd_size(cx.tcx(), t) as u64;
@@ -413,14 +418,14 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           }
       }
 
-      ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
-      ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
-      ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
-      ty::ty_err(..) => cx.sess().bug("type_of with ty_err"),
+      ty::TyInfer(..) => cx.sess().bug("type_of with TyInfer"),
+      ty::TyProjection(..) => cx.sess().bug("type_of with TyProjection"),
+      ty::TyParam(..) => cx.sess().bug("type_of with ty_param"),
+      ty::TyError(..) => cx.sess().bug("type_of with TyError"),
     };
 
-    debug!("--> mapped t={} {:?} to llty={}",
-            t.repr(cx.tcx()),
+    debug!("--> mapped t={:?} {:?} to llty={}",
+            t,
             t,
             cx.tn().type_to_string(llty));
 
@@ -428,7 +433,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
 
     // If this was an enum or struct, fill in the type now.
     match t.sty {
-        ty::ty_enum(..) | ty::ty_struct(..) | ty::ty_closure(..)
+        ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..)
                 if !ty::type_is_simd(cx.tcx(), t) => {
             let repr = adt::represent_type(cx, t);
             adt::finish_type_of(cx, &*repr, &mut llty);
@@ -450,7 +455,7 @@ fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                             tps: &[Ty<'tcx>])
                             -> String {
     let base = ty::item_path_str(cx.tcx(), did);
-    let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
+    let strings: Vec<String> = tps.iter().map(|t| t.to_string()).collect();
     let tstr = if strings.is_empty() {
         base
     } else {
index 54ec1aace92112fe16a1109126004b15fdbacdc6..922ca61227e50f1d6c65c9058b301a32349fdda7 100644 (file)
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
 use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
-use middle::const_eval;
+use middle::const_eval::{self, ConstVal};
 use middle::def;
 use middle::implicator::object_region_bounds;
 use middle::resolve_lifetime as rl;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
-use middle::ty::{self, RegionEscape, Ty};
+use middle::ty::{self, RegionEscape, Ty, AsPredicate};
+use middle::ty_fold;
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ExplicitRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::FnvHashSet;
-use util::ppaux::{self, Repr, UserString};
 
 use std::iter::repeat;
 use std::slice;
@@ -178,10 +178,10 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
         }
     };
 
-    debug!("ast_region_to_region(lifetime={} id={}) yields {}",
-           lifetime.repr(tcx),
+    debug!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
+           lifetime,
            lifetime.id,
-           r.repr(tcx));
+           r);
 
     r
 }
@@ -256,9 +256,9 @@ pub fn opt_ast_region_to_region<'tcx>(
         }
     };
 
-    debug!("opt_ast_region_to_region(opt_lifetime={}) yields {}",
-            opt_lifetime.repr(this.tcx()),
-            r.repr(this.tcx()));
+    debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
+            opt_lifetime,
+            r);
 
     r
 }
@@ -291,10 +291,13 @@ pub fn ast_path_substs_for_ty<'tcx>(
         ast::AngleBracketedParameters(ref data) => {
             convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
         }
-        ast::ParenthesizedParameters(ref data) => {
+        ast::ParenthesizedParameters(..) => {
             span_err!(tcx.sess, span, E0214,
-                "parenthesized parameters may only be used with a trait");
-            convert_parenthesized_parameters(this, rscope, span, decl_generics, data)
+                      "parenthesized parameters may only be used with a trait");
+            let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
+            (Substs::empty(),
+             ty_param_defs.iter().map(|_| tcx.types.err).collect(),
+             vec![])
         }
     };
 
@@ -373,10 +376,10 @@ 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={}",
-           decl_generics.repr(tcx), self_ty.repr(tcx), types_provided.repr(tcx),
-           region_substs.repr(tcx));
+    debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
+           types_provided={:?}, region_substs={:?}",
+           decl_generics, self_ty, types_provided,
+           region_substs);
 
     assert_eq!(region_substs.regions().len(TypeSpace), decl_generics.regions.len(TypeSpace));
     assert!(region_substs.types.is_empty());
@@ -437,13 +440,12 @@ fn create_substs_for_ast_path<'tcx>(
             // defaults. This will lead to an ICE if we are not
             // careful!
             if self_ty.is_none() && ty::type_has_self(default) {
-                tcx.sess.span_err(
-                    span,
-                    &format!("the type parameter `{}` must be explicitly specified \
-                              in an object type because its default value `{}` references \
-                              the type `Self`",
-                             param.name.user_string(tcx),
-                             default.user_string(tcx)));
+                span_err!(tcx.sess, span, E0393,
+                          "the type parameter `{}` must be explicitly specified \
+                           in an object type because its default value `{}` references \
+                           the type `Self`",
+                          param.name,
+                          default);
                 substs.types.push(TypeSpace, tcx.types.err);
             } else {
                 // This is a default type parameter.
@@ -509,7 +511,7 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
     let mut lifetimes_for_params: Vec<(String, usize)> = Vec::new();
     let mut possible_implied_output_region = None;
 
-    for (input_type, input_pat) in input_tys.iter().zip(input_pats.into_iter()) {
+    for (input_type, input_pat) in input_tys.iter().zip(input_pats) {
         let mut accumulator = Vec::new();
         ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type);
 
@@ -650,7 +652,7 @@ fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::D
         def::DefTrait(trait_def_id) => trait_def_id,
         _ => {
             span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
-                        path.user_string(this.tcx()));
+                        path);
         }
     }
 }
@@ -880,7 +882,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
 
     let candidate = try!(one_bound_for_assoc_type(tcx,
                                                   candidates,
-                                                  &trait_ref.user_string(tcx),
+                                                  &trait_ref.to_string(),
                                                   &token::get_name(binding.item_name),
                                                   binding.span));
 
@@ -986,19 +988,21 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
             });
             match (&ty.node, full_span) {
                 (&ast::TyRptr(None, ref mut_ty), Some(full_span)) => {
+                    let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
                     this.tcx().sess
                         .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                          format!("&{}({} +{})",
-                                                 ppaux::mutability_to_string(mut_ty.mutbl),
+                                                 mutbl_str,
                                                  pprust::ty_to_string(&*mut_ty.ty),
                                                  pprust::bounds_to_string(bounds)));
                 }
                 (&ast::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
+                    let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
                     this.tcx().sess
                         .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                          format!("&{} {}({} +{})",
                                                  pprust::lifetime_to_string(lt),
-                                                 ppaux::mutability_to_string(mut_ty.mutbl),
+                                                 mutbl_str,
                                                  pprust::ty_to_string(&*mut_ty.ty),
                                                  pprust::bounds_to_string(bounds)));
                 }
@@ -1029,8 +1033,8 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
                                                      bounds);
 
     let result = make_object_type(this, span, trait_ref, existential_bounds);
-    debug!("trait_ref_to_object_type: result={}",
-           result.repr(this.tcx()));
+    debug!("trait_ref_to_object_type: result={:?}",
+           result);
 
     result
 }
@@ -1041,7 +1045,7 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
                           bounds: ty::ExistentialBounds<'tcx>)
                           -> Ty<'tcx> {
     let tcx = this.tcx();
-    let object = ty::TyTrait {
+    let object = ty::TraitTy {
         principal: principal,
         bounds: bounds
     };
@@ -1073,7 +1077,7 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
     for (trait_def_id, name) in associated_types {
         span_err!(tcx.sess, span, E0191,
             "the value of the associated type `{}` (from the trait `{}`) must be specified",
-                    name.user_string(tcx),
+                    name,
                     ty::item_path_str(tcx, trait_def_id));
     }
 
@@ -1159,7 +1163,7 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
             span_note!(tcx.sess, span,
                        "associated type `{}` could derive from `{}`",
                        ty_param_name,
-                       bound.user_string(tcx));
+                       bound);
         }
     }
 
@@ -1182,7 +1186,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     let tcx = this.tcx();
     let assoc_name = item_segment.identifier.name;
 
-    debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name));
+    debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
 
     check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
 
@@ -1225,8 +1229,8 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 _ => unreachable!()
             }
         }
-        (&ty::ty_param(_), def::DefTyParam(..)) |
-        (&ty::ty_param(_), def::DefSelfTy(Some(_), None)) => {
+        (&ty::TyParam(_), def::DefTyParam(..)) |
+        (&ty::TyParam(_), def::DefSelfTy(Some(_), None)) => {
             // A type parameter or Self, we need to find the associated item from
             // a bound.
             let ty_param_node_id = ty_path_def.local_node_id();
@@ -1238,7 +1242,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         _ => {
             report_ambiguous_associated_type(tcx,
                                              span,
-                                             &ty.user_string(tcx),
+                                             &ty.to_string(),
                                              "Trait",
                                              &token::get_name(assoc_name));
             return (tcx.types.err, ty_path_def);
@@ -1295,7 +1299,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
         return tcx.types.err;
     };
 
-    debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
+    debug!("qpath_to_ty: self_type={:?}", self_ty);
 
     let trait_ref = ast_path_to_mono_trait_ref(this,
                                                rscope,
@@ -1305,7 +1309,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
                                                Some(self_ty),
                                                trait_segment);
 
-    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
+    debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
 
     this.projected_ty(span, trait_ref, item_segment.identifier.name)
 }
@@ -1395,7 +1399,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             // Self in impl (we know the concrete type).
             check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
             if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
-                ty
+                if let Some(free_substs) = this.get_free_substs() {
+                    ty.subst(tcx, free_substs)
+                } else {
+                    ty
+                }
             } else {
                 tcx.sess.span_bug(span, "self type has not been fully resolved")
             }
@@ -1468,7 +1476,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     let mut def = *def;
     // If any associated type segments remain, attempt to resolve them.
     for segment in assoc_segments {
-        if ty.sty == ty::ty_err {
+        if ty.sty == ty::TyError {
             break;
         }
         // This is pretty bad (it will fail except for T::A and Self::A).
@@ -1490,8 +1498,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                           ast_ty: &ast::Ty)
                           -> Ty<'tcx>
 {
-    debug!("ast_ty_to_ty(ast_ty={})",
-           ast_ty.repr(this.tcx()));
+    debug!("ast_ty_to_ty(ast_ty={:?})",
+           ast_ty);
 
     let tcx = this.tcx();
 
@@ -1526,11 +1534,11 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
         }
         ast::TyRptr(ref region, ref mt) => {
             let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
-            debug!("ty_rptr r={}", r.repr(this.tcx()));
+            debug!("TyRef r={:?}", r);
             let rscope1 =
                 &ObjectLifetimeDefaultRscope::new(
                     rscope,
-                    Some(ty::ObjectLifetimeDefault::Specific(r)));
+                    ty::ObjectLifetimeDefault::Specific(r));
             let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
             ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
         }
@@ -1543,7 +1551,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
         ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
         ast::TyBareFn(ref bf) => {
             if bf.decl.variadic && bf.abi != abi::C {
-                span_err!(tcx.sess, ast_ty.span, E0222,
+                span_err!(tcx.sess, ast_ty.span, E0045,
                           "variadic function must have C calling convention");
             }
             let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
@@ -1563,8 +1571,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                     depth: path.segments.len()
                 }
             } else {
-                tcx.sess.span_bug(ast_ty.span,
-                                  &format!("unbound path {}", ast_ty.repr(tcx)))
+                tcx.sess.span_bug(ast_ty.span, &format!("unbound path {:?}", ast_ty))
             };
             let def = path_res.base_def;
             let base_ty_end = path.segments.len() - path_res.depth;
@@ -1580,7 +1587,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                                                 &path.segments[..base_ty_end],
                                                 &path.segments[base_ty_end..]);
 
-            if path_res.depth != 0 && ty.sty != ty::ty_err {
+            if path_res.depth != 0 && ty.sty != ty::TyError {
                 // Write back the new resolution.
                 tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution {
                     base_def: def,
@@ -1595,10 +1602,10 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.usize)) {
                 Ok(r) => {
                     match r {
-                        const_eval::const_int(i) =>
+                        ConstVal::Int(i) =>
                             ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
                                         Some(i as usize)),
-                        const_eval::const_uint(i) =>
+                        ConstVal::Uint(i) =>
                             ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
                                         Some(i as usize)),
                         _ => {
@@ -1838,11 +1845,11 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
             let impl_modifiers = count_modifiers(self_info.untransformed_self_ty);
             let method_modifiers = count_modifiers(explicit_type);
 
-            debug!("determine_explicit_self_category(self_info.untransformed_self_ty={} \
-                   explicit_type={} \
+            debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
+                   explicit_type={:?} \
                    modifiers=({},{})",
-                   self_info.untransformed_self_ty.repr(this.tcx()),
-                   explicit_type.repr(this.tcx()),
+                   self_info.untransformed_self_ty,
+                   explicit_type,
                    impl_modifiers,
                    method_modifiers);
 
@@ -1850,8 +1857,8 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
                 ty::ByValueExplicitSelfCategory
             } else {
                 match explicit_type.sty {
-                    ty::ty_rptr(r, mt) => ty::ByReferenceExplicitSelfCategory(*r, mt.mutbl),
-                    ty::ty_uniq(_) => ty::ByBoxExplicitSelfCategory,
+                    ty::TyRef(r, mt) => ty::ByReferenceExplicitSelfCategory(*r, mt.mutbl),
+                    ty::TyBox(_) => ty::ByBoxExplicitSelfCategory,
                     _ => ty::ByValueExplicitSelfCategory,
                 }
             }
@@ -1860,8 +1867,8 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
 
     fn count_modifiers(ty: Ty) -> usize {
         match ty.sty {
-            ty::ty_rptr(_, mt) => count_modifiers(mt.ty) + 1,
-            ty::ty_uniq(t) => count_modifiers(t) + 1,
+            ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
+            ty::TyBox(t) => count_modifiers(t) + 1,
             _ => 0,
         }
     }
@@ -1875,8 +1882,8 @@ pub fn ty_of_closure<'tcx>(
     expected_sig: Option<ty::FnSig<'tcx>>)
     -> ty::ClosureTy<'tcx>
 {
-    debug!("ty_of_closure(expected_sig={})",
-           expected_sig.repr(this.tcx()));
+    debug!("ty_of_closure(expected_sig={:?})",
+           expected_sig);
 
     // new region names that appear inside of the fn decl are bound to
     // that function type
@@ -1914,8 +1921,8 @@ pub fn ty_of_closure<'tcx>(
         ast::NoReturn(..) => ty::FnDiverging
     };
 
-    debug!("ty_of_closure: input_tys={}", input_tys.repr(this.tcx()));
-    debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx()));
+    debug!("ty_of_closure: input_tys={:?}", input_tys);
+    debug!("ty_of_closure: output_ty={:?}", output_ty);
 
     ty::ClosureTy {
         unsafety: unsafety,
@@ -2000,12 +2007,30 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
                   "only the builtin traits can be used as closure or object bounds");
     }
 
-    let region_bound = compute_object_lifetime_bound(this,
-                                                     rscope,
-                                                     span,
-                                                     &region_bounds,
-                                                     principal_trait_ref,
-                                                     builtin_bounds);
+    let region_bound =
+        compute_object_lifetime_bound(this,
+                                      span,
+                                      &region_bounds,
+                                      principal_trait_ref,
+                                      builtin_bounds);
+
+    let (region_bound, will_change) = match region_bound {
+        Some(r) => (r, false),
+        None => {
+            match rscope.object_lifetime_default(span) {
+                Some(r) => (r, rscope.object_lifetime_default_will_change_in_1_3()),
+                None => {
+                    span_err!(this.tcx().sess, span, E0228,
+                              "the lifetime bound for this object type cannot be deduced \
+                               from context; please supply an explicit bound");
+                    (ty::ReStatic, false)
+                }
+            }
+        }
+    };
+
+    debug!("region_bound: {:?} will_change: {:?}",
+           region_bound, will_change);
 
     ty::sort_bounds_list(&mut projection_bounds);
 
@@ -2013,6 +2038,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
         region_bound: region_bound,
         builtin_bounds: builtin_bounds,
         projection_bounds: projection_bounds,
+        region_bound_will_change: will_change,
     }
 }
 
@@ -2022,20 +2048,19 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
 /// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
 fn compute_object_lifetime_bound<'tcx>(
     this: &AstConv<'tcx>,
-    rscope: &RegionScope,
     span: Span,
     explicit_region_bounds: &[&ast::Lifetime],
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
     builtin_bounds: ty::BuiltinBounds)
-    -> ty::Region
+    -> Option<ty::Region> // if None, use the default
 {
     let tcx = this.tcx();
 
     debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
-           principal_trait_ref={}, builtin_bounds={})",
+           principal_trait_ref={:?}, builtin_bounds={:?})",
            explicit_region_bounds,
-           principal_trait_ref.repr(tcx),
-           builtin_bounds.repr(tcx));
+           principal_trait_ref,
+           builtin_bounds);
 
     if explicit_region_bounds.len() > 1 {
         span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
@@ -2045,11 +2070,11 @@ fn compute_object_lifetime_bound<'tcx>(
     if !explicit_region_bounds.is_empty() {
         // Explicitly specified region bound. Use that.
         let r = explicit_region_bounds[0];
-        return ast_region_to_region(tcx, r);
+        return Some(ast_region_to_region(tcx, r));
     }
 
     if let Err(ErrorReported) = this.ensure_super_predicates(span,principal_trait_ref.def_id()) {
-        return ty::ReStatic;
+        return Some(ty::ReStatic);
     }
 
     // No explicit region bound specified. Therefore, examine trait
@@ -2058,23 +2083,15 @@ fn compute_object_lifetime_bound<'tcx>(
         object_region_bounds(tcx, &principal_trait_ref, builtin_bounds);
 
     // If there are no derived region bounds, then report back that we
-    // can find no region bound.
+    // can find no region bound. The caller will use the default.
     if derived_region_bounds.is_empty() {
-        match rscope.object_lifetime_default(span) {
-            Some(r) => { return r; }
-            None => {
-                span_err!(this.tcx().sess, span, E0228,
-                          "the lifetime bound for this object type cannot be deduced \
-                           from context; please supply an explicit bound");
-                return ty::ReStatic;
-            }
-        }
+        return None;
     }
 
     // If any of the derived region bounds are 'static, that is always
     // the best choice.
     if derived_region_bounds.iter().any(|r| ty::ReStatic == *r) {
-        return ty::ReStatic;
+        return Some(ty::ReStatic);
     }
 
     // Determine whether there is exactly one unique region in the set
@@ -2085,7 +2102,7 @@ fn compute_object_lifetime_bound<'tcx>(
         span_err!(tcx.sess, span, E0227,
                   "ambiguous lifetime bound, explicit lifetime bound required");
     }
-    return r;
+    return Some(r);
 }
 
 pub struct PartitionedBounds<'a> {
@@ -2101,7 +2118,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                             ast_bounds: &'a [ast::TyParamBound])
                             -> PartitionedBounds<'a>
 {
-    let mut builtin_bounds = ty::empty_builtin_bounds();
+    let mut builtin_bounds = ty::BuiltinBounds::empty();
     let mut region_bounds = Vec::new();
     let mut trait_bounds = Vec::new();
     for ast_bound in ast_bounds {
@@ -2185,3 +2202,47 @@ fn report_lifetime_number_error(tcx: &ty::ctxt, span: Span, number: usize, expec
               "wrong number of lifetime parameters: expected {}, found {}",
               expected, number);
 }
+
+// A helper struct for conveniently grouping a set of bounds which we pass to
+// and return from functions in multiple places.
+#[derive(PartialEq, Eq, Clone, Debug)]
+pub struct Bounds<'tcx> {
+    pub region_bounds: Vec<ty::Region>,
+    pub builtin_bounds: ty::BuiltinBounds,
+    pub trait_bounds: Vec<ty::PolyTraitRef<'tcx>>,
+    pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
+}
+
+impl<'tcx> Bounds<'tcx> {
+    pub fn predicates(&self,
+        tcx: &ty::ctxt<'tcx>,
+        param_ty: Ty<'tcx>)
+        -> Vec<ty::Predicate<'tcx>>
+    {
+        let mut vec = Vec::new();
+
+        for builtin_bound in &self.builtin_bounds {
+            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
+                Ok(trait_ref) => { vec.push(trait_ref.as_predicate()); }
+                Err(ErrorReported) => { }
+            }
+        }
+
+        for &region_bound in &self.region_bounds {
+            // account for the binder being introduced below; no need to shift `param_ty`
+            // because, at present at least, it can only refer to early-bound regions
+            let region_bound = ty_fold::shift_region(region_bound, 1);
+            vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).as_predicate());
+        }
+
+        for bound_trait_ref in &self.trait_bounds {
+            vec.push(bound_trait_ref.as_predicate());
+        }
+
+        for projection in &self.projection_bounds {
+            vec.push(projection.as_predicate());
+        }
+
+        vec
+    }
+}
index 1f4d6cc2fd471b4b8e04539edcb12438dedc6c36..cf086a32ae599b27803a0437e3b973ced446c067 100644 (file)
@@ -18,10 +18,10 @@ use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
+use check::{check_expr_with_lvalue_pref, LvaluePreference};
 use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
 use require_same_types;
 use util::nodemap::FnvHashMap;
-use util::ppaux::Repr;
 
 use std::cmp::{self, Ordering};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -39,9 +39,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    debug!("check_pat(pat={},expected={})",
-           pat.repr(tcx),
-           expected.repr(tcx));
+    debug!("check_pat(pat={:?},expected={:?})",
+           pat,
+           expected);
 
     match pat.node {
         ast::PatWild(_) => {
@@ -57,8 +57,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             if let ast::ExprLit(ref lt) = lt.node {
                 if let ast::LitBinary(_) = lt.node {
                     let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
-                    if let ty::ty_rptr(_, mt) = expected_ty.sty {
-                        if let ty::ty_vec(_, None) = mt.ty.sty {
+                    if let ty::TyRef(_, mt) = expected_ty.sty {
+                        if let ty::TySlice(_) = mt.ty.sty {
                             pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
                                 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
                         }
@@ -83,39 +83,64 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             demand::suptype(fcx, pat.span, expected, pat_ty);
         }
         ast::PatRange(ref begin, ref end) => {
-            check_expr(fcx, &**begin);
-            check_expr(fcx, &**end);
-
-            let lhs_ty = fcx.expr_ty(&**begin);
-            let rhs_ty = fcx.expr_ty(&**end);
-
-            let lhs_eq_rhs =
-                require_same_types(
-                    tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty,
-                    || "mismatched types in range".to_string());
-
-            let numeric_or_char =
-                lhs_eq_rhs && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(lhs_ty));
-
-            if numeric_or_char {
-                match const_eval::compare_lit_exprs(tcx, &**begin, &**end, Some(lhs_ty)) {
-                    Some(Ordering::Less) |
-                    Some(Ordering::Equal) => {}
-                    Some(Ordering::Greater) => {
-                        span_err!(tcx.sess, begin.span, E0030,
-                            "lower range bound must be less than upper");
-                    }
-                    None => {
-                        span_err!(tcx.sess, begin.span, E0031,
-                            "mismatched types in range");
-                    }
-                }
-            } else {
-                span_err!(tcx.sess, begin.span, E0029,
-                          "only char and numeric types are allowed in range");
+            check_expr(fcx, begin);
+            check_expr(fcx, end);
+
+            let lhs_ty = fcx.expr_ty(begin);
+            let rhs_ty = fcx.expr_ty(end);
+
+            // Check that both end-points are of numeric or char type.
+            let numeric_or_char = |t| ty::type_is_numeric(t) || ty::type_is_char(t);
+            let lhs_compat = numeric_or_char(lhs_ty);
+            let rhs_compat = numeric_or_char(rhs_ty);
+
+            if !lhs_compat || !rhs_compat {
+                let span = if !lhs_compat && !rhs_compat {
+                    pat.span
+                } else if !lhs_compat {
+                    begin.span
+                } else {
+                    end.span
+                };
+
+                // Note: spacing here is intentional, we want a space before "start" and "end".
+                span_err!(tcx.sess, span, E0029,
+                          "only char and numeric types are allowed in range patterns\n \
+                           start type: {}\n end type: {}",
+                          fcx.infcx().ty_to_string(lhs_ty),
+                          fcx.infcx().ty_to_string(rhs_ty)
+                );
+                return;
+            }
+
+            // Check that the types of the end-points can be unified.
+            let types_unify = require_same_types(
+                    tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
+                    || "mismatched types in range".to_string()
+            );
+
+            // It's ok to return without a message as `require_same_types` prints an error.
+            if !types_unify {
+                return;
             }
 
-            fcx.write_ty(pat.id, lhs_ty);
+            // Now that we know the types can be unified we find the unified type and use
+            // it to type the entire expression.
+            let common_type = fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
+
+            fcx.write_ty(pat.id, common_type);
+
+            // Finally we evaluate the constants and check that the range is non-empty.
+            let get_substs = |id| fcx.item_substs()[&id].substs.clone();
+            match const_eval::compare_lit_exprs(tcx, begin, end, Some(&common_type), get_substs) {
+                Some(Ordering::Less) |
+                Some(Ordering::Equal) => {}
+                Some(Ordering::Greater) => {
+                    span_err!(tcx.sess, begin.span, E0030,
+                        "lower range bound must be less than or equal to upper");
+                }
+                None => tcx.sess.span_bug(begin.span, "literals of different types in range pat")
+            }
 
             // subtyping doesn't matter here, as the value is some kind of scalar
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
@@ -196,7 +221,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 }
             } else {
                 tcx.sess.span_bug(pat.span,
-                                  &format!("unbound path {}", pat.repr(tcx)))
+                                  &format!("unbound path {:?}", pat))
             };
             if let Some((opt_ty, segments, def)) =
                     resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
@@ -224,7 +249,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let pat_ty = ty::mk_tup(tcx, element_tys.clone());
             fcx.write_ty(pat.id, pat_ty);
             demand::eqtype(fcx, pat.span, expected, pat_ty);
-            for (element_pat, element_ty) in elements.iter().zip(element_tys.into_iter()) {
+            for (element_pat, element_ty) in elements.iter().zip(element_tys) {
                 check_pat(pcx, &**element_pat, element_ty);
             }
         }
@@ -267,7 +292,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
             let inner_ty = fcx.infcx().next_ty_var();
             let pat_ty = match expected_ty.sty {
-                ty::ty_vec(_, Some(size)) => ty::mk_vec(tcx, inner_ty, Some({
+                ty::TyArray(_, size) => ty::mk_vec(tcx, inner_ty, Some({
                     let min_len = before.len() + after.len();
                     match *slice {
                         Some(_) => cmp::max(min_len, size),
@@ -387,7 +412,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     if pat_is_binding(&tcx.def_map, inner) {
         let expected = fcx.infcx().shallow_resolve(expected);
         ty::deref(expected, true).map_or(true, |mt| match mt.ty.sty {
-            ty::ty_trait(_) => {
+            ty::TyTrait(_) => {
                 // This is "x = SomeTrait" being reduced from
                 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
                 span_err!(tcx.sess, span, E0033,
@@ -413,10 +438,15 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Not entirely obvious: if matches may create ref bindings, we
     // want to use the *precise* type of the discriminant, *not* some
     // supertype, as the "discriminant type" (issue #23116).
-    let contains_ref_bindings = arms.iter().any(|a| tcx.arm_contains_ref_binding(a));
+    let contains_ref_bindings = arms.iter()
+                                    .filter_map(|a| tcx.arm_contains_ref_binding(a))
+                                    .max_by(|m| match *m {
+                                        ast::MutMutable => 1,
+                                        ast::MutImmutable => 0,
+                                    });
     let discrim_ty;
-    if contains_ref_bindings {
-        check_expr(fcx, discrim);
+    if let Some(m) = contains_ref_bindings {
+        check_expr_with_lvalue_pref(fcx, discrim, LvaluePreference::from_mutbl(m));
         discrim_ty = fcx.expr_ty(discrim);
     } else {
         // ...but otherwise we want to use any supertype of the
@@ -527,9 +557,9 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
         _ => {
             let def_type = ty::lookup_item_type(tcx, def.def_id());
             match def_type.ty.sty {
-                ty::ty_struct(struct_def_id, _) =>
+                ty::TyStruct(struct_def_id, _) =>
                     (struct_def_id, struct_def_id),
-                ty::ty_enum(enum_def_id, _)
+                ty::TyEnum(enum_def_id, _)
                     if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
                     (enum_def_id, def.def_id()),
                 _ => {
@@ -631,7 +661,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     let real_path_ty = fcx.node_ty(pat.id);
     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
-        ty::ty_enum(enum_def_id, expected_substs)
+        ty::TyEnum(enum_def_id, expected_substs)
             if def == def::DefVariant(enum_def_id, def.def_id(), false) =>
         {
             let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id());
@@ -640,7 +670,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                          .collect(),
              "variant")
         }
-        ty::ty_struct(struct_def_id, expected_substs) => {
+        ty::TyStruct(struct_def_id, expected_substs) => {
             let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs);
             (struct_fields.iter()
                           .map(|field| fcx.instantiate_type_scheme(pat.span,
@@ -666,8 +696,8 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     if let Some(subpats) = subpats {
         if subpats.len() == arg_tys.len() {
-            for (subpat, arg_ty) in subpats.iter().zip(arg_tys.iter()) {
-                check_pat(pcx, &**subpat, *arg_ty);
+            for (subpat, arg_ty) in subpats.iter().zip(arg_tys) {
+                check_pat(pcx, &**subpat, arg_ty);
             }
         } else if arg_tys.is_empty() {
             span_err!(tcx.sess, pat.span, E0024,
index 377af080526b7084a961c372de6535587d5cb511..df9fe6b002efba6efaeee2a74779a969eb4d366a 100644 (file)
@@ -12,10 +12,9 @@ use middle::infer::InferCtxt;
 use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
                      SelectionContext, ObligationCause};
 use middle::ty::{self, HasProjectionTypes};
-use middle::ty_fold::{TypeFoldable, TypeFolder};
+use middle::ty_fold::TypeFoldable;
 use syntax::ast;
 use syntax::codemap::Span;
-use util::ppaux::Repr;
 
 pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                 typer: &(ty::ClosureTyper<'tcx>+'a),
@@ -24,15 +23,15 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                 body_id: ast::NodeId,
                                                 value: &T)
                                                 -> T
-    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes
 {
-    debug!("normalize_associated_types_in(value={})", value.repr(infcx.tcx));
+    debug!("normalize_associated_types_in(value={:?})", value);
     let mut selcx = SelectionContext::new(infcx, typer);
     let cause = ObligationCause::new(span, body_id, MiscObligation);
     let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
-    debug!("normalize_associated_types_in: result={} predicates={}",
-           result.repr(infcx.tcx),
-           obligations.repr(infcx.tcx));
+    debug!("normalize_associated_types_in: result={:?} predicates={:?}",
+           result,
+           obligations);
     for obligation in obligations {
         fulfillment_cx.register_predicate_obligation(infcx, obligation);
     }
index b065eb2d2741cff20e1669944c8b04b5d3fa4d08..e7271d2fa88cf1ef123f12f452208d5292567e57 100644 (file)
@@ -32,7 +32,6 @@ use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::ptr::P;
-use util::ppaux::Repr;
 
 /// Check that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
@@ -120,19 +119,19 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       autoderefs: usize)
                                       -> Option<CallStep<'tcx>>
 {
-    debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefs={})",
-           call_expr.repr(fcx.tcx()),
-           adjusted_ty.repr(fcx.tcx()),
+    debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
+           call_expr,
+           adjusted_ty,
            autoderefs);
 
     // If the callee is a bare function or a closure, then we're all set.
     match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
-        ty::ty_bare_fn(..) => {
+        ty::TyBareFn(..) => {
             fcx.write_autoderef_adjustment(callee_expr.id, autoderefs);
             return Some(CallStep::Builtin);
         }
 
-        ty::ty_closure(def_id, substs) => {
+        ty::TyClosure(def_id, substs) => {
             assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
             // Check whether this is a call to a closure where we
@@ -165,7 +164,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         // over the top. The simplest fix by far is to just ignore
         // this case and deref again, so we wind up with
         // `FnMut::call_mut(&mut *x, ())`.
-        ty::ty_rptr(..) if autoderefs == 0 => {
+        ty::TyRef(..) if autoderefs == 0 => {
             return None;
         }
 
@@ -184,11 +183,11 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                        -> Option<ty::MethodCallee<'tcx>>
 {
     // Try the options that are least restrictive on the caller first.
-    for &(opt_trait_def_id, method_name) in [
+    for &(opt_trait_def_id, method_name) in &[
         (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
         (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
         (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
-    ].iter() {
+    ] {
         let trait_def_id = match opt_trait_def_id {
             Some(def_id) => def_id,
             None => continue,
@@ -222,7 +221,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     let error_fn_sig;
 
     let fn_sig = match callee_ty.sty {
-        ty::ty_bare_fn(_, &ty::BareFnTy {ref sig, ..}) => {
+        ty::TyBareFn(_, &ty::BareFnTy {ref sig, ..}) => {
             sig
         }
         _ => {
@@ -328,6 +327,7 @@ fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
 }
 
+#[derive(Debug)]
 struct CallResolution<'tcx> {
     call_expr: &'tcx ast::Expr,
     callee_expr: &'tcx ast::Expr,
@@ -337,23 +337,10 @@ struct CallResolution<'tcx> {
     closure_def_id: ast::DefId,
 }
 
-impl<'tcx> Repr<'tcx> for CallResolution<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("CallResolution(call_expr={}, callee_expr={}, adjusted_ty={}, \
-                autoderefs={}, fn_sig={}, closure_def_id={})",
-                self.call_expr.repr(tcx),
-                self.callee_expr.repr(tcx),
-                self.adjusted_ty.repr(tcx),
-                self.autoderefs,
-                self.fn_sig.repr(tcx),
-                self.closure_def_id.repr(tcx))
-    }
-}
-
 impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
     fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
-        debug!("DeferredCallResolution::resolve() {}",
-               self.repr(fcx.tcx()));
+        debug!("DeferredCallResolution::resolve() {:?}",
+               self);
 
         // we should not be invoked until the closure kind has been
         // determined by upvar inference
@@ -375,11 +362,11 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                     ty::no_late_bound_regions(fcx.tcx(),
                                               ty::ty_fn_sig(method_callee.ty)).unwrap();
 
-                debug!("attempt_resolution: method_callee={}",
-                       method_callee.repr(fcx.tcx()));
+                debug!("attempt_resolution: method_callee={:?}",
+                       method_callee);
 
                 for (&method_arg_ty, &self_arg_ty) in
-                    method_sig.inputs[1..].iter().zip(self.fn_sig.inputs.iter())
+                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
                 {
                     demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
                 }
index bc6159c0cff3003f9ca791a346ed76d7505f5de9..c46a033c13f95ca87429763f06fe1ebbbb734c95 100644 (file)
@@ -9,6 +9,34 @@
 // except according to those terms.
 
 //! Code for type-checking cast expressions.
+//!
+//! A cast `e as U` is valid if one of the following holds:
+//! * `e` has type `T` and `T` coerces to `U`; *coercion-cast*
+//! * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
+//!    unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast*
+//! * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
+//! * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
+//! * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
+//! * `e` is a C-like enum and `U` is an integer type; *enum-cast*
+//! * `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast*
+//! * `e` has type `u8` and `U` is `char`; *u8-char-cast*
+//! * `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
+//! * `e` is a function pointer type and `U` has type `*T`,
+//!   while `T: Sized`; *fptr-ptr-cast*
+//! * `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
+//!
+//! where `&.T` and `*T` are references of either mutability,
+//! and where unsize_kind(`T`) is the kind of the unsize info
+//! in `T` - the vtable for a trait definition (e.g. `fmt::Display` or
+//! `Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`).
+//!
+//! Note that lengths are not adjusted when casting raw slices -
+//! `T: *const [u16] as *const [u8]` creates a slice that only includes
+//! half of the original memory.
+//!
+//! Casting is not transitive, that is, even if `e as U1 as U2` is a valid
+//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
+//! `U1` coerces to `U2`).
 
 use super::coercion;
 use super::demand;
@@ -16,10 +44,11 @@ use super::FnCtxt;
 use super::structurally_resolved_type;
 
 use lint;
-use middle::infer;
+use middle::cast::{CastKind, CastTy};
 use middle::ty;
 use middle::ty::Ty;
 use syntax::ast;
+use syntax::ast::UintTy::{TyU8};
 use syntax::codemap::Span;
 
 /// Reifies a cast check to be checked once we have full type information for
@@ -31,6 +60,51 @@ pub struct CastCheck<'tcx> {
     span: Span,
 }
 
+/// The kind of the unsize info (length or vtable) - we only allow casts between
+/// fat pointers if their unsize-infos have the same kind.
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum UnsizeKind<'tcx> {
+    Vtable(ast::DefId),
+    Length,
+    /// The unsize info of this projection
+    OfProjection(&'tcx ty::ProjectionTy<'tcx>),
+    /// The unsize info of this parameter
+    OfParam(&'tcx ty::ParamTy)
+}
+
+/// Returns the kind of unsize information of t, or None
+/// if t is sized or it is unknown.
+fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                        t: Ty<'tcx>)
+                        -> Option<UnsizeKind<'tcx>> {
+    match t.sty {
+        ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
+        ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
+        ty::TyStruct(did, substs) => {
+            match ty::struct_fields(fcx.tcx(), did, substs).pop() {
+                None => None,
+                Some(f) => unsize_kind(fcx, f.mt.ty)
+            }
+        }
+        // We should really try to normalize here.
+        ty::TyProjection(ref pi) => Some(UnsizeKind::OfProjection(pi)),
+        ty::TyParam(ref p) => Some(UnsizeKind::OfParam(p)),
+        _ => None
+    }
+}
+
+#[derive(Copy, Clone)]
+enum CastError {
+    CastToBool,
+    CastToChar,
+    DifferingKinds,
+    IllegalCast,
+    NeedViaPtr,
+    NeedViaInt,
+    NeedViaUsize,
+    NonScalar,
+}
+
 impl<'tcx> CastCheck<'tcx> {
     pub fn new(expr: ast::Expr, expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, span: Span)
                -> CastCheck<'tcx> {
@@ -41,155 +115,265 @@ impl<'tcx> CastCheck<'tcx> {
             span: span,
         }
     }
-}
 
-pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
-    fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                          span: Span,
-                                          t_1: Ty<'tcx>,
-                                          t_e: Ty<'tcx>) {
-        fcx.type_error_message(span, |actual| {
-            format!("illegal cast; cast through an \
-                    integer first: `{}` as `{}`",
-                    actual,
-                    fcx.infcx().ty_to_string(t_1))
-        }, t_e, None);
+    fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>,
+                             e: CastError) {
+        match e {
+            CastError::NeedViaPtr |
+            CastError::NeedViaInt |
+            CastError::NeedViaUsize => {
+                fcx.type_error_message(self.span, |actual| {
+                    format!("illegal cast; cast through {} first: `{}` as `{}`",
+                            match e {
+                                CastError::NeedViaPtr => "a raw pointer",
+                                CastError::NeedViaInt => "an integer",
+                                CastError::NeedViaUsize => "a usize",
+                                _ => unreachable!()
+                            },
+                            actual,
+                            fcx.infcx().ty_to_string(self.cast_ty))
+                }, self.expr_ty, None)
+            }
+            CastError::CastToBool => {
+                span_err!(fcx.tcx().sess, self.span, E0054,
+                          "cannot cast as `bool`, compare with zero instead");
+            }
+            CastError::CastToChar => {
+                fcx.type_error_message(self.span, |actual| {
+                    format!("only `u8` can be cast as `char`, not `{}`", actual)
+                }, self.expr_ty, None);
+            }
+            CastError::NonScalar => {
+                fcx.type_error_message(self.span, |actual| {
+                    format!("non-scalar cast: `{}` as `{}`",
+                            actual,
+                            fcx.infcx().ty_to_string(self.cast_ty))
+                }, self.expr_ty, None);
+            }
+            CastError::IllegalCast => {
+                fcx.type_error_message(self.span, |actual| {
+                    format!("illegal cast: `{}` as `{}`",
+                            actual,
+                            fcx.infcx().ty_to_string(self.cast_ty))
+                }, self.expr_ty, None);
+            }
+            CastError::DifferingKinds => {
+                fcx.type_error_message(self.span, |actual| {
+                    format!("illegal cast: `{}` as `{}`; vtable kinds may not match",
+                            actual,
+                            fcx.infcx().ty_to_string(self.cast_ty))
+                }, self.expr_ty, None);
+            }
+        }
+    }
+
+    fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
+        let t_cast = self.cast_ty;
+        let t_expr = self.expr_ty;
+        if ty::type_is_numeric(t_cast) && ty::type_is_numeric(t_expr) {
+            fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
+                                    self.expr.id,
+                                    self.span,
+                                    format!("trivial numeric cast: `{}` as `{}`. Cast can be \
+                                             replaced by coercion, this might require type \
+                                             ascription or a temporary variable",
+                                            fcx.infcx().ty_to_string(t_expr),
+                                            fcx.infcx().ty_to_string(t_cast)));
+        } else {
+            fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
+                                    self.expr.id,
+                                    self.span,
+                                    format!("trivial cast: `{}` as `{}`. Cast can be \
+                                             replaced by coercion, this might require type \
+                                             ascription or a temporary variable",
+                                            fcx.infcx().ty_to_string(t_expr),
+                                            fcx.infcx().ty_to_string(t_cast)));
+        }
+
     }
 
-    let span = cast.span;
-    let e = &cast.expr;
-    let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
-    let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
-    let tcx = fcx.tcx();
-
-    // Check for trivial casts.
-    if !ty::type_has_ty_infer(t_1) {
-        if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
-            if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
-                tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
-                                  e.id,
-                                  span,
-                                  format!("trivial numeric cast: `{}` as `{}`. Cast can be \
-                                           replaced by coercion, this might require type \
-                                           ascription or a temporary variable",
-                                          fcx.infcx().ty_to_string(t_e),
-                                          fcx.infcx().ty_to_string(t_1)));
-            } else {
-                tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS,
-                                  e.id,
-                                  span,
-                                  format!("trivial cast: `{}` as `{}`. Cast can be \
-                                           replaced by coercion, this might require type \
-                                           ascription or a temporary variable",
-                                          fcx.infcx().ty_to_string(t_e),
-                                          fcx.infcx().ty_to_string(t_1)));
+    pub fn check<'a>(mut self, fcx: &FnCtxt<'a, 'tcx>) {
+        self.expr_ty = structurally_resolved_type(fcx, self.span, self.expr_ty);
+        self.cast_ty = structurally_resolved_type(fcx, self.span, self.cast_ty);
+
+        debug!("check_cast({}, {:?} as {:?})", self.expr.id, self.expr_ty,
+               self.cast_ty);
+
+        if ty::type_is_error(self.expr_ty) || ty::type_is_error(self.cast_ty) {
+            // No sense in giving duplicate error messages
+        } else if self.try_coercion_cast(fcx) {
+            self.trivial_cast_lint(fcx);
+            debug!(" -> CoercionCast");
+            fcx.tcx().cast_kinds.borrow_mut().insert(self.expr.id,
+                                                     CastKind::CoercionCast);
+        } else { match self.do_check(fcx) {
+            Ok(k) => {
+                debug!(" -> {:?}", k);
+                fcx.tcx().cast_kinds.borrow_mut().insert(self.expr.id, k);
             }
-            return;
+            Err(e) => self.report_cast_error(fcx, e)
+        };}
+    }
+
+    /// Check a cast, and report an error if one exists. In some cases, this
+    /// can return Ok and create type errors in the fcx rather than returning
+    /// directly. coercion-cast is handled in check instead of here.
+    fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
+        use middle::cast::IntTy::*;
+        use middle::cast::CastTy::*;
+
+        let (t_from, t_cast) = match (CastTy::from_ty(fcx.tcx(), self.expr_ty),
+                                      CastTy::from_ty(fcx.tcx(), self.cast_ty)) {
+            (Some(t_from), Some(t_cast)) => (t_from, t_cast),
+            _ => {
+                return Err(CastError::NonScalar)
+            }
+        };
+
+        match (t_from, t_cast) {
+            // These types have invariants! can't cast into them.
+            (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
+
+            // * -> Bool
+            (_, Int(Bool)) => Err(CastError::CastToBool),
+
+            // * -> Char
+            (Int(U(ast::TyU8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast
+            (_, Int(Char)) => Err(CastError::CastToChar),
+
+            // prim -> float,ptr
+            (Int(Bool), Float) | (Int(CEnum), Float) | (Int(Char), Float)
+                => Err(CastError::NeedViaInt),
+            (Int(Bool), Ptr(_)) | (Int(CEnum), Ptr(_)) | (Int(Char), Ptr(_))
+                => Err(CastError::NeedViaUsize),
+
+            // ptr -> *
+            (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
+            (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
+            (Ptr(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize),
+            (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
+            (RPtr(_), Int(_)) | (RPtr(_), Float) => Err(CastError::NeedViaPtr),
+            // * -> ptr
+            (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
+            (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
+            (Float, Ptr(_)) => Err(CastError::NeedViaUsize),
+            (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast
+
+            // prim -> prim
+            (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
+            (Int(Char), Int(_)) | (Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
+
+            (Int(_), Int(_)) |
+            (Int(_), Float) |
+            (Float, Int(_)) |
+            (Float, Float) => Ok(CastKind::NumericCast),
+
         }
     }
 
-    let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
-    let t_e_is_scalar = ty::type_is_scalar(t_e);
-    let t_e_is_integral = ty::type_is_integral(t_e);
-    let t_e_is_float = ty::type_is_floating_point(t_e);
-    let t_e_is_c_enum = ty::type_is_c_like_enum(tcx, t_e);
-
-    let t_1_is_scalar = ty::type_is_scalar(t_1);
-    let t_1_is_integral = ty::type_is_integral(t_1);
-    let t_1_is_char = ty::type_is_char(t_1);
-    let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
-    let t_1_is_float = ty::type_is_floating_point(t_1);
-    let t_1_is_c_enum = ty::type_is_c_like_enum(tcx, t_1);
-    let t1_is_fat_ptr = fcx.type_is_fat_ptr(t_1, span);
-
-    // casts to scalars other than `char` and `bare fn` are trivial
-    let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
-
-    if t_e_is_bare_fn_item && t_1_is_bare_fn {
-        demand::coerce(fcx, e.span, t_1, &e);
-    } else if t_1_is_char {
-        let t_e = fcx.infcx().shallow_resolve(t_e);
-        if t_e.sty != ty::ty_uint(ast::TyU8) {
-            fcx.type_error_message(span, |actual| {
-                format!("only `u8` can be cast as `char`, not `{}`", actual)
-            }, t_e, None);
+    fn check_ptr_ptr_cast<'a>(&self,
+                              fcx: &FnCtxt<'a, 'tcx>,
+                              m_expr: &'tcx ty::mt<'tcx>,
+                              m_cast: &'tcx ty::mt<'tcx>)
+                              -> Result<CastKind, CastError>
+    {
+        debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}",
+               m_expr, m_cast);
+        // ptr-ptr cast. vtables must match.
+
+        // Cast to sized is OK
+        if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
+            return Ok(CastKind::PtrPtrCast);
         }
-    } else if t_1.sty == ty::ty_bool {
-        span_err!(tcx.sess, span, E0054,
-                  "cannot cast as `bool`, compare with zero instead");
-    } else if t_e_is_float && (t_1_is_scalar || t_1_is_c_enum) &&
-        !(t_1_is_integral || t_1_is_float) {
-        // Casts from float must go through an integer
-        cast_through_integer_err(fcx, span, t_1, t_e)
-    } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) &&
-        !(t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
-        // Casts to float must go through an integer or boolean
-        cast_through_integer_err(fcx, span, t_1, t_e)
-    } else if t_e_is_c_enum && t_1_is_trivial {
-        if ty::type_is_unsafe_ptr(t_1) {
-            // ... and likewise with C enum -> *T
-            cast_through_integer_err(fcx, span, t_1, t_e)
+
+        // sized -> unsized? report illegal cast (don't complain about vtable kinds)
+        if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
+            return Err(CastError::IllegalCast);
         }
-        // casts from C-like enums are allowed
-    } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
-        fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
-                                      t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
-            match t1.sty {
-                ty::ty_vec(_, Some(_)) => {}
-                _ => return false
-            }
-            if ty::type_needs_infer(t2) {
-                // This prevents this special case from going off when casting
-                // to a type that isn't fully specified; e.g. `as *_`. (Issue
-                // #14893.)
-                return false
-            }
 
-            let el = ty::sequence_element_type(fcx.tcx(), t1);
-            infer::mk_eqty(fcx.infcx(),
-                           false,
-                           infer::Misc(sp),
-                           el,
-                           t2).is_ok()
+        // vtable kinds must match
+        match (unsize_kind(fcx, m_cast.ty), unsize_kind(fcx, m_expr.ty)) {
+            (Some(a), Some(b)) if a == b => Ok(CastKind::PtrPtrCast),
+            _ => Err(CastError::DifferingKinds)
         }
+    }
 
-        // Due to the limitations of LLVM global constants,
-        // region pointers end up pointing at copies of
-        // vector elements instead of the original values.
-        // To allow unsafe pointers to work correctly, we
-        // need to special-case obtaining an unsafe pointer
-        // from a region pointer to a vector.
-
-        /* this cast is only allowed from &[T, ..n] to *T or
-        &T to *T. */
-        match (&t_e.sty, &t_1.sty) {
-            (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
-             &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
-            if types_compatible(fcx, e.span, mt1, mt2) => {
-                /* this case is allowed */
-            }
-            _ => {
-                demand::coerce(fcx, e.span, t_1, &e);
+    fn check_fptr_ptr_cast<'a>(&self,
+                               fcx: &FnCtxt<'a, 'tcx>,
+                               m_cast: &'tcx ty::mt<'tcx>)
+                               -> Result<CastKind, CastError>
+    {
+        // fptr-ptr cast. must be to sized ptr
+
+        if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
+            Ok(CastKind::FnPtrPtrCast)
+        } else {
+            Err(CastError::IllegalCast)
+        }
+    }
+
+    fn check_ptr_addr_cast<'a>(&self,
+                               fcx: &FnCtxt<'a, 'tcx>,
+                               m_expr: &'tcx ty::mt<'tcx>)
+                               -> Result<CastKind, CastError>
+    {
+        // ptr-addr cast. must be from sized ptr
+
+        if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
+            Ok(CastKind::PtrAddrCast)
+        } else {
+            Err(CastError::NeedViaPtr)
+        }
+    }
+
+    fn check_ref_cast<'a>(&self,
+                          fcx: &FnCtxt<'a, 'tcx>,
+                          m_expr: &'tcx ty::mt<'tcx>,
+                          m_cast: &'tcx ty::mt<'tcx>)
+                          -> Result<CastKind, CastError>
+    {
+        // array-ptr-cast.
+
+        if m_expr.mutbl == ast::MutImmutable && m_cast.mutbl == ast::MutImmutable {
+            if let ty::TyArray(ety, _) = m_expr.ty.sty {
+                // Due to the limitations of LLVM global constants,
+                // region pointers end up pointing at copies of
+                // vector elements instead of the original values.
+                // To allow raw pointers to work correctly, we
+                // need to special-case obtaining a raw pointer
+                // from a region pointer to a vector.
+
+                // this will report a type mismatch if needed
+                demand::eqtype(fcx, self.span, ety, m_cast.ty);
+                return Ok(CastKind::ArrayPtrCast);
             }
         }
-    } else if t1_is_fat_ptr {
-        // FIXME This should be allowed where the lefthandside is also a fat
-        // pointer and is the same kind of fat pointer, i.e., array to array,
-        // trait object to trait object. That is a bit looser than the current
-        // rquirement that they are pointers to the same type.
-        if !(fcx.type_is_fat_ptr(t_e, span) &&
-             ty::deref(t_1, true).unwrap().ty == ty::deref(t_e, true).unwrap().ty) {
-            fcx.type_error_message(span, |actual| {
-                format!("cast to fat pointer: `{}` as `{}`",
-                        actual,
-                        fcx.infcx().ty_to_string(t_1))
-            }, t_e, None);
+
+        Err(CastError::IllegalCast)
+    }
+
+    fn check_addr_ptr_cast<'a>(&self,
+                               fcx: &FnCtxt<'a, 'tcx>,
+                               m_cast: &'tcx ty::mt<'tcx>)
+                               -> Result<CastKind, CastError>
+    {
+        // ptr-addr cast. pointer must be thin.
+        if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
+           Ok(CastKind::AddrPtrCast)
+        } else {
+           Err(CastError::IllegalCast)
         }
-    } else if !(t_e_is_scalar && t_1_is_trivial) {
-        fcx.type_error_message(span, |actual| {
-            format!("non-scalar cast: `{}` as `{}`",
-                    actual,
-                    fcx.infcx().ty_to_string(t_1))
-        }, t_e, None);
     }
+
+    fn try_coercion_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool {
+        if let Ok(()) = coercion::mk_assignty(fcx,
+                                              &self.expr,
+                                              self.expr_ty,
+                                              self.cast_ty) {
+            true
+        } else {
+            false
+        }
+    }
+
 }
index d2a06fcf9909138d1a1b354350c9dc1ea903b5ce..10b2459b220f2a8ffeb62d94c425d98a9b216553 100644 (file)
@@ -20,7 +20,6 @@ use std::cmp;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_util;
-use util::ppaux::Repr;
 
 pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                    expr: &ast::Expr,
@@ -28,9 +27,9 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                    decl: &'tcx ast::FnDecl,
                                    body: &'tcx ast::Block,
                                    expected: Expectation<'tcx>) {
-    debug!("check_expr_closure(expr={},expected={})",
-           expr.repr(fcx.tcx()),
-           expected.repr(fcx.tcx()));
+    debug!("check_expr_closure(expr={:?},expected={:?})",
+           expr,
+           expected);
 
     // It's always helpful for inference if we know the kind of
     // closure sooner rather than later, so first examine the expected
@@ -50,9 +49,9 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                           expected_sig: Option<ty::FnSig<'tcx>>) {
     let expr_def_id = ast_util::local_def(expr.id);
 
-    debug!("check_closure opt_kind={:?} expected_sig={}",
+    debug!("check_closure opt_kind={:?} expected_sig={:?}",
            opt_kind,
-           expected_sig.repr(fcx.tcx()));
+           expected_sig);
 
     let mut fn_ty = astconv::ty_of_closure(
         fcx,
@@ -86,9 +85,9 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     // the `closures` table.
     fn_ty.sig.0.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.0.inputs)];
 
-    debug!("closure for {} --> sig={} opt_kind={:?}",
-           expr_def_id.repr(fcx.tcx()),
-           fn_ty.sig.repr(fcx.tcx()),
+    debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
+           expr_def_id,
+           fn_ty.sig,
            opt_kind);
 
     fcx.inh.closure_tys.borrow_mut().insert(expr_def_id, fn_ty);
@@ -103,11 +102,11 @@ fn deduce_expectations_from_expected_type<'a,'tcx>(
     expected_ty: Ty<'tcx>)
     -> (Option<ty::FnSig<'tcx>>,Option<ty::ClosureKind>)
 {
-    debug!("deduce_expectations_from_expected_type(expected_ty={})",
-           expected_ty.repr(fcx.tcx()));
+    debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
+           expected_ty);
 
     match expected_ty.sty {
-        ty::ty_trait(ref object_type) => {
+        ty::TyTrait(ref object_type) => {
             let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
                                                                          fcx.tcx().types.err);
             let sig = proj_bounds.iter()
@@ -116,7 +115,7 @@ fn deduce_expectations_from_expected_type<'a,'tcx>(
             let kind = fcx.tcx().lang_items.fn_trait_kind(object_type.principal_def_id());
             (sig, kind)
         }
-        ty::ty_infer(ty::TyVar(vid)) => {
+        ty::TyInfer(ty::TyVar(vid)) => {
             deduce_expectations_from_obligations(fcx, vid)
         }
         _ => {
@@ -138,8 +137,8 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
         .pending_obligations()
         .iter()
         .filter_map(|obligation| {
-            debug!("deduce_expectations_from_obligations: obligation.predicate={}",
-                   obligation.predicate.repr(fcx.tcx()));
+            debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
+                   obligation.predicate);
 
             match obligation.predicate {
                 // Given a Projection predicate, we can potentially infer
@@ -200,8 +199,8 @@ fn deduce_sig_from_projection<'a,'tcx>(
 {
     let tcx = fcx.tcx();
 
-    debug!("deduce_sig_from_projection({})",
-           projection.repr(tcx));
+    debug!("deduce_sig_from_projection({:?})",
+           projection);
 
     let trait_ref = projection.to_poly_trait_ref();
 
@@ -211,24 +210,24 @@ fn deduce_sig_from_projection<'a,'tcx>(
 
     let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0);
     let arg_param_ty = fcx.infcx().resolve_type_vars_if_possible(&arg_param_ty);
-    debug!("deduce_sig_from_projection: arg_param_ty {}", arg_param_ty.repr(tcx));
+    debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty);
 
     let input_tys = match arg_param_ty.sty {
-        ty::ty_tup(ref tys) => { (*tys).clone() }
+        ty::TyTuple(ref tys) => { (*tys).clone() }
         _ => { return None; }
     };
-    debug!("deduce_sig_from_projection: input_tys {}", input_tys.repr(tcx));
+    debug!("deduce_sig_from_projection: input_tys {:?}", input_tys);
 
     let ret_param_ty = projection.0.ty;
     let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty);
-    debug!("deduce_sig_from_projection: ret_param_ty {}", ret_param_ty.repr(tcx));
+    debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
 
     let fn_sig = ty::FnSig {
         inputs: input_tys,
         output: ty::FnConverging(ret_param_ty),
         variadic: false
     };
-    debug!("deduce_sig_from_projection: fn_sig {}", fn_sig.repr(tcx));
+    debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
 
     Some(fn_sig)
 }
@@ -240,11 +239,11 @@ fn self_type_matches_expected_vid<'a,'tcx>(
     -> Option<ty::PolyTraitRef<'tcx>>
 {
     let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
-    debug!("self_type_matches_expected_vid(trait_ref={}, self_ty={})",
-           trait_ref.repr(fcx.tcx()),
-           self_ty.repr(fcx.tcx()));
+    debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
+           trait_ref,
+           self_ty);
     match self_ty.sty {
-        ty::ty_infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
+        ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
         _ => None,
     }
 }
index dd63a512ae39305f20e4fc8f362fb44a74bfa8d2..785202de92159e03302f641caebf0f9f4790518b 100644 (file)
@@ -60,7 +60,7 @@
 //! sort of a minor point so I've opted to leave it for later---after all
 //! we may want to adjust precisely when coercions occur.
 
-use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction};
+use check::{autoderef, FnCtxt, LvaluePreference, UnresolvedTypeAction};
 
 use middle::infer::{self, Coercion};
 use middle::traits::{self, ObligationCause};
@@ -69,7 +69,6 @@ use middle::ty::{AutoDerefRef, AdjustDerefRef};
 use middle::ty::{self, mt, Ty};
 use middle::ty_relate::RelateResult;
 use util::common::indent;
-use util::ppaux::Repr;
 
 use std::cell::RefCell;
 use std::collections::VecDeque;
@@ -104,9 +103,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
               a: Ty<'tcx>,
               b: Ty<'tcx>)
               -> CoerceResult<'tcx> {
-        debug!("Coerce.tys({} => {})",
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
+        debug!("Coerce.tys({:?} => {:?})",
+               a,
+               b);
 
         // Consider coercing the subtype to a DST
         let unsize = self.unpack_actual_value(a, |a| {
@@ -121,13 +120,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // Note: does not attempt to resolve type variables we encounter.
         // See above for details.
         match b.sty {
-            ty::ty_ptr(mt_b) => {
+            ty::TyRawPtr(mt_b) => {
                 return self.unpack_actual_value(a, |a| {
                     self.coerce_unsafe_ptr(a, b, mt_b.mutbl)
                 });
             }
 
-            ty::ty_rptr(_, mt_b) => {
+            ty::TyRef(_, mt_b) => {
                 return self.unpack_actual_value(a, |a| {
                     self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl)
                 });
@@ -138,13 +137,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         self.unpack_actual_value(a, |a| {
             match a.sty {
-                ty::ty_bare_fn(Some(_), a_f) => {
+                ty::TyBareFn(Some(_), a_f) => {
                     // Function items are coercible to any closure
                     // type; function pointers are not (that would
                     // require double indirection).
                     self.coerce_from_fn_item(a, a_f, b)
                 }
-                ty::ty_bare_fn(None, a_f) => {
+                ty::TyBareFn(None, a_f) => {
                     // We permit coercion of fn pointers to drop the
                     // unsafe qualifier.
                     self.coerce_from_fn_pointer(a, a_f, b)
@@ -166,9 +165,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                                b: Ty<'tcx>,
                                mutbl_b: ast::Mutability)
                                -> CoerceResult<'tcx> {
-        debug!("coerce_borrowed_pointer(a={}, b={})",
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
+        debug!("coerce_borrowed_pointer(a={:?}, b={:?})",
+               a,
+               b);
 
         // If we have a parameter of type `&M T_a` and the value
         // provided is `expr`, we will be adding an implicit borrow,
@@ -177,7 +176,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // yield.
 
         match a.sty {
-            ty::ty_rptr(_, mt_a) => {
+            ty::TyRef(_, mt_a) => {
                 try!(coerce_mutbls(mt_a.mutbl, mutbl_b));
             }
             _ => return self.subtype(a, b)
@@ -188,10 +187,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         let r_borrow = self.tcx().mk_region(r_borrow);
         let autoref = Some(ty::AutoPtr(r_borrow, mutbl_b));
 
-        let lvalue_pref = match mutbl_b {
-            ast::MutMutable => PreferMutLvalue,
-            ast::MutImmutable => NoPreference
-        };
+        let lvalue_pref = LvaluePreference::from_mutbl(mutbl_b);
         let mut first_error = None;
         let (_, autoderefs, success) = autoderef(self.fcx,
                                                  expr_a.span,
@@ -234,16 +230,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     }
 
 
-    // &[T, ..n] or &mut [T, ..n] -> &[T]
-    // or &mut [T, ..n] -> &mut [T]
+    // &[T; n] or &mut [T; n] -> &[T]
+    // or &mut [Tn] -> &mut [T]
     // or &Concrete -> &Trait, etc.
     fn coerce_unsized(&self,
                       source: Ty<'tcx>,
                       target: Ty<'tcx>)
                       -> CoerceResult<'tcx> {
-        debug!("coerce_unsized(source={}, target={})",
-               source.repr(self.tcx()),
-               target.repr(self.tcx()));
+        debug!("coerce_unsized(source={:?}, target={:?})",
+               source,
+               target);
 
         let traits = (self.tcx().lang_items.unsize_trait(),
                       self.tcx().lang_items.coerce_unsized_trait());
@@ -261,7 +257,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
         let (source, reborrow) = match (&source.sty, &target.sty) {
-            (&ty::ty_rptr(_, mt_a), &ty::ty_rptr(_, mt_b)) => {
+            (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
                 try!(coerce_mutbls(mt_a.mutbl, mt_b.mutbl));
 
                 let coercion = Coercion(self.origin.span());
@@ -269,7 +265,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 let region = self.tcx().mk_region(r_borrow);
                 (mt_a.ty, Some(ty::AutoPtr(region, mt_b.mutbl)))
             }
-            (&ty::ty_rptr(_, mt_a), &ty::ty_ptr(mt_b)) => {
+            (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
                 try!(coerce_mutbls(mt_a.mutbl, mt_b.mutbl));
                 (mt_a.ty, Some(ty::AutoUnsafe(mt_b.mutbl)))
             }
@@ -297,7 +293,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // inference might unify those two inner type variables later.
         let traits = [coerce_unsized_did, unsize_did];
         while let Some(obligation) = queue.pop_front() {
-            debug!("coerce_unsized resolve step: {}", obligation.repr(self.tcx()));
+            debug!("coerce_unsized resolve step: {:?}", obligation);
             let trait_ref =  match obligation.predicate {
                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                     tr.clone()
@@ -323,7 +319,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 }
 
                 Ok(Some(vtable)) => {
-                    vtable.map_move_nested(|o| queue.push_back(o));
+                    for obligation in vtable.nested_obligations() {
+                        queue.push_back(obligation);
+                    }
                 }
             }
         }
@@ -337,7 +335,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             autoref: reborrow,
             unsize: Some(target)
         };
-        debug!("Success, coerced with {}", adjustment.repr(self.tcx()));
+        debug!("Success, coerced with {:?}", adjustment);
         Ok(Some(AdjustDerefRef(adjustment)))
     }
 
@@ -353,10 +351,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
          */
 
         self.unpack_actual_value(b, |b| {
-            debug!("coerce_from_fn_pointer(a={}, b={})",
-                   a.repr(self.tcx()), b.repr(self.tcx()));
+            debug!("coerce_from_fn_pointer(a={:?}, b={:?})",
+                   a, b);
 
-            if let ty::ty_bare_fn(None, fn_ty_b) = b.sty {
+            if let ty::TyBareFn(None, fn_ty_b) = b.sty {
                 match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
                     (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
                         let unsafe_a = self.tcx().safe_to_unsafe_fn_ty(fn_ty_a);
@@ -381,11 +379,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
          */
 
         self.unpack_actual_value(b, |b| {
-            debug!("coerce_from_fn_item(a={}, b={})",
-                   a.repr(self.tcx()), b.repr(self.tcx()));
+            debug!("coerce_from_fn_item(a={:?}, b={:?})",
+                   a, b);
 
             match b.sty {
-                ty::ty_bare_fn(None, _) => {
+                ty::TyBareFn(None, _) => {
                     let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, fn_ty_a);
                     try!(self.subtype(a_fn_pointer, b));
                     Ok(Some(ty::AdjustReifyFnPointer))
@@ -400,12 +398,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                          b: Ty<'tcx>,
                          mutbl_b: ast::Mutability)
                          -> CoerceResult<'tcx> {
-        debug!("coerce_unsafe_ptr(a={}, b={})",
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
+        debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
+               a,
+               b);
 
-        let mt_a = match a.sty {
-            ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt,
+        let (is_ref, mt_a) = match a.sty {
+            ty::TyRef(_, mt) => (true, mt),
+            ty::TyRawPtr(mt) => (false, mt),
             _ => {
                 return self.subtype(a, b);
             }
@@ -419,11 +418,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // Although references and unsafe ptrs have the same
         // representation, we still register an AutoDerefRef so that
         // regionck knows that the region for `a` must be valid here.
-        Ok(Some(AdjustDerefRef(AutoDerefRef {
-            autoderefs: 1,
-            autoref: Some(ty::AutoUnsafe(mutbl_b)),
-            unsize: None
-        })))
+        if is_ref {
+            Ok(Some(AdjustDerefRef(AutoDerefRef {
+                autoderefs: 1,
+                autoref: Some(ty::AutoUnsafe(mutbl_b)),
+                unsize: None
+            })))
+        } else {
+            Ok(None)
+        }
     }
 }
 
@@ -432,7 +435,7 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              a: Ty<'tcx>,
                              b: Ty<'tcx>)
                              -> RelateResult<'tcx, ()> {
-    debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
+    debug!("mk_assignty({:?} -> {:?})", a, b);
     let mut unsizing_obligations = vec![];
     let adjustment = try!(indent(|| {
         fcx.infcx().commit_if_ok(|_| {
@@ -456,7 +459,7 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     if let Some(adjustment) = adjustment {
-        debug!("Success, coerced with {}", adjustment.repr(fcx.tcx()));
+        debug!("Success, coerced with {:?}", adjustment);
         fcx.write_adjustment(expr.id, adjustment);
     }
     Ok(())
index b3267a5be495b4df92f5157913b5ff93bee04b76..7cd5e4548ec2b74b4c6c54227274dcd093cf50f9 100644 (file)
@@ -13,7 +13,6 @@ use middle::infer;
 use middle::traits;
 use middle::ty::{self};
 use middle::subst::{self, Subst, Substs, VecPerParamSpace};
-use util::ppaux::{self, Repr};
 
 use syntax::ast;
 use syntax::codemap::Span;
@@ -38,14 +37,14 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  impl_m_body_id: ast::NodeId,
                                  trait_m: &ty::Method<'tcx>,
                                  impl_trait_ref: &ty::TraitRef<'tcx>) {
-    debug!("compare_impl_method(impl_trait_ref={})",
-           impl_trait_ref.repr(tcx));
+    debug!("compare_impl_method(impl_trait_ref={:?})",
+           impl_trait_ref);
 
-    debug!("compare_impl_method: impl_trait_ref (liberated) = {}",
-           impl_trait_ref.repr(tcx));
+    debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
+           impl_trait_ref);
 
     let infcx = infer::new_infer_ctxt(tcx);
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
+    let mut fulfillment_cx = traits::FulfillmentContext::new(true);
 
     let trait_to_impl_substs = &impl_trait_ref.substs;
 
@@ -63,18 +62,16 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             span_err!(tcx.sess, impl_m_span, E0185,
                 "method `{}` has a `{}` declaration in the impl, \
                         but not in the trait",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &impl_m.explicit_self));
+                        trait_m.name,
+                        impl_m.explicit_self);
             return;
         }
         (_, &ty::StaticExplicitSelfCategory) => {
             span_err!(tcx.sess, impl_m_span, E0186,
                 "method `{}` has a `{}` declaration in the trait, \
                         but not in the impl",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &trait_m.explicit_self));
+                        trait_m.name,
+                        trait_m.explicit_self);
             return;
         }
         _ => {
@@ -185,8 +182,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         .subst(tcx, impl_to_skol_substs)
         .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
                      impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
-    debug!("compare_impl_method: trait_to_skol_substs={}",
-           trait_to_skol_substs.repr(tcx));
+    debug!("compare_impl_method: trait_to_skol_substs={:?}",
+           trait_to_skol_substs);
 
     // Check region bounds. FIXME(@jroesch) refactor this away when removing
     // ParamBounds.
@@ -213,8 +210,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             impl_m_span,
             infer::HigherRankedType,
             &ty::Binder(impl_bounds));
-    debug!("compare_impl_method: impl_bounds={}",
-           impl_bounds.repr(tcx));
+    debug!("compare_impl_method: impl_bounds={:?}",
+           impl_bounds);
 
     // Normalize the associated types in the trait_bounds.
     let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs);
@@ -244,8 +241,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     let trait_param_env = traits::normalize_param_env_or_error(trait_param_env,
                                                                normalize_cause.clone());
 
-    debug!("compare_impl_method: trait_bounds={}",
-        trait_param_env.caller_bounds.repr(tcx));
+    debug!("compare_impl_method: trait_bounds={:?}",
+        trait_param_env.caller_bounds);
 
     let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env);
 
@@ -305,8 +302,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                            tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
                                                          abi: impl_m.fty.abi,
                                                          sig: ty::Binder(impl_sig) }));
-        debug!("compare_impl_method: impl_fty={}",
-               impl_fty.repr(tcx));
+        debug!("compare_impl_method: impl_fty={:?}",
+               impl_fty);
 
         let (trait_sig, skol_map) =
             infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
@@ -326,8 +323,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                          abi: trait_m.fty.abi,
                                                          sig: ty::Binder(trait_sig) }));
 
-        debug!("compare_impl_method: trait_fty={}",
-               trait_fty.repr(tcx));
+        debug!("compare_impl_method: trait_fty={:?}",
+               trait_fty);
 
         try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
 
@@ -337,13 +334,13 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     match err {
         Ok(()) => { }
         Err(terr) => {
-            debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
-                   impl_fty.repr(tcx),
-                   trait_fty.repr(tcx));
+            debug!("checking trait method for compatibility: impl ty {:?}, trait ty {:?}",
+                   impl_fty,
+                   trait_fty);
             span_err!(tcx.sess, impl_m_span, E0053,
                       "method `{}` has an incompatible type for trait: {}",
                       token::get_name(trait_m.name),
-                      ty::type_err_to_str(tcx, &terr));
+                      terr);
             return;
         }
     }
@@ -383,14 +380,14 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
 
         debug!("check_region_bounds_on_impl_method: \
-               trait_generics={} \
-               impl_generics={} \
-               trait_to_skol_substs={} \
-               impl_to_skol_substs={}",
-               trait_generics.repr(tcx),
-               impl_generics.repr(tcx),
-               trait_to_skol_substs.repr(tcx),
-               impl_to_skol_substs.repr(tcx));
+               trait_generics={:?} \
+               impl_generics={:?} \
+               trait_to_skol_substs={:?} \
+               impl_to_skol_substs={:?}",
+               trait_generics,
+               impl_generics,
+               trait_to_skol_substs,
+               impl_to_skol_substs);
 
         // Must have same number of early-bound lifetime parameters.
         // Unfortunately, if the user screws up the bounds, then this
@@ -418,11 +415,11 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 impl_c_span: Span,
                                 trait_c: &ty::AssociatedConst<'tcx>,
                                 impl_trait_ref: &ty::TraitRef<'tcx>) {
-    debug!("compare_const_impl(impl_trait_ref={})",
-           impl_trait_ref.repr(tcx));
+    debug!("compare_const_impl(impl_trait_ref={:?})",
+           impl_trait_ref);
 
     let infcx = infer::new_infer_ctxt(tcx);
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
+    let mut fulfillment_cx = traits::FulfillmentContext::new(true);
 
     // The below is for the most part highly similar to the procedure
     // for methods above. It is simpler in many respects, especially
@@ -445,8 +442,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
         .subst(tcx, impl_to_skol_substs)
         .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
                      impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
-    debug!("compare_const_impl: trait_to_skol_substs={}",
-           trait_to_skol_substs.repr(tcx));
+    debug!("compare_const_impl: trait_to_skol_substs={:?}",
+           trait_to_skol_substs);
 
     // Compute skolemized form of impl and trait const tys.
     let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
@@ -463,8 +460,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                  impl_c_span,
                                                  0,
                                                  &impl_ty);
-        debug!("compare_const_impl: impl_ty={}",
-               impl_ty.repr(tcx));
+        debug!("compare_const_impl: impl_ty={:?}",
+               impl_ty);
 
         let trait_ty =
             assoc::normalize_associated_types_in(&infcx,
@@ -473,8 +470,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                  impl_c_span,
                                                  0,
                                                  &trait_ty);
-        debug!("compare_const_impl: trait_ty={}",
-               trait_ty.repr(tcx));
+        debug!("compare_const_impl: trait_ty={:?}",
+               trait_ty);
 
         infer::mk_subty(&infcx, false, origin, impl_ty, trait_ty)
     });
@@ -482,14 +479,14 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
     match err {
         Ok(()) => { }
         Err(terr) => {
-            debug!("checking associated const for compatibility: impl ty {}, trait ty {}",
-                   impl_ty.repr(tcx),
-                   trait_ty.repr(tcx));
+            debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
+                   impl_ty,
+                   trait_ty);
             span_err!(tcx.sess, impl_c_span, E0326,
                       "implemented const `{}` has an incompatible type for \
                       trait: {}",
                       token::get_name(trait_c.name),
-                      ty::type_err_to_str(tcx, &terr));
+                      terr);
             return;
         }
     }
index cd6a1226e00c9d639d8c83d38891caaf13122e85..392515926da0c9b71735ffd7423f62b9e92e8877 100644 (file)
@@ -16,7 +16,6 @@ use middle::infer;
 use std::result::Result::{Err, Ok};
 use syntax::ast;
 use syntax::codemap::Span;
-use util::ppaux::Repr;
 
 // Requires that the two types unify, and prints an error message if
 // they don't.
@@ -59,9 +58,9 @@ pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         expected: Ty<'tcx>,
                         expr: &ast::Expr) {
     let expr_ty = fcx.expr_ty(expr);
-    debug!("demand::coerce(expected = {}, expr_ty = {})",
-           expected.repr(fcx.ccx.tcx),
-           expr_ty.repr(fcx.ccx.tcx));
+    debug!("demand::coerce(expected = {:?}, expr_ty = {:?})",
+           expected,
+           expr_ty);
     let expr_ty = fcx.resolve_type_vars_if_possible(expr_ty);
     let expected = fcx.resolve_type_vars_if_possible(expected);
     match coercion::mk_assignty(fcx, expr, expr_ty, expected) {
index fd90d662bd141d5eb4e9343adc455e8757f39b9a..fb17f41d88d9a354c4f0bc9898062a61259803b5 100644 (file)
@@ -14,7 +14,6 @@ use middle::infer;
 use middle::region;
 use middle::subst::{self, Subst};
 use middle::ty::{self, Ty};
-use util::ppaux::{Repr, UserString};
 
 use syntax::ast;
 use syntax::codemap::{self, Span};
@@ -38,16 +37,16 @@ use syntax::codemap::{self, Span};
 ///
 pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), ()> {
     let ty::TypeScheme { generics: ref dtor_generics,
-                         ty: ref dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did);
+                         ty: dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did);
     let dtor_predicates = ty::lookup_predicates(tcx, drop_impl_did);
     match dtor_self_type.sty {
-        ty::ty_enum(self_type_did, self_to_impl_substs) |
-        ty::ty_struct(self_type_did, self_to_impl_substs) |
-        ty::ty_closure(self_type_did, self_to_impl_substs) => {
+        ty::TyEnum(self_type_did, self_to_impl_substs) |
+        ty::TyStruct(self_type_did, self_to_impl_substs) |
+        ty::TyClosure(self_type_did, self_to_impl_substs) => {
             try!(ensure_drop_params_and_item_params_correspond(tcx,
                                                                drop_impl_did,
                                                                dtor_generics,
-                                                               dtor_self_type,
+                                                               &dtor_self_type,
                                                                self_type_did));
 
             ensure_drop_predicates_are_implied_by_item_defn(tcx,
@@ -62,7 +61,7 @@ pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(),
             let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
             tcx.sess.span_bug(
                 span, &format!("should have been rejected by coherence check: {}",
-                               dtor_self_type.repr(tcx)));
+                               dtor_self_type));
         }
     }
 }
@@ -212,9 +211,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 
         if !assumptions_in_impl_context.contains(&predicate) {
             let item_span = tcx.map.span(self_type_did.node);
-            let req = predicate.user_string(tcx);
             span_err!(tcx.sess, drop_impl_span, E0367,
-                      "The requirement `{}` is added only by the Drop impl.", req);
+                      "The requirement `{}` is added only by the Drop impl.", predicate);
             tcx.sess.span_note(item_span,
                                "The same requirement must be part of \
                                 the struct/enum definition");
@@ -238,14 +236,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 /// 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,
+/// * (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
+///   * (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,
 ///
@@ -259,8 +255,8 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
                                                      typ: ty::Ty<'tcx>,
                                                      span: Span,
                                                      scope: region::CodeExtent) {
-    debug!("check_safety_of_destructor_if_necessary typ: {} scope: {:?}",
-           typ.repr(rcx.tcx()), scope);
+    debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
+           typ, scope);
 
     // types that have been traversed so far by `traverse_type_if_unseen`
     let mut breadcrumbs: Vec<Ty<'tcx>> = Vec::new();
@@ -279,8 +275,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
         Err(Error::Overflow(ref ctxt, ref detected_on_typ)) => {
             let tcx = rcx.tcx();
             span_err!(tcx.sess, span, E0320,
-                      "overflow while adding drop-check rules for {}",
-                      typ.user_string(rcx.tcx()));
+                      "overflow while adding drop-check rules for {}", typ);
             match *ctxt {
                 TypeContext::Root => {
                     // no need for an additional note if the overflow
@@ -296,7 +291,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
                         ty::item_path_str(tcx, def_id),
                         variant,
                         arg_index,
-                        detected_on_typ.user_string(rcx.tcx()));
+                        detected_on_typ);
                 }
                 TypeContext::Struct { def_id, field } => {
                     span_note!(
@@ -305,7 +300,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
                         "overflowed on struct {} field {} type: {}",
                         ty::item_path_str(tcx, def_id),
                         field,
-                        detected_on_typ.user_string(rcx.tcx()));
+                        detected_on_typ);
                 }
             }
         }
@@ -368,26 +363,26 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
         // with `T`, the type it represents as owned by the
         // surrounding context, before doing further analysis.
         let (typ, xref_depth) = match typ.sty {
-            ty::ty_struct(struct_did, substs) => {
+            ty::TyStruct(struct_did, substs) => {
                 if opt_phantom_data_def_id == Some(struct_did) {
                     let item_type = ty::lookup_item_type(rcx.tcx(), struct_did);
                     let tp_def = item_type.generics.types
                         .opt_get(subst::TypeSpace, 0).unwrap();
                     let new_typ = substs.type_for_def(tp_def);
-                    debug!("replacing phantom {} with {}",
-                           typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx()));
+                    debug!("replacing phantom {:?} with {:?}",
+                           typ, new_typ);
                     (new_typ, xref_depth_orig + 1)
                 } else {
                     (typ, xref_depth_orig)
                 }
             }
 
-            // Note: When ty_uniq is removed from compiler, the
+            // Note: When TyBox is removed from compiler, the
             // definition of `Box<T>` must carry a PhantomData that
             // puts us into the previous case.
-            ty::ty_uniq(new_typ) => {
-                debug!("replacing ty_uniq {} with {}",
-                       typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx()));
+            ty::TyBox(new_typ) => {
+                debug!("replacing TyBox {:?} with {:?}",
+                       typ, new_typ);
                 (new_typ, xref_depth_orig + 1)
             }
 
@@ -397,14 +392,14 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
         };
 
         let dtor_kind = match typ.sty {
-            ty::ty_enum(def_id, _) |
-            ty::ty_struct(def_id, _) => {
+            ty::TyEnum(def_id, _) |
+            ty::TyStruct(def_id, _) => {
                 match destructor_for_type.get(&def_id) {
                     Some(def_id) => DtorKind::KnownDropMethod(*def_id),
                     None => DtorKind::PureRecur,
                 }
             }
-            ty::ty_trait(ref ty_trait) => {
+            ty::TyTrait(ref ty_trait) => {
                 DtorKind::Unknown(ty_trait.bounds.clone())
             }
             _ => DtorKind::PureRecur,
@@ -413,7 +408,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
         debug!("iterate_over_potentially_unsafe_regions_in_type \
                 {}typ: {} scope: {:?} xref: {}",
                (0..depth).map(|_| ' ').collect::<String>(),
-               typ.repr(rcx.tcx()), scope, xref_depth);
+               typ, scope, xref_depth);
 
         // If `typ` has a destructor, then we must ensure that all
         // borrowed data reachable via `typ` must outlive the parent
@@ -468,16 +463,16 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
             // destructor.
 
             match typ.sty {
-                ty::ty_struct(struct_did, substs) => {
-                    debug!("typ: {} is struct; traverse structure and not type-expression",
-                           typ.repr(rcx.tcx()));
+                ty::TyStruct(struct_did, substs) => {
+                    debug!("typ: {:?} is struct; traverse structure and not type-expression",
+                           typ);
                     // Don't recurse; we extract type's substructure,
                     // so do not process subparts of type expression.
                     walker.skip_current_subtree();
 
                     let fields =
                         ty::lookup_struct_fields(rcx.tcx(), struct_did);
-                    for field in fields.iter() {
+                    for field in &fields {
                         let field_type =
                             ty::lookup_field_type(rcx.tcx(),
                                                   struct_did,
@@ -498,9 +493,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                     }
                 }
 
-                ty::ty_enum(enum_did, substs) => {
-                    debug!("typ: {} is enum; traverse structure and not type-expression",
-                           typ.repr(rcx.tcx()));
+                ty::TyEnum(enum_did, substs) => {
+                    debug!("typ: {:?} is enum; traverse structure and not type-expression",
+                           typ);
                     // Don't recurse; we extract type's substructure,
                     // so do not process subparts of type expression.
                     walker.skip_current_subtree();
@@ -509,7 +504,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                         ty::substd_enum_variants(rcx.tcx(),
                                                  enum_did,
                                                  substs);
-                    for variant_info in all_variant_info.iter() {
+                    for variant_info in &all_variant_info {
                         for (i, arg_type) in variant_info.args.iter().enumerate() {
                             try!(iterate_over_potentially_unsafe_regions_in_type(
                                 rcx,
@@ -528,7 +523,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                     }
                 }
 
-                ty::ty_rptr(..) | ty::ty_ptr(_) | ty::ty_bare_fn(..) => {
+                ty::TyRef(..) | ty::TyRawPtr(_) | ty::TyBareFn(..) => {
                     // Don't recurse, since references, pointers,
                     // and bare functions don't own instances
                     // of the types appearing within them.
@@ -573,24 +568,24 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
     match dtor_kind {
         DtorKind::PureRecur => {
             has_dtor_of_interest = false;
-            debug!("typ: {} has no dtor, and thus is uninteresting",
-                   typ.repr(tcx));
+            debug!("typ: {:?} has no dtor, and thus is uninteresting",
+                   typ);
         }
         DtorKind::Unknown(bounds) => {
             match bounds.region_bound {
                 ty::ReStatic => {
-                    debug!("trait: {} has 'static bound, and thus is uninteresting",
-                           typ.repr(tcx));
+                    debug!("trait: {:?} has 'static bound, and thus is uninteresting",
+                           typ);
                     has_dtor_of_interest = false;
                 }
                 ty::ReEmpty => {
-                    debug!("trait: {} has empty region bound, and thus is uninteresting",
-                           typ.repr(tcx));
+                    debug!("trait: {:?} has empty region bound, and thus is uninteresting",
+                           typ);
                     has_dtor_of_interest = false;
                 }
                 r => {
-                    debug!("trait: {} has non-static bound: {}; assumed interesting",
-                           typ.repr(tcx), r.repr(tcx));
+                    debug!("trait: {:?} has non-static bound: {:?}; assumed interesting",
+                           typ, r);
                     has_dtor_of_interest = true;
                 }
             }
@@ -647,8 +642,8 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
 
                     if result {
                         has_pred_of_interest = true;
-                        debug!("typ: {} has interesting dtor due to generic preds, e.g. {}",
-                               typ.repr(tcx), pred.repr(tcx));
+                        debug!("typ: {:?} has interesting dtor due to generic preds, e.g. {:?}",
+                               typ, pred);
                         break 'items;
                     }
                 }
@@ -672,14 +667,14 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
                 has_pred_of_interest;
 
             if has_dtor_of_interest {
-                debug!("typ: {} has interesting dtor, due to \
+                debug!("typ: {:?} has interesting dtor, due to \
                         region params: {} or pred: {}",
-                       typ.repr(tcx),
+                       typ,
                        has_region_param_of_interest,
                        has_pred_of_interest);
             } else {
-                debug!("typ: {} has dtor, but it is uninteresting",
-                       typ.repr(tcx));
+                debug!("typ: {:?} has dtor, but it is uninteresting",
+                       typ);
             }
         }
     }
index 367273dc635f47b003fed53abf9a7f001f5bb595..b5d317d602538f2cf83cfed10e18680e35c417c1 100644 (file)
@@ -18,7 +18,7 @@ into a more explicit UFCS form:
 Here `ADJ` is some kind of adjustment, which is typically a series of
 autoderefs and then possibly an autoref (e.g., `&**receiver`). However
 we sometimes do other adjustments and coercions along the way, in
-particular unsizing (e.g., converting from `[T, ..n]` to `[T]`).
+particular unsizing (e.g., converting from `[Tn]` to `[T]`).
 
 ## The Two Phases
 
index c068bfaa82eb74b23ab3f4c9027d625c0c8dbadf..fd93a2493db5aac32ba00ba579696fabd73946e3 100644 (file)
@@ -24,7 +24,6 @@ use middle::infer::InferCtxt;
 use syntax::ast;
 use syntax::codemap::Span;
 use std::iter::repeat;
-use util::ppaux::Repr;
 
 struct ConfirmContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -56,10 +55,10 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                          supplied_method_types: Vec<Ty<'tcx>>)
                          -> MethodCallee<'tcx>
 {
-    debug!("confirm(unadjusted_self_ty={}, pick={}, supplied_method_types={})",
-           unadjusted_self_ty.repr(fcx.tcx()),
-           pick.repr(fcx.tcx()),
-           supplied_method_types.repr(fcx.tcx()));
+    debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
+           unadjusted_self_ty,
+           pick,
+           supplied_method_types);
 
     let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr);
     confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
@@ -93,7 +92,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         let (method_types, method_regions) =
             self.instantiate_method_substs(&pick, supplied_method_types);
         let all_substs = rcvr_substs.with_method(method_types, method_regions);
-        debug!("all_substs={}", all_substs.repr(self.tcx()));
+        debug!("all_substs={:?}", all_substs);
 
         // Create the final signature for the method, replacing late-bound regions.
         let InstantiatedMethodSig {
@@ -225,10 +224,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                         this.upcast(original_poly_trait_ref.clone(), trait_def_id);
                     let upcast_trait_ref =
                         this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
-                    debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
-                           original_poly_trait_ref.repr(this.tcx()),
-                           upcast_trait_ref.repr(this.tcx()),
-                           trait_def_id.repr(this.tcx()));
+                    debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
+                           original_poly_trait_ref,
+                           upcast_trait_ref,
+                           trait_def_id);
                     let substs = upcast_trait_ref.substs.clone();
                     let origin = MethodTraitObject(MethodObject {
                         trait_ref: upcast_trait_ref,
@@ -296,7 +295,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     }
 
     fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
-        F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R,
+        F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
     {
         // If we specified that this is an object method, then the
         // self-type ought to be something that can be dereferenced to
@@ -311,7 +310,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                                               NoPreference,
                                               |ty, _| {
             match ty.sty {
-                ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
+                ty::TyTrait(ref data) => Some(closure(self, ty, &**data)),
                 _ => None,
             }
         });
@@ -322,7 +321,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 self.tcx().sess.span_bug(
                     self.span,
                     &format!("self-type `{}` for ObjectPick never dereferenced to an object",
-                            self_ty.repr(self.tcx())))
+                            self_ty))
             }
         }
     }
@@ -376,10 +375,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             Err(_) => {
                 self.tcx().sess.span_bug(
                     self.span,
-                    &format!(
-                        "{} was a subtype of {} but now is not?",
-                        self_ty.repr(self.tcx()),
-                        method_self_ty.repr(self.tcx())));
+                    &format!("{} was a subtype of {} but now is not?",
+                             self_ty, method_self_ty));
             }
         }
     }
@@ -392,9 +389,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                               all_substs: subst::Substs<'tcx>)
                               -> InstantiatedMethodSig<'tcx>
     {
-        debug!("instantiate_method_sig(pick={}, all_substs={})",
-               pick.repr(self.tcx()),
-               all_substs.repr(self.tcx()));
+        debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
+               pick,
+               all_substs);
 
         // Instantiate the bounds on the method with the
         // type/early-bound-regions substitutions performed. There can
@@ -404,8 +401,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         let method_predicates = self.fcx.normalize_associated_types_in(self.span,
                                                                        &method_predicates);
 
-        debug!("method_predicates after subst = {}",
-               method_predicates.repr(self.tcx()));
+        debug!("method_predicates after subst = {:?}",
+               method_predicates);
 
         // Instantiate late-bound regions and substitute the trait
         // parameters into the method type to get the actual method type.
@@ -415,12 +412,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         // may reference those regions.
         let method_sig = self.replace_late_bound_regions_with_fresh_var(
             &pick.item.as_opt_method().unwrap().fty.sig);
-        debug!("late-bound lifetimes from method instantiated, method_sig={}",
-               method_sig.repr(self.tcx()));
+        debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
+               method_sig);
 
         let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
-        debug!("type scheme substituted, method_sig={}",
-               method_sig.repr(self.tcx()));
+        debug!("type scheme substituted, method_sig={:?}",
+               method_sig);
 
         InstantiatedMethodSig {
             method_sig: method_sig,
@@ -433,10 +430,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                        pick: &probe::Pick<'tcx>,
                        all_substs: &subst::Substs<'tcx>,
                        method_predicates: &ty::InstantiatedPredicates<'tcx>) {
-        debug!("add_obligations: pick={} all_substs={} method_predicates={}",
-               pick.repr(self.tcx()),
-               all_substs.repr(self.tcx()),
-               method_predicates.repr(self.tcx()));
+        debug!("add_obligations: pick={:?} all_substs={:?} method_predicates={:?}",
+               pick,
+               all_substs,
+               method_predicates);
 
         self.fcx.add_obligations_for_parameters(
             traits::ObligationCause::misc(self.span, self.fcx.body_id),
@@ -456,12 +453,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     fn fixup_derefs_on_method_receiver_if_necessary(&self,
                                                     method_callee: &MethodCallee) {
         let sig = match method_callee.ty.sty {
-            ty::ty_bare_fn(_, ref f) => f.sig.clone(),
+            ty::TyBareFn(_, ref f) => f.sig.clone(),
             _ => return,
         };
 
         match sig.0.inputs[0].sty {
-            ty::ty_rptr(_, ty::mt {
+            ty::TyRef(_, ty::mt {
                 ty: _,
                 mutbl: ast::MutMutable,
             }) => {}
@@ -483,8 +480,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             }
         }
 
-        debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
-               exprs.repr(self.tcx()));
+        debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={:?}",
+               exprs);
 
         // Fix up autoderefs and derefs.
         for (i, &expr) in exprs.iter().rev().enumerate() {
@@ -498,8 +495,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 Some(_) | None => 0,
             };
 
-            debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
-                   i, expr.repr(self.tcx()), autoderef_count);
+            debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={:?} \
+                                                                  autoderef_count={}",
+                   i, expr, autoderef_count);
 
             if autoderef_count > 0 {
                 check::autoderef(self.fcx,
@@ -545,8 +543,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                                 Some(_) => {
                                     self.tcx().sess.span_bug(
                                         base_expr.span,
-                                        &format!("unexpected adjustment autoref {}",
-                                                adr.repr(self.tcx())));
+                                        &format!("unexpected adjustment autoref {:?}",
+                                                adr));
                                 }
                             },
                             None => (0, None),
@@ -647,17 +645,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         if upcast_trait_refs.len() != 1 {
             self.tcx().sess.span_bug(
                 self.span,
-                &format!("cannot uniquely upcast `{}` to `{}`: `{}`",
-                         source_trait_ref.repr(self.tcx()),
-                         target_trait_def_id.repr(self.tcx()),
-                         upcast_trait_refs.repr(self.tcx())));
+                &format!("cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
+                         source_trait_ref,
+                         target_trait_def_id,
+                         upcast_trait_refs));
         }
 
         upcast_trait_refs.into_iter().next().unwrap()
     }
 
     fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         self.infcx().replace_late_bound_regions_with_fresh_var(
             self.span, infer::FnCall, value).0
index 90df0b853a083bca91097986ed2b8229e85bd9ce..e5a57fa9c138e17e17ec02f435c28e99579fe4dd 100644 (file)
@@ -16,9 +16,8 @@ use middle::def;
 use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
 use middle::subst;
 use middle::traits;
-use middle::ty::{self, AsPredicate, ToPolyTraitRef};
+use middle::ty::{self, AsPredicate, ToPolyTraitRef, TraitRef};
 use middle::infer;
-use util::ppaux::Repr;
 
 use syntax::ast::DefId;
 use syntax::ast;
@@ -33,11 +32,9 @@ mod confirm;
 mod probe;
 mod suggest;
 
-pub enum MethodError {
-    // Did not find an applicable method, but we did find various
-    // static methods that may apply, as well as a list of
-    // not-in-scope traits which may work.
-    NoMatch(Vec<CandidateSource>, Vec<ast::DefId>, probe::Mode),
+pub enum MethodError<'tcx> {
+    // Did not find an applicable method, but we did find various near-misses that may work.
+    NoMatch(NoMatchData<'tcx>),
 
     // Multiple methods might apply.
     Ambiguity(Vec<CandidateSource>),
@@ -46,9 +43,32 @@ pub enum MethodError {
     ClosureAmbiguity(/* DefId of fn trait */ ast::DefId),
 }
 
+// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
+// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
+pub struct NoMatchData<'tcx> {
+    pub static_candidates: Vec<CandidateSource>,
+    pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
+    pub out_of_scope_traits: Vec<ast::DefId>,
+    pub mode: probe::Mode
+}
+
+impl<'tcx> NoMatchData<'tcx> {
+    pub fn new(static_candidates: Vec<CandidateSource>,
+               unsatisfied_predicates: Vec<TraitRef<'tcx>>,
+               out_of_scope_traits: Vec<ast::DefId>,
+               mode: probe::Mode) -> Self {
+        NoMatchData {
+            static_candidates: static_candidates,
+            unsatisfied_predicates: unsatisfied_predicates,
+            out_of_scope_traits: out_of_scope_traits,
+            mode: mode
+        }
+    }
+}
+
 // A pared down enum describing just the places from which a method
 // candidate can arise. Used for error reporting only.
-#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
 pub enum CandidateSource {
     ImplSource(ast::DefId),
     TraitSource(/* trait id */ ast::DefId),
@@ -94,13 +114,13 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         supplied_method_types: Vec<ty::Ty<'tcx>>,
                         call_expr: &'tcx ast::Expr,
                         self_expr: &'tcx ast::Expr)
-                        -> Result<ty::MethodCallee<'tcx>, MethodError>
+                        -> Result<ty::MethodCallee<'tcx>, MethodError<'tcx>>
 {
-    debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})",
-           method_name.repr(fcx.tcx()),
-           self_ty.repr(fcx.tcx()),
-           call_expr.repr(fcx.tcx()),
-           self_expr.repr(fcx.tcx()));
+    debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
+           method_name,
+           self_ty,
+           call_expr,
+           self_expr);
 
     let mode = probe::Mode::MethodCall;
     let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
@@ -141,11 +161,11 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
                                           -> Option<ty::MethodCallee<'tcx>>
 {
-    debug!("lookup_in_trait_adjusted(self_ty={}, self_expr={}, m_name={}, trait_def_id={})",
-           self_ty.repr(fcx.tcx()),
-           self_expr.repr(fcx.tcx()),
-           m_name.repr(fcx.tcx()),
-           trait_def_id.repr(fcx.tcx()));
+    debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, m_name={}, trait_def_id={:?})",
+           self_ty,
+           self_expr,
+           m_name,
+           trait_def_id);
 
     let trait_def = ty::lookup_trait_def(fcx.tcx(), trait_def_id);
 
@@ -190,8 +210,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
     assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
 
-    debug!("lookup_in_trait_adjusted: method_num={} method_ty={}",
-           method_num, method_ty.repr(fcx.tcx()));
+    debug!("lookup_in_trait_adjusted: method_num={} method_ty={:?}",
+           method_num, method_ty);
 
     // Instantiate late-bound regions and substitute the trait
     // parameters into the method type to get the actual method type.
@@ -210,9 +230,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         abi: method_ty.fty.abi.clone(),
     }));
 
-    debug!("lookup_in_trait_adjusted: matched method fty={} obligation={}",
-           fty.repr(fcx.tcx()),
-           obligation.repr(fcx.tcx()));
+    debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
+           fty,
+           obligation);
 
     // Register obligations for the parameters.  This will include the
     // `Self` parameter, which in turn has a bound of the main trait,
@@ -254,7 +274,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     // Trait method is fn(&self) or fn(&mut self), need an
                     // autoref. Pull the region etc out of the type of first argument.
                     match transformed_self_ty.sty {
-                        ty::ty_rptr(region, ty::mt { mutbl, ty: _ }) => {
+                        ty::TyRef(region, ty::mt { mutbl, ty: _ }) => {
                             fcx.write_adjustment(self_expr.id,
                                 ty::AdjustDerefRef(ty::AutoDerefRef {
                                     autoderefs: autoderefs,
@@ -272,7 +292,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                 span,
                                 &format!(
                                     "trait method is &self but first arg is: {}",
-                                    transformed_self_ty.repr(fcx.tcx())));
+                                    transformed_self_ty));
                         }
                     }
                 }
@@ -296,7 +316,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         substs: trait_ref.substs.clone()
     };
 
-    debug!("callee = {}", callee.repr(fcx.tcx()));
+    debug!("callee = {:?}", callee);
 
     Some(callee)
 }
@@ -306,7 +326,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               method_name: ast::Name,
                               self_ty: ty::Ty<'tcx>,
                               expr_id: ast::NodeId)
-                              -> Result<(def::Def, LastPrivate), MethodError>
+                              -> Result<(def::Def, LastPrivate), MethodError<'tcx>>
 {
     let mode = probe::Mode::Path;
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
index 2eca855d5960b08bfaff09be483c57cf402f9047..46bffa8ccabdaefbaf905208c036e2ddb6e350a4 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 use super::MethodError;
+use super::NoMatchData;
 use super::ItemIndex;
-use super::{CandidateSource,ImplSource,TraitSource};
+use super::{CandidateSource, ImplSource, TraitSource};
 use super::suggest;
 
 use check;
@@ -19,7 +20,7 @@ use middle::fast_reject;
 use middle::subst;
 use middle::subst::Subst;
 use middle::traits;
-use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef};
+use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
 use middle::ty_fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
@@ -28,7 +29,6 @@ use syntax::codemap::{Span, DUMMY_SP};
 use std::collections::HashSet;
 use std::mem;
 use std::rc::Rc;
-use util::ppaux::Repr;
 
 use self::CandidateKind::*;
 pub use self::PickKind::*;
@@ -43,31 +43,44 @@ struct ProbeContext<'a, 'tcx:'a> {
     inherent_candidates: Vec<Candidate<'tcx>>,
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: HashSet<ast::DefId>,
+
+    /// Collects near misses when the candidate functions are missing a `self` keyword and is only
+    /// used for error reporting
     static_candidates: Vec<CandidateSource>,
+
+    /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
+    /// for error reporting
+    unsatisfied_predicates: Vec<TraitRef<'tcx>>
 }
 
+#[derive(Debug)]
 struct CandidateStep<'tcx> {
     self_ty: Ty<'tcx>,
     autoderefs: usize,
     unsize: bool
 }
 
+#[derive(Debug)]
 struct Candidate<'tcx> {
     xform_self_ty: Ty<'tcx>,
     item: ty::ImplOrTraitItem<'tcx>,
     kind: CandidateKind<'tcx>,
 }
 
+#[derive(Debug)]
 enum CandidateKind<'tcx> {
-    InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
+    InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>,
+                          /* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
     ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize),
     ExtensionImplCandidate(/* Impl */ ast::DefId, ty::TraitRef<'tcx>,
-                           subst::Substs<'tcx>, ItemIndex),
+                           subst::Substs<'tcx>, ItemIndex,
+                           /* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
     ClosureCandidate(/* Trait */ ast::DefId, ItemIndex),
     WhereClauseCandidate(ty::PolyTraitRef<'tcx>, ItemIndex),
     ProjectionCandidate(ast::DefId, ItemIndex),
 }
 
+#[derive(Debug)]
 pub struct Pick<'tcx> {
     pub item: ty::ImplOrTraitItem<'tcx>,
     pub kind: PickKind<'tcx>,
@@ -99,7 +112,7 @@ pub enum PickKind<'tcx> {
     WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, ItemIndex),
 }
 
-pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError>;
+pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;
 
 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
 pub enum Mode {
@@ -121,8 +134,8 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                        scope_expr_id: ast::NodeId)
                        -> PickResult<'tcx>
 {
-    debug!("probe(self_ty={}, item_name={}, scope_expr_id={})",
-           self_ty.repr(fcx.tcx()),
+    debug!("probe(self_ty={:?}, item_name={}, scope_expr_id={})",
+           self_ty,
            item_name,
            scope_expr_id);
 
@@ -136,7 +149,8 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let steps = if mode == Mode::MethodCall {
         match create_steps(fcx, span, self_ty) {
             Some(steps) => steps,
-            None => return Err(MethodError::NoMatch(Vec::new(), Vec::new(), mode)),
+            None =>return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), Vec::new(),
+                                                                    Vec::new(), mode))),
         }
     } else {
         vec![CandidateStep {
@@ -161,9 +175,9 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             Some(simplified_steps)
         };
 
-    debug!("ProbeContext: steps for self_ty={} are {}",
-           self_ty.repr(fcx.tcx()),
-           steps.repr(fcx.tcx()));
+    debug!("ProbeContext: steps for self_ty={:?} are {:?}",
+           self_ty,
+           steps);
 
     // this creates one big transaction so that all type variables etc
     // that we create during the probe process are removed later
@@ -202,7 +216,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     });
 
     match final_ty.sty {
-        ty::ty_vec(elem_ty, Some(_)) => {
+        ty::TyArray(elem_ty, _) => {
             let slice_ty = ty::mk_vec(fcx.tcx(), elem_ty, None);
             steps.push(CandidateStep {
                 self_ty: slice_ty,
@@ -210,7 +224,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 unsize: true
             });
         }
-        ty::ty_err => return None,
+        ty::TyError => return None,
         _ => (),
     }
 
@@ -237,6 +251,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             steps: Rc::new(steps),
             opt_simplified_steps: opt_simplified_steps,
             static_candidates: Vec::new(),
+            unsatisfied_predicates: Vec::new(),
         }
     }
 
@@ -260,98 +275,98 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
     fn assemble_inherent_candidates(&mut self) {
         let steps = self.steps.clone();
-        for step in &*steps {
+        for step in steps.iter() {
             self.assemble_probe(step.self_ty);
         }
     }
 
     fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
-        debug!("assemble_probe: self_ty={}",
-               self_ty.repr(self.tcx()));
+        debug!("assemble_probe: self_ty={:?}",
+               self_ty);
 
         match self_ty.sty {
-            ty::ty_trait(box ref data) => {
+            ty::TyTrait(box ref data) => {
                 self.assemble_inherent_candidates_from_object(self_ty, data);
                 self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
             }
-            ty::ty_enum(did, _) |
-            ty::ty_struct(did, _) |
-            ty::ty_closure(did, _) => {
+            ty::TyEnum(did, _) |
+            ty::TyStruct(did, _) |
+            ty::TyClosure(did, _) => {
                 self.assemble_inherent_impl_candidates_for_type(did);
             }
-            ty::ty_uniq(_) => {
+            ty::TyBox(_) => {
                 if let Some(box_did) = self.tcx().lang_items.owned_box() {
                     self.assemble_inherent_impl_candidates_for_type(box_did);
                 }
             }
-            ty::ty_param(p) => {
+            ty::TyParam(p) => {
                 self.assemble_inherent_candidates_from_param(self_ty, p);
             }
-            ty::ty_char => {
+            ty::TyChar => {
                 let lang_def_id = self.tcx().lang_items.char_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::ty_str => {
+            ty::TyStr => {
                 let lang_def_id = self.tcx().lang_items.str_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::ty_vec(_, None) => {
+            ty::TySlice(_) => {
                 let lang_def_id = self.tcx().lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
+            ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
                 let lang_def_id = self.tcx().lang_items.const_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
+            ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
                 let lang_def_id = self.tcx().lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::ty_int(ast::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::ty_int(ast::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::ty_int(ast::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::ty_int(ast::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::ty_int(ast::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::ty_uint(ast::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::ty_uint(ast::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::ty_uint(ast::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::ty_uint(ast::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::ty_uint(ast::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::ty_float(ast::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::ty_float(ast::TyF64) => {
+            ty::TyFloat(ast::TyF64) => {
                 let lang_def_id = self.tcx().lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
@@ -374,7 +389,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id);
 
         if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) {
-            for &impl_def_id in &***impl_infos {
+            for &impl_def_id in impl_infos.iter() {
                 self.assemble_inherent_impl_probe(impl_def_id);
             }
         }
@@ -398,24 +413,32 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
 
         let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
-        let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
+        let impl_ty = impl_ty.subst(self.tcx(), &impl_substs);
 
         // Determine the receiver type that the method itself expects.
-        let xform_self_ty =
-            self.xform_self_ty(&item, impl_ty, &impl_substs);
+        let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs);
+
+        // We can't use normalize_associated_types_in as it will pollute the
+        // fcx's fulfillment context after this probe is over.
+        let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
+        let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
+        let traits::Normalized { value: xform_self_ty, obligations } =
+            traits::normalize(selcx, cause, &xform_self_ty);
+        debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
+               xform_self_ty);
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
             item: item,
-            kind: InherentImplCandidate(impl_def_id, impl_substs)
+            kind: InherentImplCandidate(impl_def_id, impl_substs, obligations)
         });
     }
 
     fn assemble_inherent_candidates_from_object(&mut self,
                                                 self_ty: Ty<'tcx>,
-                                                data: &ty::TyTrait<'tcx>) {
-        debug!("assemble_inherent_candidates_from_object(self_ty={})",
-               self_ty.repr(self.tcx()));
+                                                data: &ty::TraitTy<'tcx>) {
+        debug!("assemble_inherent_candidates_from_object(self_ty={:?})",
+               self_ty);
 
         let tcx = self.tcx();
 
@@ -460,7 +483,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                 match *predicate {
                     ty::Predicate::Trait(ref trait_predicate) => {
                         match trait_predicate.0.trait_ref.self_ty().sty {
-                            ty::ty_param(ref p) if *p == param_ty => {
+                            ty::TyParam(ref p) if *p == param_ty => {
                                 Some(trait_predicate.to_poly_trait_ref())
                             }
                             _ => None
@@ -486,10 +509,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                    trait_ref.substs);
 
             if let Some(ref m) = item.as_opt_method() {
-                debug!("found match: trait_ref={} substs={} m={}",
-                       trait_ref.repr(this.tcx()),
-                       trait_ref.substs.repr(this.tcx()),
-                       m.repr(this.tcx()));
+                debug!("found match: trait_ref={:?} substs={:?} m={:?}",
+                       trait_ref,
+                       trait_ref.substs,
+                       m);
                 assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
                            trait_ref.substs.types.get_slice(subst::TypeSpace).len());
                 assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
@@ -529,7 +552,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             usize,
         ),
     {
-        debug!("elaborate_bounds(bounds={})", bounds.repr(self.tcx()));
+        debug!("elaborate_bounds(bounds={:?})", bounds);
 
         let tcx = self.tcx();
         for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
@@ -550,7 +573,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
     fn assemble_extension_candidates_for_traits_in_scope(&mut self,
                                                          expr_id: ast::NodeId)
-                                                         -> Result<(),MethodError>
+                                                         -> Result<(), MethodError<'tcx>>
     {
         let mut duplicates = HashSet::new();
         let opt_applicable_traits = self.fcx.ccx.trait_map.get(&expr_id);
@@ -564,7 +587,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         Ok(())
     }
 
-    fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(),MethodError> {
+    fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> {
         let mut duplicates = HashSet::new();
         for trait_info in suggest::all_traits(self.fcx.ccx) {
             if duplicates.insert(trait_info.def_id) {
@@ -576,10 +599,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
     fn assemble_extension_candidates_for_trait(&mut self,
                                                trait_def_id: ast::DefId)
-                                               -> Result<(),MethodError>
+                                               -> Result<(), MethodError<'tcx>>
     {
-        debug!("assemble_extension_candidates_for_trait(trait_def_id={})",
-               trait_def_id.repr(self.tcx()));
+        debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
+               trait_def_id);
 
         // Check whether `trait_def_id` defines a method with suitable name:
         let trait_items =
@@ -628,9 +651,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
         // FIXME(arielb1): can we use for_each_relevant_impl here?
         trait_def.for_each_impl(self.tcx(), |impl_def_id| {
-            debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={} impl_def_id={}",
-                   trait_def_id.repr(self.tcx()),
-                   impl_def_id.repr(self.tcx()));
+            debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \
+                                                                  impl_def_id={:?}",
+                   trait_def_id,
+                   impl_def_id);
 
             if !self.impl_can_possibly_match(impl_def_id) {
                 return;
@@ -638,14 +662,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
             let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
 
-            debug!("impl_substs={}", impl_substs.repr(self.tcx()));
+            debug!("impl_substs={:?}", impl_substs);
 
             let impl_trait_ref =
                 ty::impl_trait_ref(self.tcx(), impl_def_id)
                 .unwrap() // we know this is a trait impl
                 .subst(self.tcx(), &impl_substs);
 
-            debug!("impl_trait_ref={}", impl_trait_ref.repr(self.tcx()));
+            debug!("impl_trait_ref={:?}", impl_trait_ref);
 
             // Determine the receiver type that the method itself expects.
             let xform_self_ty =
@@ -653,12 +677,24 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                    impl_trait_ref.self_ty(),
                                    impl_trait_ref.substs);
 
-            debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
+            // Normalize the receiver. We can't use normalize_associated_types_in
+            // as it will pollute the fcx's fulfillment context after this probe
+            // is over.
+            let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
+            let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
+            let traits::Normalized { value: xform_self_ty, obligations } =
+                traits::normalize(selcx, cause, &xform_self_ty);
+
+            debug!("xform_self_ty={:?}", xform_self_ty);
 
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item.clone(),
-                kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, item_index)
+                kind: ExtensionImplCandidate(impl_def_id,
+                                             impl_trait_ref,
+                                             impl_substs,
+                                             item_index,
+                                             obligations)
             });
         });
     }
@@ -683,7 +719,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                    trait_def_id: ast::DefId,
                                    item: ty::ImplOrTraitItem<'tcx>,
                                    item_index: usize)
-                                   -> Result<(),MethodError>
+                                   -> Result<(), MethodError<'tcx>>
     {
         // Check if this is one of the Fn,FnMut,FnOnce traits.
         let tcx = self.tcx();
@@ -700,9 +736,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         // Check if there is an unboxed-closure self-type in the list of receivers.
         // If so, add "synthetic impls".
         let steps = self.steps.clone();
-        for step in &*steps {
+        for step in steps.iter() {
             let closure_def_id = match step.self_ty.sty {
-                ty::ty_closure(a, _) => a,
+                ty::TyClosure(a, _) => a,
                 _ => continue,
             };
 
@@ -747,31 +783,31 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                       item_index: usize)
     {
         debug!("assemble_projection_candidates(\
-               trait_def_id={}, \
-               item={}, \
+               trait_def_id={:?}, \
+               item={:?}, \
                item_index={})",
-               trait_def_id.repr(self.tcx()),
-               item.repr(self.tcx()),
+               trait_def_id,
+               item,
                item_index);
 
-        for step in &*self.steps {
-            debug!("assemble_projection_candidates: step={}",
-                   step.repr(self.tcx()));
+        for step in self.steps.iter() {
+            debug!("assemble_projection_candidates: step={:?}",
+                   step);
 
             let projection_trait_ref = match step.self_ty.sty {
-                ty::ty_projection(ref data) => &data.trait_ref,
+                ty::TyProjection(ref data) => &data.trait_ref,
                 _ => continue,
             };
 
-            debug!("assemble_projection_candidates: projection_trait_ref={}",
-                   projection_trait_ref.repr(self.tcx()));
+            debug!("assemble_projection_candidates: projection_trait_ref={:?}",
+                   projection_trait_ref);
 
             let trait_predicates = ty::lookup_predicates(self.tcx(),
                                                          projection_trait_ref.def_id);
             let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
             let predicates = bounds.predicates.into_vec();
-            debug!("assemble_projection_candidates: predicates={}",
-                   predicates.repr(self.tcx()));
+            debug!("assemble_projection_candidates: predicates={:?}",
+                   predicates);
             for poly_bound in
                 traits::elaborate_predicates(self.tcx(), predicates)
                 .filter_map(|p| p.to_opt_poly_trait_ref())
@@ -779,18 +815,18 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             {
                 let bound = self.erase_late_bound_regions(&poly_bound);
 
-                debug!("assemble_projection_candidates: projection_trait_ref={} bound={}",
-                       projection_trait_ref.repr(self.tcx()),
-                       bound.repr(self.tcx()));
+                debug!("assemble_projection_candidates: projection_trait_ref={:?} bound={:?}",
+                       projection_trait_ref,
+                       bound);
 
                 if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
                     let xform_self_ty = self.xform_self_ty(&item,
                                                            bound.self_ty(),
                                                            bound.substs);
 
-                    debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
-                           bound.repr(self.tcx()),
-                           xform_self_ty.repr(self.tcx()));
+                    debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
+                           bound,
+                           xform_self_ty);
 
                     self.extension_candidates.push(Candidate {
                         xform_self_ty: xform_self_ty,
@@ -807,8 +843,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                         item: ty::ImplOrTraitItem<'tcx>,
                                         item_index: usize)
     {
-        debug!("assemble_where_clause_candidates(trait_def_id={})",
-               trait_def_id.repr(self.tcx()));
+        debug!("assemble_where_clause_candidates(trait_def_id={:?})",
+               trait_def_id);
 
         let caller_predicates = self.fcx.inh.param_env.caller_bounds.clone();
         for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates)
@@ -820,9 +856,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                                    bound.self_ty(),
                                                    bound.substs);
 
-            debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
-                   bound.repr(self.tcx()),
-                   xform_self_ty.repr(self.tcx()));
+            debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}",
+                   bound,
+                   xform_self_ty);
 
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
@@ -842,6 +878,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
 
         let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
+        let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
 
         // things failed, so lets look at all traits, for diagnostic purposes now:
         self.reset();
@@ -866,7 +903,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     }
                 }
             }).collect(),
-            Some(Err(MethodError::NoMatch(_, others, _))) => {
+            Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
                 assert!(others.is_empty());
                 vec![]
             }
@@ -877,7 +914,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             None => vec![],
         };
 
-        Err(MethodError::NoMatch(static_candidates, out_of_scope_traits, self.mode))
+        Err(MethodError::NoMatch(NoMatchData::new(static_candidates, unsatisfied_predicates,
+                                                  out_of_scope_traits, self.mode)))
     }
 
     fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
@@ -888,7 +926,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     }
 
     fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
-        debug!("pick_step: step={}", step.repr(self.tcx()));
+        debug!("pick_step: step={:?}", step);
 
         if ty::type_is_error(step.self_ty) {
             return None;
@@ -924,7 +962,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             pick.autoderefs = step.autoderefs;
 
             // Insert a `&*` or `&mut *` if this is a reference type:
-            if let ty::ty_rptr(_, mt) = step.self_ty.sty {
+            if let ty::TyRef(_, mt) = step.self_ty.sty {
                 pick.autoderefs += 1;
                 pick.autoref = Some(mt.mutbl);
             }
@@ -965,8 +1003,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_method(self_ty={})", self.infcx().ty_to_string(self_ty));
 
+        let mut possibly_unsatisfied_predicates = Vec::new();
+
         debug!("searching inherent candidates");
-        match self.consider_candidates(self_ty, &self.inherent_candidates) {
+        match self.consider_candidates(self_ty, &self.inherent_candidates,
+                                       &mut possibly_unsatisfied_predicates) {
             None => {}
             Some(pick) => {
                 return Some(pick);
@@ -974,19 +1015,26 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
 
         debug!("searching extension candidates");
-        self.consider_candidates(self_ty, &self.extension_candidates)
+        let res = self.consider_candidates(self_ty, &self.extension_candidates,
+                                           &mut possibly_unsatisfied_predicates);
+        if let None = res {
+            self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+        }
+        res
     }
 
     fn consider_candidates(&self,
                            self_ty: Ty<'tcx>,
-                           probes: &[Candidate<'tcx>])
+                           probes: &[Candidate<'tcx>],
+                           possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
                            -> Option<PickResult<'tcx>> {
         let mut applicable_candidates: Vec<_> =
             probes.iter()
-                  .filter(|&probe| self.consider_probe(self_ty, probe))
+                  .filter(|&probe| self.consider_probe(self_ty,
+                                                       probe,possibly_unsatisfied_predicates))
                   .collect();
 
-        debug!("applicable_candidates: {}", applicable_candidates.repr(self.tcx()));
+        debug!("applicable_candidates: {:?}", applicable_candidates);
 
         if applicable_candidates.len() > 1 {
             match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
@@ -1006,10 +1054,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         })
     }
 
-    fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>) -> bool {
-        debug!("consider_probe: self_ty={} probe={}",
-               self_ty.repr(self.tcx()),
-               probe.repr(self.tcx()));
+    fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>,
+                      possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>) -> bool {
+        debug!("consider_probe: self_ty={:?} probe={:?}",
+               self_ty,
+               probe);
 
         self.infcx().probe(|_| {
             // First check that the self type can be related.
@@ -1026,8 +1075,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             // match as well (or at least may match, sometimes we
             // don't have enough information to fully evaluate).
             match probe.kind {
-                InherentImplCandidate(impl_def_id, ref substs) |
-                ExtensionImplCandidate(impl_def_id, _, ref substs, _) => {
+                InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
+                ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
                     let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx);
                     let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
@@ -1040,14 +1089,23 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
                     // Convert the bounds into obligations.
                     let obligations =
-                        traits::predicates_for_generics(self.tcx(),
-                                                        cause.clone(),
+                        traits::predicates_for_generics(cause.clone(),
                                                         &impl_bounds);
-                    debug!("impl_obligations={}", obligations.repr(self.tcx()));
+                    debug!("impl_obligations={:?}", obligations);
 
                     // Evaluate those obligations to see if they might possibly hold.
-                    obligations.all(|o| selcx.evaluate_obligation(o)) &&
-                        norm_obligations.iter().all(|o| selcx.evaluate_obligation(o))
+                    let mut all_true = true;
+                    for o in obligations.iter()
+                        .chain(norm_obligations.iter())
+                        .chain(ref_obligations.iter()) {
+                        if !selcx.evaluate_obligation(o) {
+                            all_true = false;
+                            if let &ty::Predicate::Trait(ref pred) = &o.predicate {
+                                possibly_unsatisfied_predicates.push(pred.0.trait_ref);
+                            }
+                        }
+                    }
+                    all_true
                 }
 
                 ProjectionCandidate(..) |
@@ -1153,10 +1211,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                             substs: &subst::Substs<'tcx>)
                             -> Ty<'tcx>
     {
-        debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
-               impl_ty.repr(self.tcx()),
-               method.fty.sig.0.inputs.get(0).repr(self.tcx()),
-               substs.repr(self.tcx()));
+        debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
+               impl_ty,
+               method.fty.sig.0.inputs.get(0),
+               substs);
 
         assert!(!substs.has_escaping_regions());
 
@@ -1241,7 +1299,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     ///    and/or tracking the substitution and
     ///    so forth.
     fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         ty::erase_late_bound_regions(self.tcx(), value)
     }
@@ -1281,13 +1339,13 @@ impl<'tcx> Candidate<'tcx> {
         Pick {
             item: self.item.clone(),
             kind: match self.kind {
-                InherentImplCandidate(def_id, _) => {
+                InherentImplCandidate(def_id, _, _) => {
                     InherentImplPick(def_id)
                 }
                 ObjectCandidate(def_id, item_num, real_index) => {
                     ObjectPick(def_id, item_num, real_index)
                 }
-                ExtensionImplCandidate(def_id, _, _, index) => {
+                ExtensionImplCandidate(def_id, _, _, index, _) => {
                     ExtensionImplPick(def_id, index)
                 }
                 ClosureCandidate(trait_def_id, index) => {
@@ -1315,9 +1373,9 @@ impl<'tcx> Candidate<'tcx> {
 
     fn to_source(&self) -> CandidateSource {
         match self.kind {
-            InherentImplCandidate(def_id, _) => ImplSource(def_id),
+            InherentImplCandidate(def_id, _, _) => ImplSource(def_id),
             ObjectCandidate(def_id, _, _) => TraitSource(def_id),
-            ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
+            ExtensionImplCandidate(def_id, _, _, _, _) => ImplSource(def_id),
             ClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
             WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
             ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id),
@@ -1335,7 +1393,7 @@ impl<'tcx> Candidate<'tcx> {
             ClosureCandidate(trait_def_id, item_num) => {
                 Some((trait_def_id, item_num))
             }
-            ExtensionImplCandidate(_, ref trait_ref, _, item_num) => {
+            ExtensionImplCandidate(_, ref trait_ref, _, item_num, _) => {
                 Some((trait_ref.def_id, item_num))
             }
             WhereClauseCandidate(ref trait_ref, item_num) => {
@@ -1347,58 +1405,3 @@ impl<'tcx> Candidate<'tcx> {
         }
     }
 }
-
-impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Candidate(xform_self_ty={}, kind={})",
-                self.xform_self_ty.repr(tcx),
-                self.kind.repr(tcx))
-    }
-}
-
-impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            InherentImplCandidate(ref a, ref b) =>
-                format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
-            ObjectCandidate(a, b, c) =>
-                format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
-            ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
-                format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
-                        c.repr(tcx), d),
-            ClosureCandidate(ref a, ref b) =>
-                format!("ClosureCandidate({},{})", a.repr(tcx), b),
-            WhereClauseCandidate(ref a, ref b) =>
-                format!("WhereClauseCandidate({},{})", a.repr(tcx), b),
-            ProjectionCandidate(ref a, ref b) =>
-                format!("ProjectionCandidate({},{})", a.repr(tcx), b),
-        }
-    }
-}
-
-impl<'tcx> Repr<'tcx> for CandidateStep<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("CandidateStep({}, autoderefs={}, unsize={})",
-                self.self_ty.repr(tcx),
-                self.autoderefs,
-                self.unsize)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for PickKind<'tcx> {
-    fn repr(&self, _tcx: &ty::ctxt) -> String {
-        format!("{:?}", self)
-    }
-}
-
-impl<'tcx> Repr<'tcx> for Pick<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Pick(item={}, autoderefs={},
-                 autoref={}, unsize={}, kind={:?})",
-                self.item.repr(tcx),
-                self.autoderefs,
-                self.autoref.repr(tcx),
-                self.unsize.repr(tcx),
-                self.kind)
-    }
-}
index 93239df60e16499b15536c39c252f514ffc0631d..2325b9852c73dc4c62b1835e64e2765fa4ba8c4f 100644 (file)
@@ -15,10 +15,12 @@ use CrateCtxt;
 
 use astconv::AstConv;
 use check::{self, FnCtxt};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, ToPolyTraitRef, AsPredicate};
 use middle::def;
+use middle::lang_items::FnOnceTraitLangItem;
+use middle::subst::Substs;
+use middle::traits::{Obligation, SelectionContext};
 use metadata::{csearch, cstore, decoder};
-use util::ppaux::UserString;
 
 use syntax::{ast, ast_util};
 use syntax::codemap::Span;
@@ -27,7 +29,7 @@ use syntax::print::pprust;
 use std::cell;
 use std::cmp::Ordering;
 
-use super::{MethodError, CandidateSource, impl_item, trait_item};
+use super::{MethodError, NoMatchData, CandidateSource, impl_item, trait_item};
 use super::probe::Mode;
 
 pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -35,7 +37,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               rcvr_ty: Ty<'tcx>,
                               item_name: ast::Name,
                               rcvr_expr: Option<&ast::Expr>,
-                              error: MethodError)
+                              error: MethodError<'tcx>)
 {
     // avoid suggestions when we don't know what's going on.
     if ty::type_is_error(rcvr_ty) {
@@ -43,9 +45,11 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     match error {
-        MethodError::NoMatch(static_sources, out_of_scope_traits, mode) => {
+        MethodError::NoMatch(NoMatchData { static_candidates: static_sources,
+                                           unsatisfied_predicates,
+                                           out_of_scope_traits,
+                                           mode }) => {
             let cx = fcx.tcx();
-            let item_ustring = item_name.user_string(cx);
 
             fcx.type_error_message(
                 span,
@@ -54,30 +58,91 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              in the current scope",
                             if mode == Mode::MethodCall { "method" }
                             else { "associated item" },
-                            item_ustring,
+                            item_name,
                             actual)
                 },
                 rcvr_ty,
                 None);
 
             // If the item has the name of a field, give a help note
-            if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
+            if let (&ty::TyStruct(did, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
                 let fields = ty::lookup_struct_fields(cx, did);
-                if fields.iter().any(|f| f.name == item_name) {
-                    cx.sess.span_note(span,
-                        &format!("use `(s.{0})(...)` if you meant to call the \
-                                 function stored in the `{0}` field", item_ustring));
+
+                if let Some(field) = fields.iter().find(|f| f.name == item_name) {
+                    let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
+                        Ok(expr_string) => expr_string,
+                        _ => "s".into() // Default to a generic placeholder for the
+                                        // expression when we can't generate a string
+                                        // snippet
+                    };
+
+                    let span_stored_function = || {
+                        cx.sess.span_note(span,
+                                          &format!("use `({0}.{1})(...)` if you meant to call \
+                                                    the function stored in the `{1}` field",
+                                                   expr_string, item_name));
+                    };
+
+                    let span_did_you_mean = || {
+                        cx.sess.span_note(span, &format!("did you mean to write `{0}.{1}`?",
+                                                         expr_string, item_name));
+                    };
+
+                    // Determine if the field can be used as a function in some way
+                    let field_ty = ty::lookup_field_type(cx, did, field.id, substs);
+                    if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) {
+                        let infcx = fcx.infcx();
+                        infcx.probe(|_| {
+                            let fn_once_substs = Substs::new_trait(vec![infcx.next_ty_var()],
+                                                                   Vec::new(),
+                                                                   field_ty);
+                            let trait_ref = ty::TraitRef::new(fn_once_trait_did,
+                                                              cx.mk_substs(fn_once_substs));
+                            let poly_trait_ref = trait_ref.to_poly_trait_ref();
+                            let obligation = Obligation::misc(span,
+                                                              fcx.body_id,
+                                                              poly_trait_ref.as_predicate());
+                            let mut selcx = SelectionContext::new(infcx, fcx);
+
+                            if selcx.evaluate_obligation(&obligation) {
+                                span_stored_function();
+                            } else {
+                                span_did_you_mean();
+                            }
+                        });
+                    } else {
+                        match field_ty.sty {
+                            // fallback to matching a closure or function pointer
+                            ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(),
+                            _ => span_did_you_mean(),
+                        }
+                    }
                 }
             }
 
             if !static_sources.is_empty() {
-                fcx.tcx().sess.fileline_note(
+                cx.sess.fileline_note(
                     span,
                     "found defined static methods, maybe a `self` is missing?");
 
                 report_candidates(fcx, span, item_name, static_sources);
             }
 
+            if !unsatisfied_predicates.is_empty() {
+                let bound_list = unsatisfied_predicates.iter()
+                    .map(|p| format!("`{} : {}`",
+                                     p.self_ty(),
+                                     p))
+                    .collect::<Vec<_>>()
+                    .connect(", ");
+                cx.sess.fileline_note(
+                    span,
+                    &format!("the method `{}` exists but the \
+                             following trait bounds were not satisfied: {}",
+                             item_name,
+                             bound_list));
+            }
+
             suggest_traits_to_import(fcx, span, rcvr_ty, item_name,
                                      rcvr_expr, out_of_scope_traits)
         }
@@ -93,7 +158,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
                                invoked on this closure as we have not yet inferred what \
                                kind of closure it is",
-                               item_name.user_string(fcx.tcx()),
+                               item_name,
                                ty::item_path_str(fcx.tcx(), trait_def_id));
             let msg = if let Some(callee) = rcvr_expr {
                 format!("{}; use overloaded call notation instead (e.g., `{}()`)",
@@ -134,7 +199,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                "candidate #{} is defined in an impl{} for the type `{}`",
                                idx + 1,
                                insertion,
-                               impl_ty.user_string(fcx.tcx()));
+                               impl_ty);
                 }
                 CandidateSource::TraitSource(trait_did) => {
                     let (_, item) = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
@@ -160,7 +225,6 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       valid_out_of_scope_traits: Vec<ast::DefId>)
 {
     let tcx = fcx.tcx();
-    let item_ustring = item_name.user_string(tcx);
 
     if !valid_out_of_scope_traits.is_empty() {
         let mut candidates = valid_out_of_scope_traits;
@@ -217,7 +281,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
              perhaps you need to implement {one_of_them}:",
             traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
             one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
-            name = item_ustring);
+            name = item_name);
 
         fcx.sess().fileline_help(span, &msg[..]);
 
@@ -238,11 +302,11 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   rcvr_expr: Option<&ast::Expr>) -> bool {
     fn is_local(ty: Ty) -> bool {
         match ty.sty {
-            ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
+            ty::TyEnum(did, _) | ty::TyStruct(did, _) => ast_util::is_local(did),
 
-            ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
+            ty::TyTrait(ref tr) => ast_util::is_local(tr.principal_def_id()),
 
-            ty::ty_param(_) => true,
+            ty::TyParam(_) => true,
 
             // everything else (primitive types etc.) is effectively
             // non-local (there are "edge" cases, e.g. (LocalType,), but
index 3cdbaec15284b7e488e423ae208e1aa8b2191781..8a54cfab038e5404b85b7b9fd96aa72889acf8b8 100644 (file)
@@ -98,7 +98,7 @@ use middle::ty::{FnSig, GenericPredicates, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
 use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::liberate_late_bound_regions;
-use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
+use middle::ty::{MethodCall, MethodCallee, MethodMap};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
 use session::Session;
@@ -106,7 +106,6 @@ use {CrateCtxt, lookup_full_def, require_same_types};
 use TypeAndSubsts;
 use lint;
 use util::common::{block_query, ErrorReported, indenter, loop_query};
-use util::ppaux::{self, Repr};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 use util::lev_distance::lev_distance;
 
@@ -164,7 +163,6 @@ pub struct Inherited<'a, 'tcx: 'a> {
     upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
     closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
     closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
-    object_cast_map: ObjectCastMap<'tcx>,
 
     // A mapping from each fn's id to its signature, with all bound
     // regions replaced with free ones. Unlike the other tables, this
@@ -194,7 +192,7 @@ type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx
 
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum Expectation<'tcx> {
     /// We know nothing about what type this expression should have.
     NoExpectation,
@@ -383,12 +381,11 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
             item_substs: RefCell::new(NodeMap()),
             adjustments: RefCell::new(NodeMap()),
             method_map: RefCell::new(FnvHashMap()),
-            object_cast_map: RefCell::new(NodeMap()),
             upvar_capture_map: RefCell::new(FnvHashMap()),
             closure_tys: RefCell::new(DefIdMap()),
             closure_kinds: RefCell::new(DefIdMap()),
             fn_sig_map: RefCell::new(NodeMap()),
-            fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
+            fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
         }
@@ -400,7 +397,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
                                         body_id: ast::NodeId,
                                         value: &T)
                                         -> T
-        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+        where T : TypeFoldable<'tcx> + HasProjectionTypes
     {
         let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
         assoc::normalize_associated_types_in(&self.infcx,
@@ -508,7 +505,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            param_env: ty::ParameterEnvironment<'a, 'tcx>)
 {
     match raw_fty.sty {
-        ty::ty_bare_fn(_, ref fn_ty) => {
+        ty::TyBareFn(_, ref fn_ty) => {
             let inh = Inherited::new(ccx.tcx, param_env);
 
             // Compute the fty from point of view of inside fn.
@@ -528,6 +525,9 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
             fcx.select_all_obligations_or_error();
             fcx.check_casts();
+
+            fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
+
             regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
@@ -566,8 +566,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
             None => None
         };
         self.assign(local.span, local.id, o_ty);
-        debug!("Local variable {} is assigned type {}",
-               self.fcx.pat_to_string(&*local.pat),
+        debug!("Local variable {:?} is assigned type {}",
+               local.pat,
                self.fcx.infcx().ty_to_string(
                    self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
         visit::walk_local(self, local);
@@ -582,11 +582,11 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                 self.fcx.require_type_is_sized(var_ty, p.span,
                                                traits::VariableType(p.id));
 
-                debug!("Pattern binding {} is assigned to {} with type {}",
+                debug!("Pattern binding {} is assigned to {} with type {:?}",
                        token::get_ident(path1.node),
                        self.fcx.infcx().ty_to_string(
                            self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
-                       var_ty.repr(self.fcx.tcx()));
+                       var_ty);
             }
         }
         visit::walk_pat(self, p);
@@ -640,9 +640,9 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
     let arg_tys = &fn_sig.inputs;
     let ret_ty = fn_sig.output;
 
-    debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
-           arg_tys.repr(tcx),
-           ret_ty.repr(tcx),
+    debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
+           arg_tys,
+           ret_ty,
            fn_id);
 
     // Create the function context.  This is either derived from scratch or,
@@ -668,9 +668,9 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
         fn_sig_tys.push(ret_ty);
     }
 
-    debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
+    debug!("fn-sig-map: fn_id={} fn_sig_tys={:?}",
            fn_id,
-           fn_sig_tys.repr(tcx));
+           fn_sig_tys);
 
     inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
 
@@ -678,7 +678,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
         let mut visit = GatherLocalsVisitor { fcx: &fcx, };
 
         // Add formal parameters.
-        for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
+        for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
             // Create type variables for each argument.
             pat_util::pat_bindings(
                 &tcx.def_map,
@@ -705,8 +705,8 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
         ty::FnDiverging => NoExpectation
     });
 
-    for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
-        fcx.write_ty(input.id, *arg);
+    for (input, arg) in decl.inputs.iter().zip(arg_tys) {
+        fcx.write_ty(input.id, arg);
     }
 
     fcx
@@ -738,7 +738,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
                             &enum_definition.variants,
                             it.id);
       }
-      ast::ItemFn(_, _, _, _, _) => {} // entirely within check_item_body
+      ast::ItemFn(..) => {} // entirely within check_item_body
       ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
           debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
           match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
@@ -793,7 +793,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
            ty::item_path_str(ccx.tcx, local_def(it.id)));
     let _indenter = indenter();
     match it.node {
-      ast::ItemFn(ref decl, _, _, _, ref body) => {
+      ast::ItemFn(ref decl, _, _, _, _, ref body) => {
         let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(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);
@@ -827,11 +827,15 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
                     check_const(ccx, trait_item.span, &*expr, trait_item.id)
                 }
                 ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
+
                     check_method_body(ccx, &trait_def.generics, sig, body,
                                       trait_item.id, trait_item.span);
                 }
+                ast::MethodTraitItem(ref sig, None) => {
+                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
+                }
                 ast::ConstTraitItem(_, None) |
-                ast::MethodTraitItem(_, None) |
                 ast::TypeTraitItem(..) => {
                     // Nothing to do.
                 }
@@ -842,6 +846,20 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
     }
 }
 
+fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                     span: Span,
+                                     constness: ast::Constness)
+{
+    match constness {
+        ast::Constness::NotConst => {
+            // good
+        }
+        ast::Constness::Const => {
+            span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
+        }
+    }
+}
+
 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                generics: &ast::Generics,
                                item: &ast::Item) {
@@ -899,12 +917,12 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                sig: &'tcx ast::MethodSig,
                                body: &'tcx ast::Block,
                                id: ast::NodeId, span: Span) {
-    debug!("check_method_body(item_generics={}, id={})",
-            item_generics.repr(ccx.tcx), id);
+    debug!("check_method_body(item_generics={:?}, id={})",
+            item_generics, id);
     let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
 
     let fty = ty::node_id_to_type(ccx.tcx, id);
-    debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
+    debug!("check_method_body: fty={:?}", fty);
 
     check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
 }
@@ -944,9 +962,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             _ => {
                                 span_err!(tcx.sess, impl_item.span, E0323,
                                           "item `{}` is an associated const, \
-                                          which doesn't match its trait `{}`",
+                                          which doesn't match its trait `{:?}`",
                                           token::get_name(impl_const_ty.name()),
-                                          impl_trait_ref.repr(tcx))
+                                          impl_trait_ref)
                             }
                         }
                     }
@@ -957,13 +975,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             impl_item.span,
                             &format!(
                                 "associated const `{}` is not a member of \
-                                 trait `{}`",
+                                 trait `{:?}`",
                                 token::get_name(impl_const_ty.name()),
-                                impl_trait_ref.repr(tcx)));
+                                impl_trait_ref));
                     }
                 }
             }
-            ast::MethodImplItem(_, ref body) => {
+            ast::MethodImplItem(ref sig, ref body) => {
+                check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
+
                 let impl_method_def_id = local_def(impl_item.id);
                 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
                                                           impl_method_def_id);
@@ -988,9 +1008,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             _ => {
                                 span_err!(tcx.sess, impl_item.span, E0324,
                                           "item `{}` is an associated method, \
-                                          which doesn't match its trait `{}`",
+                                          which doesn't match its trait `{:?}`",
                                           token::get_name(impl_item_ty.name()),
-                                          impl_trait_ref.repr(tcx))
+                                          impl_trait_ref)
                             }
                         }
                     }
@@ -999,9 +1019,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         // caught in resolve.
                         tcx.sess.span_bug(
                             impl_item.span,
-                            &format!("method `{}` is not a member of trait `{}`",
+                            &format!("method `{}` is not a member of trait `{:?}`",
                                      token::get_name(impl_item_ty.name()),
-                                     impl_trait_ref.repr(tcx)));
+                                     impl_trait_ref));
                     }
                 }
             }
@@ -1022,9 +1042,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             _ => {
                                 span_err!(tcx.sess, impl_item.span, E0325,
                                           "item `{}` is an associated type, \
-                                          which doesn't match its trait `{}`",
+                                          which doesn't match its trait `{:?}`",
                                           token::get_name(typedef_ty.name()),
-                                          impl_trait_ref.repr(tcx))
+                                          impl_trait_ref)
                             }
                         }
                     }
@@ -1035,9 +1055,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             impl_item.span,
                             &format!(
                                 "associated type `{}` is not a member of \
-                                 trait `{}`",
+                                 trait `{:?}`",
                                 token::get_name(typedef_ty.name()),
-                                impl_trait_ref.repr(tcx)));
+                                impl_trait_ref));
                     }
                 }
             }
@@ -1049,8 +1069,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // Check for missing items from trait
     let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
     let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
-    let mut missing_methods = Vec::new();
-    for trait_item in &*trait_items {
+    let mut missing_items = Vec::new();
+    for trait_item in trait_items.iter() {
         match *trait_item {
             ty::ConstTraitItem(ref associated_const) => {
                 let is_implemented = impl_items.iter().any(|ii| {
@@ -1065,8 +1085,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     associated_consts.iter().any(|ac| ac.default.is_some() &&
                                                  ac.name == associated_const.name);
                 if !is_implemented && !is_provided {
-                    missing_methods.push(format!("`{}`",
-                                                 token::get_name(associated_const.name)));
+                    missing_items.push(format!("`{}`",
+                                               token::get_name(associated_const.name)));
                 }
             }
             ty::MethodTraitItem(ref trait_method) => {
@@ -1082,7 +1102,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let is_provided =
                     provided_methods.iter().any(|m| m.name == trait_method.name);
                 if !is_implemented && !is_provided {
-                    missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
+                    missing_items.push(format!("`{}`", token::get_name(trait_method.name)));
                 }
             }
             ty::TypeTraitItem(ref associated_type) => {
@@ -1094,17 +1114,18 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         _ => false,
                     }
                 });
-                if !is_implemented {
-                    missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
+                let is_provided = associated_type.ty.is_some();
+                if !is_implemented && !is_provided {
+                    missing_items.push(format!("`{}`", token::get_name(associated_type.name)));
                 }
             }
         }
     }
 
-    if !missing_methods.is_empty() {
+    if !missing_items.is_empty() {
         span_err!(tcx.sess, impl_span, E0046,
             "not all trait items implemented, missing: {}",
-            missing_methods.connect(", "));
+            missing_items.connect(", "));
     }
 }
 
@@ -1112,20 +1133,20 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          span: Span,
                                          t_span: Span,
                                          e_span: Span,
-                                         t_1: Ty<'tcx>,
-                                         t_e: Ty<'tcx>,
+                                         t_cast: Ty<'tcx>,
+                                         t_expr: Ty<'tcx>,
                                          id: ast::NodeId) {
-    let tstr = fcx.infcx().ty_to_string(t_1);
+    let tstr = fcx.infcx().ty_to_string(t_cast);
     fcx.type_error_message(span, |actual| {
         format!("cast to unsized type: `{}` as `{}`", actual, tstr)
-    }, t_e, None);
-    match t_e.sty {
-        ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
+    }, t_expr, None);
+    match t_expr.sty {
+        ty::TyRef(_, ty::mt { mutbl: mt, .. }) => {
             let mtstr = match mt {
                 ast::MutMutable => "mut ",
                 ast::MutImmutable => ""
             };
-            if ty::type_is_trait(t_1) {
+            if ty::type_is_trait(t_cast) {
                 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                     Ok(s) => {
                         fcx.tcx().sess.span_suggestion(t_span,
@@ -1142,7 +1163,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            mtstr, tstr);
             }
         }
-        ty::ty_uniq(..) => {
+        ty::TyBox(..) => {
             match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                 Ok(s) => {
                     fcx.tcx().sess.span_suggestion(t_span,
@@ -1273,18 +1294,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// version, this version will also select obligations if it seems
     /// useful, in an effort to get more type information.
     fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx()));
+        debug!("resolve_type_vars_if_possible(ty={:?})", ty);
 
         // No ty::infer()? Nothing needs doing.
         if !ty::type_has_ty_infer(ty) {
-            debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
+            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
 
         // If `ty` is a type variable, see whether we already know what it is.
         ty = self.infcx().resolve_type_vars_if_possible(&ty);
         if !ty::type_has_ty_infer(ty) {
-            debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
+            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
 
@@ -1292,7 +1313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.select_new_obligations();
         ty = self.infcx().resolve_type_vars_if_possible(&ty);
         if !ty::type_has_ty_infer(ty) {
-            debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
+            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
 
@@ -1303,7 +1324,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.select_obligations_where_possible();
         ty = self.infcx().resolve_type_vars_if_possible(&ty);
 
-        debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
+        debug!("resolve_type_vars_if_possible: ty={:?}", ty);
         ty
     }
 
@@ -1373,16 +1394,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     #[inline]
     pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
-        debug!("write_ty({}, {}) in fcx {}",
-               node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
+        debug!("write_ty({}, {:?}) in fcx {}",
+               node_id, ty, self.tag());
         self.inh.node_types.borrow_mut().insert(node_id, ty);
     }
 
     pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
         if !substs.substs.is_noop() {
-            debug!("write_substs({}, {}) in fcx {}",
+            debug!("write_substs({}, {:?}) in fcx {}",
                    node_id,
-                   substs.repr(self.tcx()),
+                   substs,
                    self.tag());
 
             self.inh.item_substs.borrow_mut().insert(node_id, substs);
@@ -1405,7 +1426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn write_adjustment(&self,
                             node_id: ast::NodeId,
                             adj: ty::AutoAdjustment<'tcx>) {
-        debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
+        debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
 
         if adj.is_identity() {
             return;
@@ -1422,14 +1443,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                   substs: &Substs<'tcx>,
                                   value: &T)
                                   -> T
-        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+        where T : TypeFoldable<'tcx> + HasProjectionTypes
     {
         let value = value.subst(self.tcx(), substs);
         let result = self.normalize_associated_types_in(span, &value);
-        debug!("instantiate_type_scheme(value={}, substs={}) = {}",
-               value.repr(self.tcx()),
-               substs.repr(self.tcx()),
-               result.repr(self.tcx()));
+        debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
+               value,
+               substs,
+               result);
         result
     }
 
@@ -1448,7 +1469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
 
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
-        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+        where T : TypeFoldable<'tcx> + HasProjectionTypes
     {
         self.inh.normalize_associated_types_in(self, span, self.body_id, value)
     }
@@ -1581,13 +1602,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                                  span)
     }
 
-    pub fn type_is_fat_ptr(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        if let Some(mt) = ty::deref(ty, true) {
-            return !self.type_is_known_to_be_sized(mt.ty, span);
-        }
-        false
-    }
-
     pub fn register_builtin_bound(&self,
                                   ty: Ty<'tcx>,
                                   builtin_bound: ty::BuiltinBound,
@@ -1600,8 +1614,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn register_predicate(&self,
                               obligation: traits::PredicateObligation<'tcx>)
     {
-        debug!("register_predicate({})",
-               obligation.repr(self.tcx()));
+        debug!("register_predicate({:?})",
+               obligation);
         self.inh.fulfillment_cx
             .borrow_mut()
             .register_predicate_obligation(self.infcx(), obligation);
@@ -1611,18 +1625,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let t = ast_ty_to_ty(self, self, ast_t);
 
         let mut bounds_checker = wf::BoundsChecker::new(self,
-                                                        ast_t.span,
                                                         self.body_id,
                                                         None);
-        bounds_checker.check_ty(t);
+        bounds_checker.check_ty(t, ast_t.span);
 
         t
     }
 
-    pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
-        pat.repr(self.tcx())
-    }
-
     pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
         match self.inh.node_types.borrow().get(&ex.id) {
             Some(&t) => t,
@@ -1731,14 +1740,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                       cause: traits::ObligationCause<'tcx>)
     {
         let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
-        fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
+        fulfillment_cx.register_region_obligation(ty, region, cause);
     }
 
     pub fn add_default_region_param_bounds(&self,
                                            substs: &Substs<'tcx>,
                                            expr: &ast::Expr)
     {
-        for &ty in substs.types.iter() {
+        for &ty in &substs.types {
             let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
             let cause = traits::ObligationCause::new(expr.span, self.body_id,
                                                      traits::MiscObligation);
@@ -1770,14 +1779,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     {
         assert!(!predicates.has_escaping_regions());
 
-        debug!("add_obligations_for_parameters(predicates={})",
-               predicates.repr(self.tcx()));
-
-        let obligations = traits::predicates_for_generics(self.tcx(),
-                                                          cause,
-                                                          predicates);
+        debug!("add_obligations_for_parameters(predicates={:?})",
+               predicates);
 
-        obligations.map_move(|o| self.register_predicate(o));
+        for obligation in traits::predicates_for_generics(cause, predicates) {
+            self.register_predicate(obligation);
+        }
     }
 
     // Only for fields! Returns <none> for methods>
@@ -1810,11 +1817,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     fn check_casts(&self) {
         let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
-        for check in deferred_cast_checks.iter() {
-            cast::check_cast(self, check);
+        for cast in deferred_cast_checks.drain(..) {
+            cast.check(self);
         }
-
-        deferred_cast_checks.clear();
     }
 
     fn select_all_obligations_and_apply_defaults(&self) {
@@ -1871,6 +1876,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
         // RFC #599 specifies that object lifetime defaults take
         // precedence over other defaults. But within a fn body we
         // don't have a *default* region, rather we use inference to
@@ -1878,7 +1887,7 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
         // (and anyway, within a fn body the right region may not even
         // be something the user can write explicitly, since it might
         // be some expression).
-        Some(self.infcx().next_region_var(infer::MiscVariable(span)))
+        self.infcx().next_region_var(infer::MiscVariable(span))
     }
 
     fn anon_regions(&self, span: Span, count: usize)
@@ -1895,11 +1904,20 @@ pub enum LvaluePreference {
     NoPreference
 }
 
+impl LvaluePreference {
+    pub fn from_mutbl(m: ast::Mutability) -> Self {
+        match m {
+            ast::MutMutable => PreferMutLvalue,
+            ast::MutImmutable => NoPreference,
+        }
+    }
+}
+
 /// Whether `autoderef` requires types to resolve.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum UnresolvedTypeAction {
-    /// Produce an error and return `ty_err` whenever a type cannot
-    /// be resolved (i.e. it is `ty_infer`).
+    /// Produce an error and return `TyError` whenever a type cannot
+    /// be resolved (i.e. it is `TyInfer`).
     Error,
     /// Go on without emitting any errors, and return the unresolved
     /// type. Useful for probing, e.g. in coercions.
@@ -1921,9 +1939,9 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
                                  -> (Ty<'tcx>, usize, Option<T>)
     where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
 {
-    debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
-           base_ty.repr(fcx.tcx()),
-           opt_expr.repr(fcx.tcx()),
+    debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
+           base_ty,
+           opt_expr,
            lvalue_pref);
 
     let mut t = base_ty;
@@ -1983,8 +2001,8 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // We've reached the recursion limit, error gracefully.
     span_err!(fcx.tcx().sess, sp, E0055,
-        "reached the recursion limit while auto-dereferencing {}",
-        base_ty.repr(fcx.tcx()));
+        "reached the recursion limit while auto-dereferencing {:?}",
+        base_ty);
     (fcx.tcx().types.err, 0, None)
 }
 
@@ -2072,9 +2090,9 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         return final_mt;
     }
 
-    // After we have fully autoderef'd, if the resulting type is [T, ..n], then
+    // After we have fully autoderef'd, if the resulting type is [Tn], then
     // do a final unsized coercion to yield [T].
-    if let ty::ty_vec(element_ty, Some(_)) = ty.sty {
+    if let ty::TyArray(element_ty, _) = ty.sty {
         let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
         try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
                        adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
@@ -2099,20 +2117,20 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                             -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
 {
     let tcx = fcx.tcx();
-    debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, \
-                           autoderefs={}, unsize={}, index_ty={})",
-           expr.repr(tcx),
-           base_expr.repr(tcx),
-           adjusted_ty.repr(tcx),
+    debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
+                           autoderefs={}, unsize={}, index_ty={:?})",
+           expr,
+           base_expr,
+           adjusted_ty,
            autoderefs,
            unsize,
-           index_ty.repr(tcx));
+           index_ty);
 
     let input_ty = fcx.infcx().next_ty_var();
 
     // First, try built-in indexing.
     match (ty::index(adjusted_ty), &index_ty.sty) {
-        (Some(ty), &ty::ty_uint(ast::TyUs)) | (Some(ty), &ty::ty_infer(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);
@@ -2190,7 +2208,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ty::FnConverging(fcx.tcx().types.err)
     } else {
         match method_fn_ty.sty {
-            ty::ty_bare_fn(_, ref fty) => {
+            ty::TyBareFn(_, ref fty) => {
                 // HACK(eddyb) ignore self in the definition (see above).
                 let expected_arg_tys = expected_types_for_fn_args(fcx,
                                                                   sp,
@@ -2238,7 +2256,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let formal_tys = if tuple_arguments == TupleArguments {
         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
         match tuple_type.sty {
-            ty::ty_tup(ref arg_types) => {
+            ty::TyTuple(ref arg_types) => {
                 if arg_types.len() != args.len() {
                     span_err!(tcx.sess, sp, E0057,
                         "this function takes {} parameter{} but {} parameter{} supplied",
@@ -2251,7 +2269,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 } else {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
-                            ty::ty_tup(ref tys) => &**tys,
+                            ty::TyTuple(ref tys) => &**tys,
                             _ => &[]
                         },
                         None => &[]
@@ -2369,21 +2387,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::ty_float(ast::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::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
+                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::ty_uint(ast::TyU8) | ty::ty_uint(ast::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",
@@ -2433,10 +2451,10 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
-                    ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
-                    ty::ty_char => Some(tcx.types.u8),
-                    ty::ty_ptr(..) => Some(tcx.types.usize),
-                    ty::ty_bare_fn(..) => Some(tcx.types.usize),
+                    ty::TyInt(_) | ty::TyUint(_) => Some(ty),
+                    ty::TyChar => Some(tcx.types.u8),
+                    ty::TyRawPtr(..) => Some(tcx.types.usize),
+                    ty::TyBareFn(..) => Some(tcx.types.usize),
                     _ => None
                 }
             });
@@ -2447,7 +2465,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ast::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
-                    ty::ty_float(_) => Some(ty),
+                    ty::TyFloat(_) => Some(ty),
                     _ => None
                 }
             });
@@ -2585,9 +2603,9 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             None
         }
     }).unwrap_or(vec![]);
-    debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
-           formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
-           expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
+    debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
+           formal_args, formal_ret,
+           expected_args, expected_ret);
     expected_args
 }
 
@@ -2599,7 +2617,7 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// strict, _|_ can appear in the type of an expression that does not,
 /// itself, diverge: for example, fn() -> _|_.)
 /// Note that inspecting a type's structure *directly* may expose the fact
-/// that there are actually multiple representations for `ty_err`, so avoid
+/// that there are actually multiple representations for `TyError`, so avoid
 /// that when err needs to be handled differently.
 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                         expr: &'tcx ast::Expr,
@@ -2608,8 +2626,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                         unifier: F) where
     F: FnOnce(),
 {
-    debug!(">> typechecking: expr={} expected={}",
-           expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
+    debug!(">> typechecking: expr={:?} expected={:?}",
+           expr, expected);
 
     // Checks a method call.
     fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -2724,8 +2742,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                   lvalue_pref,
                                                   |base_t, _| {
                 match base_t.sty {
-                    ty::ty_struct(base_id, substs) => {
-                        debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
+                    ty::TyStruct(base_id, substs) => {
+                        debug!("struct named {:?}",  base_t);
                         let fields = ty::lookup_struct_fields(tcx, base_id);
                         fcx.lookup_field_ty(expr.span, base_id, &fields[..],
                                             field.node.name, &(*substs))
@@ -2765,7 +2783,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                             actual)
                 },
                 expr_t, None);
-            if let ty::ty_struct(did, _) = expr_t.sty {
+            if let ty::TyStruct(did, _) = expr_t.sty {
                 suggest_field_names(did, field, tcx, vec![]);
             }
         }
@@ -2826,10 +2844,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                   lvalue_pref,
                                                   |base_t, _| {
                 match base_t.sty {
-                    ty::ty_struct(base_id, substs) => {
+                    ty::TyStruct(base_id, substs) => {
                         tuple_like = ty::is_tuple_struct(tcx, base_id);
                         if tuple_like {
-                            debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
+                            debug!("tuple struct named {:?}",  base_t);
                             let fields = ty::lookup_struct_fields(tcx, base_id);
                             fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
                                                     idx.node, &(*substs))
@@ -2837,7 +2855,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                             None
                         }
                     }
-                    ty::ty_tup(ref v) => {
+                    ty::TyTuple(ref v) => {
                         tuple_like = true;
                         if idx.node < v.len() { Some(v[idx.node]) } else { None }
                     }
@@ -3116,7 +3134,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
             match unop {
                 ast::UnUniq => match ty.sty {
-                    ty::ty_uniq(ty) => {
+                    ty::TyBox(ty) => {
                         Expectation::rvalue_hint(ty)
                     }
                     _ => {
@@ -3153,26 +3171,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
                             Some(mt) => mt.ty,
                             None => {
-                                let is_newtype = match oprnd_t.sty {
-                                    ty::ty_struct(did, substs) => {
-                                        let fields = ty::struct_fields(fcx.tcx(), did, substs);
-                                        fields.len() == 1
-                                        && fields[0].name ==
-                                        token::special_idents::unnamed_field.name
-                                    }
-                                    _ => false
-                                };
-                                if is_newtype {
-                                    // This is an obsolete struct deref
-                                    span_err!(tcx.sess, expr.span, E0068,
-                                        "single-field tuple-structs can \
-                                         no longer be dereferenced");
-                                } else {
-                                    fcx.type_error_message(expr.span, |actual| {
-                                        format!("type `{}` cannot be \
-                                                dereferenced", actual)
-                                    }, oprnd_t, None);
-                                }
+                                fcx.type_error_message(expr.span, |actual| {
+                                    format!("type `{}` cannot be \
+                                            dereferenced", actual)
+                                }, oprnd_t, None);
                                 tcx.types.err
                             }
                         }
@@ -3182,7 +3184,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
-                         oprnd_t.sty == ty::ty_bool) {
+                         oprnd_t.sty == ty::TyBool) {
                         oprnd_t = op::check_user_unop(fcx, "!", "not",
                                                       tcx.lang_items.not_trait(),
                                                       expr, &**oprnd, oprnd_t, unop);
@@ -3197,7 +3199,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                       tcx.lang_items.neg_trait(),
                                                       expr, &**oprnd, oprnd_t, unop);
                     }
-                    if let ty::ty_uint(_) = oprnd_t.sty {
+                    if let ty::TyUint(_) = oprnd_t.sty {
                         if !tcx.sess.features.borrow().negate_unsigned {
                             feature_gate::emit_feature_err(
                                 &tcx.sess.parse_sess.span_diagnostic,
@@ -3214,7 +3216,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       ast::ExprAddrOf(mutbl, ref oprnd) => {
         let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
-                ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
+                ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
                     if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
                         // Lvalues may legitimately have unsized types.
                         // For example, dereferences of a fat pointer and
@@ -3227,10 +3229,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 _ => NoExpectation
             }
         });
-        let lvalue_pref = match mutbl {
-            ast::MutMutable => PreferMutLvalue,
-            ast::MutImmutable => NoPreference
-        };
+        let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
         check_expr_with_expectation_and_lvalue_pref(fcx,
                                                     &**oprnd,
                                                     hint,
@@ -3274,7 +3273,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 }
             } else {
               tcx.sess.span_bug(expr.span,
-                                &format!("unbound path {}", expr.repr(tcx)))
+                                &format!("unbound path {:?}", expr))
           };
 
           if let Some((opt_ty, segments, def)) =
@@ -3426,31 +3425,31 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         // Find the type of `e`. Supply hints based on the type we are casting to,
         // if appropriate.
-        let t_1 = fcx.to_ty(t);
-        let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
-        check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
-        let t_e = fcx.expr_ty(e);
+        let t_cast = fcx.to_ty(t);
+        let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
+        check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
+        let t_expr = fcx.expr_ty(e);
 
         // Eagerly check for some obvious errors.
-        if ty::type_is_error(t_e) {
+        if ty::type_is_error(t_expr) {
             fcx.write_error(id);
-        } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
-            report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
+        } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
+            report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
         } else {
             // Write a type for the whole expression, assuming everything is going
             // to work out Ok.
-            fcx.write_ty(id, t_1);
+            fcx.write_ty(id, t_cast);
 
             // Defer other checks until we're done type checking.
             let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
-            let cast_check = cast::CastCheck::new((**e).clone(), t_e, t_1, expr.span);
+            let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
             deferred_cast_checks.push(cast_check);
         }
       }
       ast::ExprVec(ref args) => {
         let uty = expected.to_option(fcx).and_then(|uty| {
             match uty.sty {
-                ty::ty_vec(ty, _) => Some(ty),
+                ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
                 _ => None
             }
         });
@@ -3480,7 +3479,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let uty = match expected {
             ExpectHasType(uty) => {
                 match uty.sty {
-                    ty::ty_vec(ty, _) => Some(ty),
+                    ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
                     _ => None
                 }
             }
@@ -3519,7 +3518,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       ast::ExprTup(ref elts) => {
         let flds = expected.only_has_type(fcx).and_then(|ty| {
             match ty.sty {
-                ty::ty_tup(ref flds) => Some(&flds[..]),
+                ty::TyTuple(ref flds) => Some(&flds[..]),
                 _ => None
             }
         });
@@ -3570,7 +3569,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 // Verify that this was actually a struct.
                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
                 match typ.ty.sty {
-                    ty::ty_struct(struct_did, _) => {
+                    ty::TyStruct(struct_did, _) => {
                         check_struct_constructor(fcx,
                                                  id,
                                                  expr.span,
@@ -3605,8 +3604,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                type_and_substs.ty) {
                 Ok(()) => {}
                 Err(type_error) => {
-                    let type_error_description =
-                        ty::type_err_to_str(tcx, &type_error);
                     span_err!(fcx.tcx().sess, path.span, E0235,
                                  "structure constructor specifies a \
                                          structure of type `{}`, but this \
@@ -3616,7 +3613,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                          fcx.infcx()
                                             .ty_to_string(
                                                 actual_structure_type),
-                                         type_error_description);
+                                         type_error);
                     ty::note_and_explain_type_err(tcx, &type_error, path.span);
                 }
             }
@@ -3746,9 +3743,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     debug!("type of expr({}) {} is...", expr.id,
            syntax::print::pprust::expr_to_string(expr));
-    debug!("... {}, expected is {}",
-           ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
-           expected.repr(tcx));
+    debug!("... {:?}, expected is {:?}",
+           fcx.expr_ty(expr),
+           expected);
 
     unifier();
 }
@@ -3763,8 +3760,36 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                                         &'a [ast::PathSegment],
                                                         def::Def)>
 {
+
+    // Associated constants can't depend on generic types.
+    fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                                def: def::Def,
+                                                ty: Ty<'tcx>,
+                                                span: Span,
+                                                node_id: ast::NodeId) -> bool {
+        match def {
+            def::DefAssociatedConst(..) => {
+                if ty::type_has_params(ty) || ty::type_has_self(ty) {
+                    span_err!(fcx.sess(), span, E0329,
+                              "Associated consts cannot depend \
+                               on type parameters or Self.");
+                    fcx.write_error(node_id);
+                    return true;
+                }
+            }
+            _ => {}
+        }
+        false
+    }
+
     // If fully resolved already, we don't have to do anything.
     if path_res.depth == 0 {
+        if let Some(ty) = opt_self_ty {
+            if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
+                                              span, node_id) {
+                return None;
+            }
+        }
         Some((opt_self_ty, &path.segments, path_res.base_def))
     } else {
         let mut def = path_res.base_def;
@@ -3780,6 +3805,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
         let item_name = item_segment.identifier.name;
         match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
             Ok((def, lp)) => {
+                if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
+                    return None;
+                }
                 // Write back the new resolution.
                 fcx.ccx.tcx.def_map.borrow_mut()
                        .insert(node_id, def::PathResolution {
@@ -3829,7 +3857,7 @@ impl<'tcx> Expectation<'tcx> {
     /// for examples of where this comes up,.
     fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
         match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_trait(..) => {
+            ty::TySlice(_) | ty::TyTrait(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
             _ => ExpectHasType(ty)
@@ -3876,20 +3904,6 @@ impl<'tcx> Expectation<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            NoExpectation => format!("NoExpectation"),
-            ExpectHasType(t) => format!("ExpectHasType({})",
-                                        t.repr(tcx)),
-            ExpectCastableToType(t) => format!("ExpectCastableToType({})",
-                                               t.repr(tcx)),
-            ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
-                                                  t.repr(tcx)),
-        }
-    }
-}
-
 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                        local: &'tcx ast::Local,
                                        init: &'tcx ast::Expr)
@@ -3897,9 +3911,7 @@ pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
 
     let local_ty = fcx.local_ty(init.span, local.id);
-    if !ref_bindings {
-        check_expr_coercable_to_type(fcx, init, local_ty)
-    } else {
+    if let Some(m) = ref_bindings {
         // Somewhat subtle: if we have a `ref` binding in the pattern,
         // we want to avoid introducing coercions for the RHS. This is
         // both because it helps preserve sanity and, in the case of
@@ -3908,9 +3920,11 @@ pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         // referent for the reference that results is *equal to* the
         // type of the lvalue it is referencing, and not some
         // supertype thereof.
-        check_expr(fcx, init);
+        check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
         let init_ty = fcx.expr_ty(init);
         demand::eqtype(fcx, init.span, init_ty, local_ty);
+    } else {
+        check_expr_coercable_to_type(fcx, init, local_ty)
     };
 }
 
@@ -4164,8 +4178,8 @@ pub fn check_instantiable(tcx: &ty::ctxt,
         span_err!(tcx.sess, sp, E0073,
             "this type cannot be instantiated without an \
              instance of itself");
-        fileline_help!(tcx.sess, sp, "consider using `Option<{}>`",
-            ppaux::ty_to_string(tcx, item_ty));
+        fileline_help!(tcx.sess, sp, "consider using `Option<{:?}>`",
+             item_ty);
         false
     } else {
         true
@@ -4179,7 +4193,7 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
         return;
     }
     match t.sty {
-        ty::ty_struct(did, substs) => {
+        ty::TyStruct(did, substs) => {
             let fields = ty::lookup_struct_fields(tcx, did);
             if fields.is_empty() {
                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
@@ -4356,11 +4370,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
-    debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
+    debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
            segments,
-           def.repr(fcx.tcx()),
+           def,
            node_id,
-           type_scheme.repr(fcx.tcx()));
+           type_scheme);
 
     // We need to extract the type parameters supplied by the user in
     // the path `path`. Due to the current setup, this is a bit of a
@@ -4529,7 +4543,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // provided (if any) into their appropriate spaces. We'll also report
     // errors if type parameters are provided in an inappropriate place.
     let mut substs = Substs::empty();
-    for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
+    for (opt_space, segment) in segment_spaces.iter().zip(segments) {
         match *opt_space {
             None => {
                 check_path_args(fcx.tcx(), slice::ref_slice(segment),
@@ -4600,9 +4614,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
             fcx.tcx().sess.span_bug(span,
             &format!(
-                "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
-                self_ty.repr(fcx.tcx()),
-                impl_ty.repr(fcx.tcx())));
+                "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
+                self_ty,
+                impl_ty));
         }
     }
 
@@ -4661,9 +4675,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 } else if i == type_count {
                     span_err!(fcx.tcx().sess, typ.span, E0087,
                         "too many type parameters provided: \
-                         expected at most {} parameter(s), \
-                         found {} parameter(s)",
-                         type_count, data.types.len());
+                         expected at most {} parameter{}, \
+                         found {} parameter{}",
+                         type_count,
+                         if type_count == 1 {""} else {"s"},
+                         data.types.len(),
+                         if data.types.len() == 1 {""} else {"s"});
                     substs.types.truncate(space, 0);
                     break;
                 }
@@ -4686,9 +4703,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 } else if i == region_count {
                     span_err!(fcx.tcx().sess, lifetime.span, E0088,
                         "too many lifetime parameters provided: \
-                         expected {} parameter(s), found {} parameter(s)",
+                         expected {} parameter{}, found {} parameter{}",
                         region_count,
-                        data.lifetimes.len());
+                        if region_count == 1 {""} else {"s"},
+                        data.lifetimes.len(),
+                        if data.lifetimes.len() == 1 {""} else {"s"});
                     substs.mut_regions().truncate(space, 0);
                     break;
                 }
@@ -4778,9 +4797,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let qualifier =
                 if desired.len() != required_len { "at least " } else { "" };
             span_err!(fcx.tcx().sess, span, E0089,
-                "too few type parameters provided: expected {}{} parameter(s) \
-                , found {} parameter(s)",
-                qualifier, required_len, provided_len);
+                "too few type parameters provided: expected {}{} parameter{}, \
+                 found {} parameter{}",
+                qualifier, required_len,
+                if required_len == 1 {""} else {"s"},
+                provided_len,
+                if provided_len == 1 {""} else {"s"});
             substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
             return;
         }
@@ -4799,7 +4821,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
         assert_eq!(substs.types.len(space), desired.len());
 
-        debug!("Final substs: {}", substs.repr(fcx.tcx()));
+        debug!("Final substs: {:?}", substs);
     }
 
     fn adjust_region_parameters(
@@ -4831,9 +4853,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         // Otherwise, too few were provided. Report an error and then
         // use inference variables.
         span_err!(fcx.tcx().sess, span, E0090,
-            "too few lifetime parameters provided: expected {} parameter(s), \
-             found {} parameter(s)",
-            desired.len(), provided_len);
+            "too few lifetime parameters provided: expected {} parameter{}, \
+             found {} parameter{}",
+            desired.len(),
+            if desired.len() == 1 {""} else {"s"},
+            provided_len,
+            if provided_len == 1 {""} else {"s"});
 
         substs.mut_regions().replace(
             space,
@@ -4905,8 +4930,8 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                        span: Span,
                                        tps: &OwnedSlice<ast::TyParam>,
                                        ty: Ty<'tcx>) {
-    debug!("check_bounds_are_used(n_tps={}, ty={})",
-           tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
+    debug!("check_bounds_are_used(n_tps={}, ty={:?})",
+           tps.len(),  ty);
 
     // make a vector of booleans initially false, set to true when used
     if tps.is_empty() { return; }
@@ -4914,7 +4939,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     ty::walk_ty(ty, |t| {
             match t.sty {
-                ty::ty_param(ParamTy {idx, ..}) => {
+                ty::TyParam(ParamTy {idx, ..}) => {
                     debug!("Found use of ty param num {}", idx);
                     tps_used[idx as usize] = true;
                 }
@@ -5009,7 +5034,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
                                                              ast::MutImmutable)),
             "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
-            "offset" => {
+            "offset" | "arith_offset" => {
               (1,
                vec!(
                   ty::mk_ptr(tcx, ty::mt {
@@ -5229,7 +5254,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                            fty,
                            || {
                 format!("intrinsic has wrong type: expected `{}`",
-                        ppaux::ty_to_string(ccx.tcx, fty))
+                         fty)
             });
     }
 }
index b4000788d1998db97ce0b5c197782efca7f6529e..a5e4e0fab5963795012ea8be23f324817368e787 100644 (file)
@@ -25,7 +25,6 @@ use middle::ty::{self, Ty};
 use syntax::ast;
 use syntax::ast_util;
 use syntax::parse::token;
-use util::ppaux::{Repr, UserString};
 
 /// Check a `a <op>= b`
 pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
@@ -51,8 +50,8 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         span_err!(tcx.sess, lhs_expr.span, E0368,
                   "binary assignment operation `{}=` cannot be applied to types `{}` and `{}`",
                   ast_util::binop_to_string(op.node),
-                  lhs_ty.user_string(fcx.tcx()),
-                  rhs_ty.user_string(fcx.tcx()));
+                  lhs_ty,
+                  rhs_ty);
         fcx.write_error(expr.id);
     }
 
@@ -73,12 +72,12 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     let tcx = fcx.ccx.tcx;
 
-    debug!("check_binop(expr.id={}, expr={}, op={:?}, lhs_expr={}, rhs_expr={})",
+    debug!("check_binop(expr.id={}, expr={:?}, op={:?}, lhs_expr={:?}, rhs_expr={:?})",
            expr.id,
-           expr.repr(tcx),
+           expr,
            op,
-           lhs_expr.repr(tcx),
-           rhs_expr.repr(tcx));
+           lhs_expr,
+           rhs_expr);
 
     check_expr(fcx, lhs_expr);
     let lhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr));
@@ -180,16 +179,16 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             // if this is simd, result is same as lhs, else bool
             if ty::type_is_simd(tcx, lhs_ty) {
                 let unit_ty = ty::simd_type(tcx, lhs_ty);
-                debug!("enforce_builtin_binop_types: lhs_ty={} unit_ty={}",
-                       lhs_ty.repr(tcx),
-                       unit_ty.repr(tcx));
+                debug!("enforce_builtin_binop_types: lhs_ty={:?} unit_ty={:?}",
+                       lhs_ty,
+                       unit_ty);
                 if !ty::type_is_integral(unit_ty) {
                     tcx.sess.span_err(
                         lhs_expr.span,
                         &format!("binary comparison operation `{}` not supported \
                                   for floating point SIMD vector `{}`",
                                  ast_util::binop_to_string(op.node),
-                                 lhs_ty.user_string(tcx)));
+                                 lhs_ty));
                     tcx.types.err
                 } else {
                     lhs_ty
@@ -209,9 +208,9 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                     op: ast::BinOp)
                                     -> (Ty<'tcx>, Ty<'tcx>)
 {
-    debug!("check_overloaded_binop(expr.id={}, lhs_ty={})",
+    debug!("check_overloaded_binop(expr.id={}, lhs_ty={:?})",
            expr.id,
-           lhs_ty.repr(fcx.tcx()));
+           lhs_ty);
 
     let (name, trait_def_id) = name_and_trait_def_id(fcx, op);
 
@@ -233,7 +232,7 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
                           "binary operation `{}` cannot be applied to type `{}`",
                           ast_util::binop_to_string(op.node),
-                          lhs_ty.user_string(fcx.tcx()));
+                          lhs_ty);
             }
             fcx.tcx().types.err
         }
@@ -304,12 +303,12 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
                               lhs_expr: &'a ast::Expr)
                               -> Result<Ty<'tcx>,()>
 {
-    debug!("lookup_op_method(expr={}, lhs_ty={}, opname={:?}, trait_did={}, lhs_expr={})",
-           expr.repr(fcx.tcx()),
-           lhs_ty.repr(fcx.tcx()),
+    debug!("lookup_op_method(expr={:?}, lhs_ty={:?}, opname={:?}, trait_did={:?}, lhs_expr={:?})",
+           expr,
+           lhs_ty,
            opname,
-           trait_did.repr(fcx.tcx()),
-           lhs_expr.repr(fcx.tcx()));
+           trait_did,
+           lhs_expr);
 
     let method = match trait_did {
         Some(trait_did) => {
index 090d111b62b898dde6acc1007c92c4ca647fddae..a96e7864fe679c8a4d63e69d16c8e79e4100f48c 100644 (file)
@@ -76,7 +76,7 @@
 //! the borrow itself (L2).  What do I mean by "guaranteed" by a
 //! borrowed pointer? I mean any data that is reached by first
 //! dereferencing a borrowed pointer and then either traversing
-//! interior offsets or owned pointers.  We say that the guarantor
+//! interior offsets or boxes.  We say that the guarantor
 //! of such data it 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
@@ -94,7 +94,6 @@ use middle::traits;
 use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall};
 use middle::infer::{self, GenericKind};
 use middle::pat_util;
-use util::ppaux::{ty_to_string, Repr};
 
 use std::mem;
 use syntax::{ast, ast_util};
@@ -321,8 +320,8 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
                                        .to_vec();
 
         for r_o in &region_obligations {
-            debug!("visit_region_obligations: r_o={}",
-                   r_o.repr(self.tcx()));
+            debug!("visit_region_obligations: r_o={:?}",
+                   r_o);
             let sup_type = self.resolve_type(r_o.sup_type);
             let origin = infer::RelateParamBound(r_o.cause.span, sup_type);
             type_must_outlive(self, origin, sup_type, r_o.sub_region);
@@ -348,24 +347,23 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
                            body_id: ast::NodeId,
                            span: Span) {
         debug!("relate_free_regions >>");
-        let tcx = self.tcx();
 
         for &ty in fn_sig_tys {
             let ty = self.resolve_type(ty);
-            debug!("relate_free_regions(t={})", ty.repr(tcx));
+            debug!("relate_free_regions(t={:?})", ty);
             let body_scope = CodeExtent::from_node_id(body_id);
             let body_scope = ty::ReScope(body_scope);
             let implications = implicator::implications(self.fcx.infcx(), self.fcx, body_id,
                                                         ty, body_scope, span);
 
             // Record any relations between free regions that we observe into the free-region-map.
-            self.free_region_map.relate_free_regions_from_implications(tcx, &implications);
+            self.free_region_map.relate_free_regions_from_implications(&implications);
 
             // But also record other relationships, such as `T:'x`,
             // that don't go into the free-region-map but which we use
             // here.
             for implication in implications {
-                debug!("implication: {}", implication.repr(tcx));
+                debug!("implication: {:?}", implication);
                 match implication {
                     implicator::Implication::RegionSubRegion(_,
                                                              ty::ReFree(free_a),
@@ -373,8 +371,8 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
                         self.fcx.inh.infcx.add_given(free_a, vid_b);
                     }
                     implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => {
-                        debug!("RegionSubGeneric: {} <= {}",
-                               r_a.repr(tcx), generic_b.repr(tcx));
+                        debug!("RegionSubGeneric: {:?} <= {:?}",
+                               r_a, generic_b);
 
                         self.region_bound_pairs.push((r_a, generic_b.clone()));
                     }
@@ -465,7 +463,7 @@ fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
 
 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
     let tcx = rcx.fcx.tcx();
-    debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
+    debug!("regionck::visit_pat(pat={:?})", pat);
     pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
         // If we have a variable that contains region'd data, that
         // data will be accessible from anywhere that the variable is
@@ -502,8 +500,8 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
 }
 
 fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
-    debug!("regionck::visit_expr(e={}, repeating_scope={})",
-           expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
+    debug!("regionck::visit_expr(e={:?}, repeating_scope={})",
+           expr, rcx.repeating_scope);
 
     // No matter what, the type of each expression must outlive the
     // scope of that expression. This also guarantees basic WF.
@@ -637,7 +635,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             // outlive the operation you are performing.
             let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs);
             let rhs_ty = rcx.resolve_expr_type_adjusted(&**rhs);
-            for &ty in [lhs_ty, rhs_ty].iter() {
+            for &ty in &[lhs_ty, rhs_ty] {
                 type_must_outlive(rcx,
                                   infer::Operand(expr.span),
                                   ty,
@@ -669,7 +667,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                 }
                 None => rcx.resolve_node_type(base.id)
             };
-            if let ty::ty_rptr(r_ptr, _) = base_ty.sty {
+            if let ty::TyRef(r_ptr, _) = base_ty.sty {
                 mk_subregion_due_to_dereference(
                     rcx, expr.span, ty::ReScope(CodeExtent::from_node_id(expr.id)), *r_ptr);
             }
@@ -745,9 +743,9 @@ fn constrain_cast(rcx: &mut Rcx,
                   cast_expr: &ast::Expr,
                   source_expr: &ast::Expr)
 {
-    debug!("constrain_cast(cast_expr={}, source_expr={})",
-           cast_expr.repr(rcx.tcx()),
-           source_expr.repr(rcx.tcx()));
+    debug!("constrain_cast(cast_expr={:?}, source_expr={:?})",
+           cast_expr,
+           source_expr);
 
     let source_ty = rcx.resolve_node_type(source_expr.id);
     let target_ty = rcx.resolve_node_type(cast_expr.id);
@@ -758,27 +756,27 @@ fn constrain_cast(rcx: &mut Rcx,
                            cast_expr: &ast::Expr,
                            from_ty: Ty<'tcx>,
                            to_ty: Ty<'tcx>) {
-        debug!("walk_cast(from_ty={}, to_ty={})",
-               from_ty.repr(rcx.tcx()),
-               to_ty.repr(rcx.tcx()));
+        debug!("walk_cast(from_ty={:?}, to_ty={:?})",
+               from_ty,
+               to_ty);
         match (&from_ty.sty, &to_ty.sty) {
-            /*From:*/ (&ty::ty_rptr(from_r, ref from_mt),
-            /*To:  */  &ty::ty_rptr(to_r, ref to_mt)) => {
+            /*From:*/ (&ty::TyRef(from_r, ref from_mt),
+            /*To:  */  &ty::TyRef(to_r, ref to_mt)) => {
                 // Target cannot outlive source, naturally.
                 rcx.fcx.mk_subr(infer::Reborrow(cast_expr.span), *to_r, *from_r);
                 walk_cast(rcx, cast_expr, from_mt.ty, to_mt.ty);
             }
 
             /*From:*/ (_,
-            /*To:  */  &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => {
+            /*To:  */  &ty::TyTrait(box ty::TraitTy { ref bounds, .. })) => {
                 // When T is existentially quantified as a trait
                 // `Foo+'to`, it must outlive the region bound `'to`.
                 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
                                   from_ty, bounds.region_bound);
             }
 
-            /*From:*/ (&ty::ty_uniq(from_referent_ty),
-            /*To:  */  &ty::ty_uniq(to_referent_ty)) => {
+            /*From:*/ (&ty::TyBox(from_referent_ty),
+            /*To:  */  &ty::TyBox(to_referent_ty)) => {
                 walk_cast(rcx, cast_expr, from_referent_ty, to_referent_ty);
             }
 
@@ -801,14 +799,14 @@ fn constrain_callee(rcx: &mut Rcx,
                     _callee_expr: &ast::Expr) {
     let callee_ty = rcx.resolve_node_type(callee_id);
     match callee_ty.sty {
-        ty::ty_bare_fn(..) => { }
+        ty::TyBareFn(..) => { }
         _ => {
             // this should not happen, but it does if the program is
             // erroneous
             //
             // tcx.sess.span_bug(
             //     callee_expr.span,
-            //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
+            //     format!("Calling non-function: {}", callee_ty));
         }
     }
 }
@@ -823,12 +821,11 @@ fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
     //! in the type of the function. Also constrains the regions that
     //! appear in the arguments appropriately.
 
-    let tcx = rcx.fcx.tcx();
-    debug!("constrain_call(call_expr={}, \
-            receiver={}, \
+    debug!("constrain_call(call_expr={:?}, \
+            receiver={:?}, \
             implicitly_ref_args={})",
-            call_expr.repr(tcx),
-            receiver.repr(tcx),
+            call_expr,
+            receiver,
             implicitly_ref_args);
 
     // `callee_region` is the scope representing the time in which the
@@ -838,10 +835,10 @@ fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
     let callee_scope = CodeExtent::from_node_id(call_expr.id);
     let callee_region = ty::ReScope(callee_scope);
 
-    debug!("callee_region={}", callee_region.repr(tcx));
+    debug!("callee_region={:?}", callee_region);
 
     for arg_expr in arg_exprs {
-        debug!("Argument: {}", arg_expr.repr(tcx));
+        debug!("Argument: {:?}", arg_expr);
 
         // ensure that any regions appearing in the argument type are
         // valid for at least the lifetime of the function:
@@ -860,7 +857,7 @@ fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
 
     // as loop above, but for receiver
     if let Some(r) = receiver {
-        debug!("receiver: {}", r.repr(tcx));
+        debug!("receiver: {:?}", r);
         type_of_node_must_outlive(
             rcx, infer::CallRcvr(r.span),
             r.id, callee_region);
@@ -877,10 +874,10 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                   derefs: usize,
                                   mut derefd_ty: Ty<'tcx>)
 {
-    debug!("constrain_autoderefs(deref_expr={}, derefs={}, derefd_ty={})",
-           deref_expr.repr(rcx.tcx()),
+    debug!("constrain_autoderefs(deref_expr={:?}, derefs={}, derefd_ty={:?})",
+           deref_expr,
            derefs,
-           derefd_ty.repr(rcx.tcx()));
+           derefd_ty);
 
     let r_deref_expr = ty::ReScope(CodeExtent::from_node_id(deref_expr.id));
     for i in 0..derefs {
@@ -889,8 +886,8 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
 
         derefd_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) {
             Some(method) => {
-                debug!("constrain_autoderefs: #{} is overloaded, method={}",
-                       i, method.repr(rcx.tcx()));
+                debug!("constrain_autoderefs: #{} is overloaded, method={:?}",
+                       i, method);
 
                 // Treat overloaded autoderefs as if an AutoRef adjustment
                 // was applied on the base type, as that is always the case.
@@ -899,23 +896,23 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                     ty::no_late_bound_regions(rcx.tcx(), fn_sig).unwrap();
                 let self_ty = fn_sig.inputs[0];
                 let (m, r) = match self_ty.sty {
-                    ty::ty_rptr(r, ref m) => (m.mutbl, r),
+                    ty::TyRef(r, ref m) => (m.mutbl, r),
                     _ => {
                         rcx.tcx().sess.span_bug(
                             deref_expr.span,
-                            &format!("bad overloaded deref type {}",
-                                     method.ty.repr(rcx.tcx())))
+                            &format!("bad overloaded deref type {:?}",
+                                     method.ty))
                     }
                 };
 
                 debug!("constrain_autoderefs: receiver r={:?} m={:?}",
-                       r.repr(rcx.tcx()), m);
+                       r, m);
 
                 {
                     let mc = mc::MemCategorizationContext::new(rcx.fcx);
                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
                     debug!("constrain_autoderefs: self_cmt={:?}",
-                           self_cmt.repr(rcx.tcx()));
+                           self_cmt);
                     link_region(rcx, deref_expr.span, r,
                                 ty::BorrowKind::from_mutbl(m), self_cmt);
                 }
@@ -935,7 +932,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
             None => derefd_ty
         };
 
-        if let ty::ty_rptr(r_ptr, _) =  derefd_ty.sty {
+        if let ty::TyRef(r_ptr, _) =  derefd_ty.sty {
             mk_subregion_due_to_dereference(rcx, deref_expr.span,
                                             r_deref_expr, *r_ptr);
         }
@@ -976,8 +973,8 @@ fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 't
                        .sess
                        .span_bug(span,
                                  &format!("unexpected rvalue region in rvalue \
-                                           destructor safety checking: `{}`",
-                                          region.repr(rcx.tcx())));
+                                           destructor safety checking: `{:?}`",
+                                          region));
                 }
             }
         }
@@ -995,9 +992,9 @@ fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
            rcx.fcx.infcx().ty_to_string(indexed_ty));
 
     let r_index_expr = ty::ReScope(CodeExtent::from_node_id(index_expr.id));
-    if let ty::ty_rptr(r_ptr, mt) = indexed_ty.sty {
+    if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
         match mt.ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => {
+            ty::TySlice(_) | ty::TyStr => {
                 rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span),
                                 r_index_expr, *r_ptr);
             }
@@ -1025,7 +1022,7 @@ fn type_of_node_must_outlive<'a, 'tcx>(
                            |method_call| rcx.resolve_method_type(method_call));
     debug!("constrain_regions_in_type_of_node(\
             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
-           ty_to_string(tcx, ty), ty_to_string(tcx, ty0),
+            ty,  ty0,
            id, minimum_lifetime);
     type_must_outlive(rcx, origin, ty, minimum_lifetime);
 }
@@ -1034,14 +1031,14 @@ fn type_of_node_must_outlive<'a, 'tcx>(
 /// resulting pointer is linked to the lifetime of its guarantor (if any).
 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
                 mutability: ast::Mutability, base: &ast::Expr) {
-    debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx()));
+    debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
 
     let cmt = {
         let mc = mc::MemCategorizationContext::new(rcx.fcx);
         ignore_err!(mc.cat_expr(base))
     };
 
-    debug!("link_addr_of: cmt={}", cmt.repr(rcx.tcx()));
+    debug!("link_addr_of: cmt={:?}", cmt);
 
     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 }
@@ -1067,7 +1064,7 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
     debug!("regionck::for_match()");
     let mc = mc::MemCategorizationContext::new(rcx.fcx);
     let discr_cmt = ignore_err!(mc.cat_expr(discr));
-    debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
+    debug!("discr_cmt={:?}", discr_cmt);
     for arm in arms {
         for root_pat in &arm.pats {
             link_pattern(rcx, mc, discr_cmt.clone(), &**root_pat);
@@ -1085,9 +1082,9 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::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={}",
-               arg_ty.repr(rcx.tcx()),
-               arg_cmt.repr(rcx.tcx()));
+        debug!("arg_ty={:?} arg_cmt={:?}",
+               arg_ty,
+               arg_cmt);
         link_pattern(rcx, mc, arg_cmt, &*arg.pat);
     }
 }
@@ -1098,9 +1095,9 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                           mc: mc::MemCategorizationContext<FnCtxt<'a, 'tcx>>,
                           discr_cmt: mc::cmt<'tcx>,
                           root_pat: &ast::Pat) {
-    debug!("link_pattern(discr_cmt={}, root_pat={})",
-           discr_cmt.repr(rcx.tcx()),
-           root_pat.repr(rcx.tcx()));
+    debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
+           discr_cmt,
+           root_pat);
     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
             match sub_pat.node {
                 // `ref x` pattern
@@ -1136,7 +1133,7 @@ fn link_autoref(rcx: &Rcx,
     debug!("link_autoref(autoref={:?})", autoref);
     let mc = mc::MemCategorizationContext::new(rcx.fcx);
     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
-    debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
+    debug!("expr_cmt={:?}", expr_cmt);
 
     match *autoref {
         ty::AutoPtr(r, m) => {
@@ -1156,9 +1153,8 @@ fn link_autoref(rcx: &Rcx,
 fn link_by_ref(rcx: &Rcx,
                expr: &ast::Expr,
                callee_scope: CodeExtent) {
-    let tcx = rcx.tcx();
-    debug!("link_by_ref(expr={}, callee_scope={:?})",
-           expr.repr(tcx), callee_scope);
+    debug!("link_by_ref(expr={:?}, callee_scope={:?})",
+           expr, callee_scope);
     let mc = mc::MemCategorizationContext::new(rcx.fcx);
     let expr_cmt = ignore_err!(mc.cat_expr(expr));
     let borrow_region = ty::ReScope(callee_scope);
@@ -1172,13 +1168,13 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                                         id: ast::NodeId,
                                         mutbl: ast::Mutability,
                                         cmt_borrowed: mc::cmt<'tcx>) {
-    debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={})",
-           id, mutbl, cmt_borrowed.repr(rcx.tcx()));
+    debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
+           id, mutbl, cmt_borrowed);
 
     let rptr_ty = rcx.resolve_node_type(id);
     if !ty::type_is_error(rptr_ty) {
         let tcx = rcx.fcx.ccx.tcx;
-        debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
+        debug!("rptr_ty={}",  rptr_ty);
         let r = ty::ty_region(tcx, span, rptr_ty);
         link_region(rcx, span, &r, ty::BorrowKind::from_mutbl(mutbl),
                     cmt_borrowed);
@@ -1197,10 +1193,10 @@ fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     let mut borrow_kind = borrow_kind;
 
     loop {
-        debug!("link_region(borrow_region={}, borrow_kind={}, borrow_cmt={})",
-               borrow_region.repr(rcx.tcx()),
-               borrow_kind.repr(rcx.tcx()),
-               borrow_cmt.repr(rcx.tcx()));
+        debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
+               borrow_region,
+               borrow_kind,
+               borrow_cmt);
         match borrow_cmt.cat.clone() {
             mc::cat_deref(ref_cmt, _,
                           mc::Implicit(ref_kind, ref_region)) |
@@ -1310,8 +1306,8 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                 _ => {
                     rcx.tcx().sess.span_bug(
                         span,
-                        &format!("Illegal upvar id: {}",
-                                upvar_id.repr(rcx.tcx())));
+                        &format!("Illegal upvar id: {:?}",
+                                upvar_id));
                 }
             }
         }
@@ -1326,9 +1322,9 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
         }
     };
 
-    debug!("link_reborrowed_region: {} <= {}",
-           borrow_region.repr(rcx.tcx()),
-           ref_region.repr(rcx.tcx()));
+    debug!("link_reborrowed_region: {:?} <= {:?}",
+           borrow_region,
+           ref_region);
     rcx.fcx.mk_subr(cause, *borrow_region, ref_region);
 
     // If we end up needing to recurse and establish a region link
@@ -1401,14 +1397,14 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                ty: Ty<'tcx>,
                                region: ty::Region)
 {
-    debug!("type_must_outlive(ty={}, region={})",
-           ty.repr(rcx.tcx()),
-           region.repr(rcx.tcx()));
+    debug!("type_must_outlive(ty={:?}, region={:?})",
+           ty,
+           region);
 
     let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx, rcx.body_id,
                                                 ty, region, origin.span());
     for implication in implications {
-        debug!("implication: {}", implication.repr(rcx.tcx()));
+        debug!("implication: {:?}", implication);
         match implication {
             implicator::Implication::RegionSubRegion(None, r_a, r_b) => {
                 rcx.fcx.mk_subr(origin.clone(), r_a, r_b);
@@ -1443,8 +1439,8 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                   region: ty::Region,
                                   def_id: ast::DefId,
                                   substs: &'tcx Substs<'tcx>) {
-    debug!("closure_must_outlive(region={}, def_id={}, substs={})",
-           region.repr(rcx.tcx()), def_id.repr(rcx.tcx()), substs.repr(rcx.tcx()));
+    debug!("closure_must_outlive(region={:?}, def_id={:?}, substs={:?})",
+           region, def_id, substs);
 
     let upvars = rcx.fcx.closure_upvars(def_id, substs).unwrap();
     for upvar in upvars {
@@ -1461,9 +1457,9 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                                   generic: &GenericKind<'tcx>) {
     let param_env = &rcx.fcx.inh.param_env;
 
-    debug!("param_must_outlive(region={}, generic={})",
-           region.repr(rcx.tcx()),
-           generic.repr(rcx.tcx()));
+    debug!("param_must_outlive(region={:?}, generic={:?})",
+           region,
+           generic);
 
     // To start, collect bounds from user:
     let mut param_bounds =
@@ -1496,9 +1492,9 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     // well-formed, then, A must be lower-generic by `'a`, but we
     // don't know that this holds from first principles.
     for &(ref r, ref p) in &rcx.region_bound_pairs {
-        debug!("generic={} p={}",
-               generic.repr(rcx.tcx()),
-               p.repr(rcx.tcx()));
+        debug!("generic={:?} p={:?}",
+               generic,
+               p);
         if generic == p {
             param_bounds.push(*r);
         }
@@ -1521,8 +1517,8 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
     let tcx = fcx.tcx();
     let infcx = fcx.infcx();
 
-    debug!("projection_bounds(projection_ty={})",
-           projection_ty.repr(tcx));
+    debug!("projection_bounds(projection_ty={:?})",
+           projection_ty);
 
     let ty = ty::mk_projection(tcx, projection_ty.trait_ref.clone(), projection_ty.item_name);
 
@@ -1546,16 +1542,16 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
                 _ => { return None; }
             };
 
-            debug!("projection_bounds: outlives={} (1)",
-                   outlives.repr(tcx));
+            debug!("projection_bounds: outlives={:?} (1)",
+                   outlives);
 
             // apply the substitutions (and normalize any projected types)
             let outlives = fcx.instantiate_type_scheme(span,
                                                        projection_ty.trait_ref.substs,
                                                        &outlives);
 
-            debug!("projection_bounds: outlives={} (2)",
-                   outlives.repr(tcx));
+            debug!("projection_bounds: outlives={:?} (2)",
+                   outlives);
 
             let region_result = infcx.commit_if_ok(|_| {
                 let (outlives, _) =
@@ -1564,8 +1560,8 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
                         infer::AssocTypeProjection(projection_ty.item_name),
                         &outlives);
 
-                debug!("projection_bounds: outlives={} (3)",
-                       outlives.repr(tcx));
+                debug!("projection_bounds: outlives={:?} (3)",
+                       outlives);
 
                 // check whether this predicate applies to our current projection
                 match infer::mk_eqty(infcx, false, infer::Misc(span), ty, outlives.0) {
@@ -1574,8 +1570,8 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
                 }
             });
 
-            debug!("projection_bounds: region_result={}",
-                   region_result.repr(tcx));
+            debug!("projection_bounds: region_result={:?}",
+                   region_result);
 
             region_result.ok()
         })
index 340cca7d47e7a395619bb5ae60ce9d1724e800a6..99e6309918c9728860f23de91cd4efafc41b10ab 100644 (file)
@@ -51,7 +51,6 @@ use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::visit::{self, Visitor};
-use util::ppaux::Repr;
 
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
@@ -133,8 +132,8 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
         if !self.fcx.inh.closure_kinds.borrow().contains_key(&closure_def_id) {
             self.closures_with_inferred_kinds.insert(expr.id);
             self.fcx.inh.closure_kinds.borrow_mut().insert(closure_def_id, ty::FnClosureKind);
-            debug!("check_closure: adding closure_id={} to closures_with_inferred_kinds",
-                   closure_def_id.repr(self.tcx()));
+            debug!("check_closure: adding closure_id={:?} to closures_with_inferred_kinds",
+                   closure_def_id);
         }
 
         ty::with_freevars(self.tcx(), expr.id, |freevars| {
@@ -178,10 +177,6 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
         AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds }
     }
 
-    fn tcx(&self) -> &'a ty::ctxt<'tcx> {
-        self.fcx.tcx()
-    }
-
     fn analyze_closure(&mut self, id: ast::NodeId, decl: &ast::FnDecl, body: &ast::Block) {
         /*!
          * Analysis starting point.
@@ -235,7 +230,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
         if self.closures_with_inferred_kinds.contains(&id) {
             let mut deferred_call_resolutions =
                 self.fcx.remove_deferred_call_resolutions(closure_def_id);
-            for deferred_call_resolution in deferred_call_resolutions.iter_mut() {
+            for deferred_call_resolution in &mut deferred_call_resolutions {
                 deferred_call_resolution.resolve(self.fcx);
             }
         }
@@ -245,8 +240,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
                                             cmt: mc::cmt<'tcx>,
                                             mode: euv::ConsumeMode)
     {
-        debug!("adjust_upvar_borrow_kind_for_consume(cmt={}, mode={:?})",
-               cmt.repr(self.tcx()), mode);
+        debug!("adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
+               cmt, mode);
 
         // we only care about moves
         match mode {
@@ -258,8 +253,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
         // for that to be legal, the upvar would have to be borrowed
         // by value instead
         let guarantor = cmt.guarantor();
-        debug!("adjust_upvar_borrow_kind_for_consume: guarantor={}",
-               guarantor.repr(self.tcx()));
+        debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
+               guarantor);
         match guarantor.cat {
             mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
             mc::cat_deref(_, _, mc::Implicit(..)) => {
@@ -296,8 +291,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
     /// to). If cmt contains any by-ref upvars, this implies that
     /// those upvars must be borrowed using an `&mut` borrow.
     fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
-        debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
-               cmt.repr(self.tcx()));
+        debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})",
+               cmt);
 
         match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::Unique) |
@@ -330,8 +325,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
     }
 
     fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) {
-        debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
-               cmt.repr(self.tcx()));
+        debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})",
+               cmt);
 
         match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::Unique) |
@@ -498,7 +493,7 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
                cmt: mc::cmt<'tcx>,
                mode: euv::ConsumeMode)
     {
-        debug!("consume(cmt={},mode={:?})", cmt.repr(self.tcx()), mode);
+        debug!("consume(cmt={:?},mode={:?})", cmt, mode);
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
 
@@ -513,7 +508,7 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode)
     {
-        debug!("consume_pat(cmt={},mode={:?})", cmt.repr(self.tcx()), mode);
+        debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
 
@@ -525,8 +520,8 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
               bk: ty::BorrowKind,
               _loan_cause: euv::LoanCause)
     {
-        debug!("borrow(borrow_id={}, cmt={}, bk={:?})",
-               borrow_id, cmt.repr(self.tcx()), bk);
+        debug!("borrow(borrow_id={}, cmt={:?}, bk={:?})",
+               borrow_id, cmt, bk);
 
         match bk {
             ty::ImmBorrow => { }
@@ -550,8 +545,8 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
               assignee_cmt: mc::cmt<'tcx>,
               _mode: euv::MutateMode)
     {
-        debug!("mutate(assignee_cmt={})",
-               assignee_cmt.repr(self.tcx()));
+        debug!("mutate(assignee_cmt={:?})",
+               assignee_cmt);
 
         self.adjust_upvar_borrow_kind_for_mut(assignee_cmt);
     }
index 79736c08f37967bb4a6cdf09d09b0362129c371f..c048845892c4b7f1d364958bdc65526647da6d35 100644 (file)
@@ -18,12 +18,11 @@ use middle::traits;
 use middle::ty::{self, Ty};
 use middle::ty::liberate_late_bound_regions;
 use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
-use util::ppaux::{Repr, UserString};
 
 use std::collections::HashSet;
 use syntax::ast;
 use syntax::ast_util::local_def;
-use syntax::codemap::Span;
+use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::{self, special_idents};
 use syntax::visit;
 use syntax::visit::Visitor;
@@ -81,7 +80,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 self.check_impl(item);
             }
             ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
-                let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
+                let trait_ref = ty::impl_trait_ref(ccx.tcx,
+                                                   local_def(item.id)).unwrap();
                 ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
@@ -123,10 +123,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
                 if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) {
                     if !items.is_empty() {
-                        ccx.tcx.sess.span_err(
-                            item.span,
-                            "traits with default impls (`e.g. unsafe impl Trait for ..`) must \
-                            have no methods or associated items")
+                        span_err!(ccx.tcx.sess, item.span, E0380,
+                                  "traits with default impls (`e.g. unsafe impl \
+                                  Trait for ..`) must have no methods or associated items")
                     }
                 }
             }
@@ -162,15 +161,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         self.with_fcx(item, |this, fcx| {
             let variants = lookup_fields(fcx);
             let mut bounds_checker = BoundsChecker::new(fcx,
-                                                        item.span,
                                                         item.id,
                                                         Some(&mut this.cache));
             debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope);
 
-             for variant in &variants {
+            for variant in &variants {
                 for field in &variant.fields {
                     // Regions are checked below.
-                    bounds_checker.check_traits_in_ty(field.ty);
+                    bounds_checker.check_traits_in_ty(field.ty, field.span);
                 }
 
                 // For DST, all intermediate types must be sized.
@@ -199,7 +197,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     {
         self.with_fcx(item, |this, fcx| {
             let mut bounds_checker = BoundsChecker::new(fcx,
-                                                        item.span,
                                                         item.id,
                                                         Some(&mut this.cache));
             debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
@@ -209,7 +206,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                                       &fcx.inh.param_env.free_substs,
                                                       &type_scheme.ty);
 
-            bounds_checker.check_traits_in_ty(item_ty);
+            bounds_checker.check_traits_in_ty(item_ty, item.span);
         });
     }
 
@@ -218,7 +215,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     {
         self.with_fcx(item, |this, fcx| {
             let mut bounds_checker = BoundsChecker::new(fcx,
-                                                        item.span,
                                                         item.id,
                                                         Some(&mut this.cache));
             debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope);
@@ -231,7 +227,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                                       &fcx.inh.param_env.free_substs,
                                                       &self_ty);
 
-            bounds_checker.check_traits_in_ty(self_ty);
+            bounds_checker.check_traits_in_ty(self_ty, item.span);
 
             // Similarly, obtain an "inside" reference to the trait
             // that the impl implements.
@@ -252,7 +248,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             // trait reference. Instead, this is done at the impl site.
             // Arguably this is wrong and we should treat the trait-reference
             // the same way as we treat the self-type.
-            bounds_checker.check_trait_ref(&trait_ref);
+            bounds_checker.check_trait_ref(&trait_ref, item.span);
 
             let cause =
                 traits::ObligationCause::new(
@@ -352,10 +348,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                          span: Span,
                          param_name: ast::Name)
     {
-        self.tcx().sess.span_err(
-            span,
-            &format!("parameter `{}` is never used",
-                     param_name.user_string(self.tcx())));
+        span_err!(self.tcx().sess, span, E0392,
+            "parameter `{}` is never used", param_name);
 
         let suggested_marker_id = self.tcx().lang_items.phantom_data();
         match suggested_marker_id {
@@ -363,7 +357,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 self.tcx().sess.fileline_help(
                     span,
                     &format!("consider removing `{}` or using a marker such as `{}`",
-                             param_name.user_string(self.tcx()),
+                             param_name,
                              ty::item_path_str(self.tcx(), def_id)));
             }
             None => {
@@ -377,7 +371,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       span: Span,
                                       predicates: &ty::GenericPredicates<'tcx>) {
-    for predicate in predicates.predicates.iter() {
+    for predicate in &predicates.predicates {
         match predicate {
             &ty::Predicate::Trait(ty::Binder(ref tr)) => {
                 let found_param = tr.input_types().iter()
@@ -400,12 +394,12 @@ fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
             "cannot bound type `{}`, where clause \
                 bounds may only be attached to types involving \
                 type parameters",
-                bounded_ty.repr(tcx))
+                bounded_ty)
     }
 
     fn is_ty_param(ty: ty::Ty) -> bool {
         match &ty.sty {
-            &ty::sty::ty_param(_) => true,
+            &ty::TyParam(_) => true,
             _ => false
         }
     }
@@ -485,11 +479,10 @@ pub struct BoundsChecker<'cx,'tcx:'cx> {
 
 impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
     pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
-               span: Span,
                scope: ast::NodeId,
                cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
                -> BoundsChecker<'cx,'tcx> {
-        BoundsChecker { fcx: fcx, span: span, scope: scope,
+        BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
                         cache: cache, binding_count: 0 }
     }
 
@@ -502,30 +495,32 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
     ///
     /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
     /// to the point where impl `A : Trait<B>` is implemented).
-    pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
+    pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
         let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id);
 
-        let bounds = self.fcx.instantiate_bounds(self.span,
+        let bounds = self.fcx.instantiate_bounds(span,
                                                  trait_ref.substs,
                                                  &trait_predicates);
 
         self.fcx.add_obligations_for_parameters(
             traits::ObligationCause::new(
-                self.span,
+                span,
                 self.fcx.body_id,
                 traits::ItemObligation(trait_ref.def_id)),
             &bounds);
 
-        for &ty in trait_ref.substs.types.iter() {
-            self.check_traits_in_ty(ty);
+        for &ty in &trait_ref.substs.types {
+            self.check_traits_in_ty(ty, span);
         }
     }
 
-    pub fn check_ty(&mut self, ty: Ty<'tcx>) {
+    pub fn check_ty(&mut self, ty: Ty<'tcx>, span: Span) {
+        self.span = span;
         ty.fold_with(self);
     }
 
-    fn check_traits_in_ty(&mut self, ty: Ty<'tcx>) {
+    fn check_traits_in_ty(&mut self, ty: Ty<'tcx>, span: Span) {
+        self.span = span;
         // When checking types outside of a type def'n, we ignore
         // region obligations. See discussion below in fold_ty().
         self.binding_count += 1;
@@ -540,23 +535,23 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
     }
 
     fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         self.binding_count += 1;
         let value = liberate_late_bound_regions(
             self.fcx.tcx(),
             region::DestructionScopeData::new(self.scope),
             binder);
-        debug!("BoundsChecker::fold_binder: late-bound regions replaced: {} at scope: {:?}",
-               value.repr(self.tcx()), self.scope);
+        debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
+               value, self.scope);
         let value = value.fold_with(self);
         self.binding_count -= 1;
         ty::Binder(value)
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("BoundsChecker t={}",
-               t.repr(self.tcx()));
+        debug!("BoundsChecker t={:?}",
+               t);
 
         match self.cache {
             Some(ref mut cache) => {
@@ -570,8 +565,8 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
         }
 
         match t.sty{
-            ty::ty_struct(type_id, substs) |
-            ty::ty_enum(type_id, substs) => {
+            ty::TyStruct(type_id, substs) |
+            ty::TyEnum(type_id, substs) => {
                 let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id);
                 let bounds = self.fcx.instantiate_bounds(self.span, substs,
                                                          &type_predicates);
index 889975f0eb2f97e2f2c4701b1c5b6c2d147a4d9d..05cc3077fc9fbb6d706fa2174d66cb8a5bdda35a 100644 (file)
@@ -21,7 +21,6 @@ use middle::ty_fold::{TypeFolder,TypeFoldable};
 use middle::infer;
 use write_substs_to_tcx;
 use write_ty_to_tcx;
-use util::ppaux::Repr;
 
 use std::cell::Cell;
 
@@ -41,7 +40,6 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
     wbcx.visit_expr(e);
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
-    wbcx.visit_object_cast_map();
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
@@ -62,7 +60,6 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
     }
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
-    wbcx.visit_object_cast_map();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -171,10 +168,10 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
 
         self.visit_node_id(ResolvingPattern(p.span), p.id);
 
-        debug!("Type for pattern binding {} (id {}) resolved to {}",
+        debug!("Type for pattern binding {} (id {}) resolved to {:?}",
                pat_to_string(p),
                p.id,
-               ty::node_id_to_type(self.tcx(), p.id).repr(self.tcx()));
+               ty::node_id_to_type(self.tcx(), p.id));
 
         visit::walk_pat(self, p);
     }
@@ -207,7 +204,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             return;
         }
 
-        for (upvar_id, upvar_capture) in &*self.fcx.inh.upvar_capture_map.borrow() {
+        for (upvar_id, upvar_capture) in self.fcx.inh.upvar_capture_map.borrow().iter() {
             let new_upvar_capture = match *upvar_capture {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
@@ -217,9 +214,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                         ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
                 }
             };
-            debug!("Upvar capture for {} resolved to {}",
-                   upvar_id.repr(self.tcx()),
-                   new_upvar_capture.repr(self.tcx()));
+            debug!("Upvar capture for {:?} resolved to {:?}",
+                   upvar_id,
+                   new_upvar_capture);
             self.fcx.tcx().upvar_capture_map.borrow_mut().insert(*upvar_id, new_upvar_capture);
         }
     }
@@ -229,37 +226,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             return
         }
 
-        for (def_id, closure_ty) in &*self.fcx.inh.closure_tys.borrow() {
+        for (def_id, closure_ty) in self.fcx.inh.closure_tys.borrow().iter() {
             let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id));
             self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty);
         }
 
-        for (def_id, &closure_kind) in &*self.fcx.inh.closure_kinds.borrow() {
+        for (def_id, &closure_kind) in self.fcx.inh.closure_kinds.borrow().iter() {
             self.fcx.tcx().closure_kinds.borrow_mut().insert(*def_id, closure_kind);
         }
     }
 
-    fn visit_object_cast_map(&self) {
-        if self.fcx.writeback_errors.get() {
-            return
-        }
-
-        for (&node_id, trait_ref) in self.fcx
-                                            .inh
-                                            .object_cast_map
-                                            .borrow()
-                                            .iter()
-        {
-            let span = ty::expr_span(self.tcx(), node_id);
-            let reason = ResolvingExpr(span);
-            let closure_ty = self.resolve(trait_ref, reason);
-            self.tcx()
-                .object_cast_map
-                .borrow_mut()
-                .insert(node_id, closure_ty);
-        }
-    }
-
     fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
         // Resolve any borrowings for the node with id `id`
         self.visit_adjustments(reason, id);
@@ -268,7 +244,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let n_ty = self.fcx.node_ty(id);
         let n_ty = self.resolve(&n_ty, reason);
         write_ty_to_tcx(self.tcx(), id, n_ty);
-        debug!("Node {} has type {}", id, n_ty.repr(self.tcx()));
+        debug!("Node {} has type {:?}", id, n_ty);
 
         // Resolve any substitutions
         self.fcx.opt_node_ty_substs(id, |item_substs| {
@@ -317,9 +293,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         // Resolve any method map entry
         match self.fcx.inh.method_map.borrow_mut().remove(&method_call) {
             Some(method) => {
-                debug!("writeback::resolve_method_map_entry(call={:?}, entry={})",
+                debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
                        method_call,
-                       method.repr(self.tcx()));
+                       method);
                 let new_method = MethodCallee {
                     origin: self.resolve(&method.origin, reason),
                     ty: self.resolve(&method.ty, reason),
@@ -450,8 +426,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
         match self.infcx.fully_resolve(&t) {
             Ok(t) => t,
             Err(e) => {
-                debug!("Resolver::fold_ty: input type `{}` not fully resolvable",
-                       t.repr(self.tcx));
+                debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable",
+                       t);
                 self.report_error(e);
                 self.tcx().types.err
             }
index 58ad8ce86280d4f1aca04cea56bfa409dc1b9e09..b66c76048c639db3b0e7531602e3a6396f59c8cb 100644 (file)
@@ -22,30 +22,28 @@ use middle::traits;
 use middle::ty::RegionEscape;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
 use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
-use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
-use middle::ty::{ty_param, TypeScheme, ty_ptr};
-use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
-use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
-use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
-use middle::ty::ty_projection;
+use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
+use middle::ty::{TyParam, TypeScheme, TyRawPtr};
+use middle::ty::{TyRef, TyStruct, TyTrait, TyTuple};
+use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
+use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
+use middle::ty::TyProjection;
 use middle::ty;
 use middle::free_region::FreeRegionMap;
 use CrateCtxt;
 use middle::infer::{self, InferCtxt, new_infer_ctxt};
+use rustc::ast_map::{self, NodeItem};
 use std::cell::RefCell;
 use std::rc::Rc;
 use syntax::ast::{Crate, DefId};
 use syntax::ast::{Item, ItemImpl};
-use syntax::ast::{LOCAL_CRATE, TraitRef};
+use syntax::ast::{LOCAL_CRATE};
 use syntax::ast;
-use syntax::ast_map::NodeItem;
-use syntax::ast_map;
 use syntax::ast_util::local_def;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::visit;
 use util::nodemap::{DefIdMap, FnvHashMap};
-use util::ppaux::Repr;
 
 mod orphan;
 mod overlap;
@@ -57,33 +55,33 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
                                   ty: Ty<'tcx>)
                                   -> Option<DefId> {
     match ty.sty {
-        ty_enum(def_id, _) |
-        ty_struct(def_id, _) => {
+        TyEnum(def_id, _) |
+        TyStruct(def_id, _) => {
             Some(def_id)
         }
 
-        ty_trait(ref t) => {
+        TyTrait(ref t) => {
             Some(t.principal_def_id())
         }
 
-        ty_uniq(_) => {
+        TyBox(_) => {
             inference_context.tcx.lang_items.owned_box()
         }
 
-        ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
-        ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
-        ty_param(..) | ty_err |
-        ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
+        TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+        TyStr(..) | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
+        TyParam(..) | TyError |
+        TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => {
             None
         }
 
-        ty_infer(..) | ty_closure(..) => {
+        TyInfer(..) | TyClosure(..) => {
             // `ty` comes from a user declaration so we should only expect types
             // that the user can type
             inference_context.tcx.sess.span_bug(
                 span,
                 &format!("coherence encountered unexpected type searching for base type: {}",
-                        ty.repr(inference_context.tcx)));
+                         ty));
         }
     }
 }
@@ -100,11 +98,8 @@ struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-
-        //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
-
-        if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
-            self.cc.check_implementation(item, opt_trait.as_ref())
+        if let ItemImpl(..) = item.node {
+            self.cc.check_implementation(item)
         }
 
         visit::walk_item(self, item);
@@ -123,7 +118,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         // the tcx.
         let mut tcx_inherent_impls =
             self.crate_context.tcx.inherent_impls.borrow_mut();
-        for (k, v) in &*self.inherent_impls.borrow() {
+        for (k, v) in self.inherent_impls.borrow().iter() {
             tcx_inherent_impls.insert((*k).clone(),
                                       Rc::new((*v.borrow()).clone()));
         }
@@ -141,7 +136,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         self.check_implementations_of_coerce_unsized();
     }
 
-    fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
+    fn check_implementation(&self, item: &Item) {
         let tcx = self.crate_context.tcx;
         let impl_did = local_def(item.id);
         let self_type = ty::lookup_item_type(tcx, impl_did);
@@ -151,32 +146,23 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
         let impl_items = self.create_impl_from_item(item);
 
-        if opt_trait.is_some() {
-            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
-            debug!("(checking implementation) adding impl for trait '{}', item '{}'",
-                   trait_ref.repr(self.crate_context.tcx),
-                   token::get_ident(item.ident));
+        if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
+                                                    impl_did) {
+            debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
+                   trait_ref,
+                   item.ident);
 
             enforce_trait_manually_implementable(self.crate_context.tcx,
                                                  item.span,
                                                  trait_ref.def_id);
             self.add_trait_impl(trait_ref, impl_did);
-        }
-
-        // Add the implementation to the mapping from implementation to base
-        // type def ID, if there is a base type for this implementation and
-        // the implementation does not have any associated traits.
-        match get_base_type_def_id(&self.inference_context,
-                                   item.span,
-                                   self_type.ty) {
-            None => {
-                // Nothing to do.
-            }
-            Some(base_type_def_id) => {
-                // FIXME: Gather up default methods?
-                if opt_trait.is_none() {
-                    self.add_inherent_impl(base_type_def_id, impl_did);
-                }
+        } else {
+            // Add the implementation to the mapping from implementation to base
+            // type def ID, if there is a base type for this implementation and
+            // the implementation does not have any associated traits.
+            if let Some(base_type_def_id) = get_base_type_def_id(
+                    &self.inference_context, item.span, self_type.ty) {
+                self.add_inherent_impl(base_type_def_id, impl_did);
             }
         }
 
@@ -192,8 +178,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             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.repr(tcx));
+        debug!("instantiate_default_methods(impl_id={:?}, trait_ref={:?})",
+               impl_id, trait_ref);
 
         let impl_type_scheme = ty::lookup_item_type(tcx, impl_id);
 
@@ -203,7 +189,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             let new_id = tcx.sess.next_node_id();
             let new_did = local_def(new_id);
 
-            debug!("new_did={:?} trait_method={}", new_did, trait_method.repr(tcx));
+            debug!("new_did={:?} trait_method={:?}", new_did, trait_method);
 
             // Create substitutions for the various trait parameters.
             let new_method_ty =
@@ -216,7 +202,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     &**trait_method,
                     Some(trait_method.def_id)));
 
-            debug!("new_method_ty={}", new_method_ty.repr(tcx));
+            debug!("new_method_ty={:?}", new_method_ty);
             all_impl_items.push(MethodTraitItemId(new_did));
 
             // construct the polytype for the method based on the
@@ -227,7 +213,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 ty: ty::mk_bare_fn(tcx, Some(new_did),
                                    tcx.mk_bare_fn(new_method_ty.fty.clone()))
             };
-            debug!("new_polytype={}", new_polytype.repr(tcx));
+            debug!("new_polytype={:?}", new_polytype);
 
             tcx.tcache.borrow_mut().insert(new_did, new_polytype);
             tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
@@ -267,7 +253,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     // Converts an implementation in the AST to a vector of items.
     fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
-            ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, _, ref impl_items) => {
                 let mut items: Vec<ImplOrTraitItemId> =
                         impl_items.iter().map(|impl_item| {
                     match impl_item.node {
@@ -287,10 +273,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     }
                 }).collect();
 
-                if opt_trait.is_some() {
-                    let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
-                                                             item.id);
-
+                if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
+                                                            local_def(item.id)) {
                     self.instantiate_default_methods(local_def(item.id),
                                                      &trait_ref,
                                                      &mut items);
@@ -300,7 +284,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
-                                                     "can't convert a non-impl to an impl");
+                                                     "can't convert a non-impl \
+                                                      to an impl");
             }
         }
     }
@@ -329,9 +314,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
             let self_type = ty::lookup_item_type(tcx, impl_did);
             match self_type.ty.sty {
-                ty::ty_enum(type_def_id, _) |
-                ty::ty_struct(type_def_id, _) |
-                ty::ty_closure(type_def_id, _) => {
+                ty::TyEnum(type_def_id, _) |
+                ty::TyStruct(type_def_id, _) |
+                ty::TyClosure(type_def_id, _) => {
                     tcx.destructor_for_type
                        .borrow_mut()
                        .insert(type_def_id, method_def_id.def_id());
@@ -374,8 +359,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         let copy_trait = ty::lookup_trait_def(tcx, copy_trait);
 
         copy_trait.for_each_impl(tcx, |impl_did| {
-            debug!("check_implementations_of_copy: impl_did={}",
-                   impl_did.repr(tcx));
+            debug!("check_implementations_of_copy: impl_did={:?}",
+                   impl_did);
 
             if impl_did.krate != ast::LOCAL_CRATE {
                 debug!("check_implementations_of_copy(): impl not in this \
@@ -384,16 +369,16 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
 
             let self_type = ty::lookup_item_type(tcx, impl_did);
-            debug!("check_implementations_of_copy: self_type={} (bound)",
-                   self_type.repr(tcx));
+            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 self_type = self_type.ty.subst(tcx, &param_env.free_substs);
             assert!(!self_type.has_escaping_regions());
 
-            debug!("check_implementations_of_copy: self_type={} (free)",
-                   self_type.repr(tcx));
+            debug!("check_implementations_of_copy: self_type={:?} (free)",
+                   self_type);
 
             match ty::can_type_implement_copy(&param_env, span, self_type) {
                 Ok(()) => {}
@@ -443,8 +428,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         let trait_def = ty::lookup_trait_def(tcx, coerce_unsized_trait);
 
         trait_def.for_each_impl(tcx, |impl_did| {
-            debug!("check_implementations_of_coerce_unsized: impl_did={}",
-                   impl_did.repr(tcx));
+            debug!("check_implementations_of_coerce_unsized: impl_did={:?}",
+                   impl_did);
 
             if impl_did.krate != ast::LOCAL_CRATE {
                 debug!("check_implementations_of_coerce_unsized(): impl not \
@@ -453,11 +438,11 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
 
             let source = ty::lookup_item_type(tcx, impl_did).ty;
-            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
-                                                     impl_did.node);
+            let trait_ref = ty::impl_trait_ref(self.crate_context.tcx,
+                                               impl_did).unwrap();
             let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
-            debug!("check_implementations_of_coerce_unsized: {} -> {} (bound)",
-                   source.repr(tcx), target.repr(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);
@@ -465,8 +450,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             let target = target.subst(tcx, &param_env.free_substs);
             assert!(!source.has_escaping_regions());
 
-            debug!("check_implementations_of_coerce_unsized: {} -> {} (free)",
-                   source.repr(tcx), target.repr(tcx));
+            debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
+                   source, target);
 
             let infcx = new_infer_ctxt(tcx);
 
@@ -479,19 +464,19 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 (mt_a.ty, mt_b.ty, unsize_trait, None)
             };
             let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
-                (&ty::ty_uniq(a), &ty::ty_uniq(b)) => (a, b, unsize_trait, None),
+                (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None),
 
-                (&ty::ty_rptr(r_a, mt_a), &ty::ty_rptr(r_b, mt_b)) => {
+                (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
                     infer::mk_subr(&infcx, infer::RelateObjectBound(span), *r_b, *r_a);
                     check_mutbl(mt_a, mt_b, &|ty| ty::mk_imm_rptr(tcx, r_b, ty))
                 }
 
-                (&ty::ty_rptr(_, mt_a), &ty::ty_ptr(mt_b)) |
-                (&ty::ty_ptr(mt_a), &ty::ty_ptr(mt_b)) => {
+                (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
+                (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
                     check_mutbl(mt_a, mt_b, &|ty| ty::mk_imm_ptr(tcx, ty))
                 }
 
-                (&ty::ty_struct(def_id_a, substs_a), &ty::ty_struct(def_id_b, substs_b)) => {
+                (&ty::TyStruct(def_id_a, substs_a), &ty::TyStruct(def_id_b, substs_b)) => {
                     if def_id_a != def_id_b {
                         let source_path = ty::item_path_str(tcx, def_id_a);
                         let target_path = ty::item_path_str(tcx, def_id_b);
@@ -532,10 +517,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                                                 if name == token::special_names::unnamed_field {
                                                     i.to_string()
                                                 } else {
-                                                    token::get_name(name).to_string()
-                                                },
-                                                a.repr(tcx),
-                                                b.repr(tcx))
+                                                    name.to_string()
+                                                }, a, b)
                                    }).collect::<Vec<_>>().connect(", "));
                         return;
                     }
@@ -553,7 +536,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 }
             };
 
-            let mut fulfill_cx = traits::FulfillmentContext::new();
+            let mut fulfill_cx = traits::FulfillmentContext::new(true);
 
             // Register an obligation for `A: Trait<B>`.
             let cause = traits::ObligationCause::misc(span, impl_did.node);
@@ -611,8 +594,8 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
 {
     let combined_substs = ty::make_substs_for_receiver_types(tcx, trait_ref, method);
 
-    debug!("subst_receiver_types_in_method_ty: combined_substs={}",
-           combined_substs.repr(tcx));
+    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);
@@ -628,13 +611,13 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
             impl_type_scheme.generics.regions.get_slice(space).to_vec());
     }
 
-    debug!("subst_receiver_types_in_method_ty: method_generics={}",
-           method_generics.repr(tcx));
+    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.repr(tcx));
+    debug!("subst_receiver_types_in_method_ty: method_ty={:?}",
+           method.fty);
 
     ty::Method::new(
         method.name,
index 4c9fe6492e9ca530430ea1884d5b5532b781e087..8376b92da3dea667c3926ad14c169d0b7de6af51 100644 (file)
@@ -18,7 +18,6 @@ use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::visit;
-use util::ppaux::{Repr, UserString};
 
 pub fn check(tcx: &ty::ctxt) {
     let mut orphan = OrphanChecker { tcx: tcx };
@@ -33,8 +32,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
     fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) {
         if def_id.krate != ast::LOCAL_CRATE {
             span_err!(self.tcx.sess, item.span, E0116,
-                      "cannot associate methods with a type outside the \
-                       crate the type is defined in; define and implement \
+                      "cannot define inherent `impl` for a type outside of the \
+                       crate where the type is defined; define and implement \
                        a trait or new type instead");
         }
     }
@@ -48,10 +47,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
         match lang_def_id {
             Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
             _ => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \
-                              is allowed for the `{}` primitive", lang, ty));
+                span_err!(self.tcx.sess, span, E0390,
+                          "only a single inherent implementation marked with `#[lang = \"{}\"]` \
+                           is allowed for the `{}` primitive", lang, ty);
             }
         }
     }
@@ -67,132 +65,133 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
             ast::ItemImpl(_, _, _, None, _, _) => {
                 // For inherent impls, self type must be a nominal type
                 // defined in this crate.
-                debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx));
+                debug!("coherence2::orphan check: inherent impl {}",
+                       self.tcx.map.node_to_string(item.id));
                 let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
                 match self_ty.sty {
-                    ty::ty_enum(def_id, _) |
-                    ty::ty_struct(def_id, _) => {
+                    ty::TyEnum(def_id, _) |
+                    ty::TyStruct(def_id, _) => {
                         self.check_def_id(item, def_id);
                     }
-                    ty::ty_trait(ref data) => {
+                    ty::TyTrait(ref data) => {
                         self.check_def_id(item, data.principal_def_id());
                     }
-                    ty::ty_uniq(..) => {
+                    ty::TyBox(..) => {
                         self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
                     }
-                    ty::ty_char => {
+                    ty::TyChar => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.char_impl(),
                                                   "char",
                                                   "char",
                                                   item.span);
                     }
-                    ty::ty_str => {
+                    ty::TyStr => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.str_impl(),
                                                   "str",
                                                   "str",
                                                   item.span);
                     }
-                    ty::ty_vec(_, None) => {
+                    ty::TySlice(_) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.slice_impl(),
                                                   "slice",
                                                   "[T]",
                                                   item.span);
                     }
-                    ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
+                    ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.const_ptr_impl(),
                                                   "const_ptr",
                                                   "*const T",
                                                   item.span);
                     }
-                    ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
+                    ty::TyRawPtr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.mut_ptr_impl(),
                                                   "mut_ptr",
                                                   "*mut T",
                                                   item.span);
                     }
-                    ty::ty_int(ast::TyI8) => {
+                    ty::TyInt(ast::TyI8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i8_impl(),
                                                   "i8",
                                                   "i8",
                                                   item.span);
                     }
-                    ty::ty_int(ast::TyI16) => {
+                    ty::TyInt(ast::TyI16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i16_impl(),
                                                   "i16",
                                                   "i16",
                                                   item.span);
                     }
-                    ty::ty_int(ast::TyI32) => {
+                    ty::TyInt(ast::TyI32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i32_impl(),
                                                   "i32",
                                                   "i32",
                                                   item.span);
                     }
-                    ty::ty_int(ast::TyI64) => {
+                    ty::TyInt(ast::TyI64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i64_impl(),
                                                   "i64",
                                                   "i64",
                                                   item.span);
                     }
-                    ty::ty_int(ast::TyIs) => {
+                    ty::TyInt(ast::TyIs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.isize_impl(),
                                                   "isize",
                                                   "isize",
                                                   item.span);
                     }
-                    ty::ty_uint(ast::TyU8) => {
+                    ty::TyUint(ast::TyU8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u8_impl(),
                                                   "u8",
                                                   "u8",
                                                   item.span);
                     }
-                    ty::ty_uint(ast::TyU16) => {
+                    ty::TyUint(ast::TyU16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u16_impl(),
                                                   "u16",
                                                   "u16",
                                                   item.span);
                     }
-                    ty::ty_uint(ast::TyU32) => {
+                    ty::TyUint(ast::TyU32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u32_impl(),
                                                   "u32",
                                                   "u32",
                                                   item.span);
                     }
-                    ty::ty_uint(ast::TyU64) => {
+                    ty::TyUint(ast::TyU64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u64_impl(),
                                                   "u64",
                                                   "u64",
                                                   item.span);
                     }
-                    ty::ty_uint(ast::TyUs) => {
+                    ty::TyUint(ast::TyUs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.usize_impl(),
                                                   "usize",
                                                   "usize",
                                                   item.span);
                     }
-                    ty::ty_float(ast::TyF32) => {
+                    ty::TyFloat(ast::TyF32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f32_impl(),
                                                   "f32",
                                                   "f32",
                                                   item.span);
                     }
-                    ty::ty_float(ast::TyF64) => {
+                    ty::TyFloat(ast::TyF64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f64_impl(),
                                                   "f64",
@@ -209,7 +208,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
             }
             ast::ItemImpl(_, _, _, Some(_), _, _) => {
                 // "Trait" impl
-                debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
+                debug!("coherence2::orphan check: trait impl {}",
+                       self.tcx.map.node_to_string(item.id));
                 let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
                 match traits::orphan_check(self.tcx, def_id) {
@@ -228,7 +228,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                 "type parameter `{}` must be used as the type parameter for \
                                  some local type (e.g. `MyStruct<T>`); only traits defined in \
                                  the current crate can be implemented for a type parameter",
-                                param_ty.user_string(self.tcx));
+                                param_ty);
                         return;
                     }
                 }
@@ -266,9 +266,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 // This final impl is legal according to the orpan
                 // rules, but it invalidates the reasoning from
                 // `two_foos` above.
-                debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}",
-                       trait_ref.repr(self.tcx),
-                       trait_def_id.repr(self.tcx),
+                debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
+                       trait_ref,
+                       trait_def_id,
                        ty::trait_has_default_impl(self.tcx, trait_def_id));
                 if
                     ty::trait_has_default_impl(self.tcx, trait_def_id) &&
@@ -276,9 +276,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 {
                     let self_ty = trait_ref.self_ty();
                     let opt_self_def_id = match self_ty.sty {
-                        ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) =>
+                        ty::TyStruct(self_def_id, _) | ty::TyEnum(self_def_id, _) =>
                             Some(self_def_id),
-                        ty::ty_uniq(..) =>
+                        ty::TyBox(..) =>
                             self.tcx.lang_items.owned_box(),
                         _ =>
                             None
@@ -306,7 +306,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                  can only be implemented for a struct/enum type, \
                                  not `{}`",
                                 ty::item_path_str(self.tcx, trait_def_id),
-                                self_ty.user_string(self.tcx)))
+                                self_ty))
                         }
                     };
 
@@ -330,7 +330,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
             }
             ast::ItemDefaultImpl(..) => {
                 // "Trait" impl
-                debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx));
+                debug!("coherence2::orphan check: default trait impl {}",
+                       self.tcx.map.node_to_string(item.id));
                 let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
                 if trait_ref.def_id.krate != ast::LOCAL_CRATE {
                     span_err!(self.tcx.sess, item.span, E0318,
index e9c69c84630ef2efc8f9eca5551c6ae9a8f4213d..0e8067e7181bd4d821ce364639c46710c384b2b0 100644 (file)
@@ -21,7 +21,6 @@ use syntax::ast_util;
 use syntax::visit;
 use syntax::codemap::Span;
 use util::nodemap::DefIdMap;
-use util::ppaux::{Repr, UserString};
 
 pub fn check(tcx: &ty::ctxt) {
     let mut overlap = OverlapChecker { tcx: tcx, default_impls: DefIdMap() };
@@ -61,8 +60,8 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
     fn check_for_overlapping_impls_of_trait(&self,
                                             trait_def: &'tcx ty::TraitDef<'tcx>)
     {
-        debug!("check_for_overlapping_impls_of_trait(trait_def={})",
-               trait_def.repr(self.tcx));
+        debug!("check_for_overlapping_impls_of_trait(trait_def={:?})",
+               trait_def);
 
         // We should already know all impls of this trait, so these
         // borrows are safe.
@@ -131,10 +130,10 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         if let Some((impl1_def_id, impl2_def_id)) = self.order_impls(
             impl1_def_id, impl2_def_id)
         {
-            debug!("check_if_impls_overlap({}, {}, {})",
-                   trait_def_id.repr(self.tcx),
-                   impl1_def_id.repr(self.tcx),
-                   impl2_def_id.repr(self.tcx));
+            debug!("check_if_impls_overlap({:?}, {:?}, {:?})",
+                   trait_def_id,
+                   impl1_def_id,
+                   impl2_def_id);
 
             let infcx = infer::new_infer_ctxt(self.tcx);
             if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
@@ -198,7 +197,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                 let trait_ref = ty::impl_trait_ref(self.tcx, impl_def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
                 match trait_ref.self_ty().sty {
-                    ty::ty_trait(ref data) => {
+                    ty::TyTrait(ref data) => {
                         // This is something like impl Trait1 for Trait2. Illegal
                         // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
 
@@ -217,7 +216,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                                 span_err!(self.tcx.sess, item.span, E0371,
                                           "the object type `{}` automatically \
                                            implements the trait `{}`",
-                                          trait_ref.self_ty().user_string(self.tcx),
+                                          trait_ref.self_ty(),
                                           ty::item_path_str(self.tcx, trait_def_id));
                             }
                         }
index e4926b119d5dbe551808b3e8bb2db99d0afd7d12..fa39e9d0491f9566136934475229e627fdd18897 100644 (file)
@@ -16,7 +16,6 @@ use syntax::ast::{Item, ItemImpl};
 use syntax::ast;
 use syntax::ast_util;
 use syntax::visit;
-use util::ppaux::UserString;
 
 pub fn check(tcx: &ty::ctxt) {
     let mut orphan = UnsafetyChecker { tcx: tcx };
@@ -55,14 +54,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
                     (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
                         span_err!(self.tcx.sess, item.span, E0199,
                                   "implementing the trait `{}` is not unsafe",
-                                  trait_ref.user_string(self.tcx));
+                                  trait_ref);
                     }
 
                     (ast::Unsafety::Unsafe,
                      ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
                         span_err!(self.tcx.sess, item.span, E0200,
                                   "the trait `{}` requires an `unsafe impl` declaration",
-                                  trait_ref.user_string(self.tcx));
+                                  trait_ref);
                     }
 
                     (ast::Unsafety::Unsafe,
index 014991f7ea560e377aeb751014bb65e05e67fb1d..3345f9ae5bfab86f766d3ea4055a781a8af86032 100644 (file)
@@ -77,10 +77,9 @@ use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
+use rustc::ast_map;
 use util::common::{ErrorReported, memoized};
 use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux;
-use util::ppaux::{Repr,UserString};
 use write_ty_to_tcx;
 
 use std::cell::{Cell, RefCell};
@@ -89,7 +88,6 @@ use std::rc::Rc;
 
 use syntax::abi;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util::local_def;
 use syntax::codemap::Span;
 use syntax::parse::token::special_idents;
@@ -236,9 +234,8 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
         assert!(!cycle.is_empty());
         let tcx = self.tcx;
 
-        tcx.sess.span_err(
-            span,
-            &format!("unsupported cyclic reference between types/traits detected"));
+        span_err!(tcx.sess, span, E0391,
+            "unsupported cyclic reference between types/traits detected");
 
         match cycle[0] {
             AstConvRequest::GetItemTypeScheme(def_id) |
@@ -257,11 +254,11 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                 tcx.sess.note(
                     &format!("the cycle begins when computing the bounds \
                               for type parameter `{}`...",
-                             def.name.user_string(tcx)));
+                             def.name));
             }
         }
 
-        for request in cycle[1..].iter() {
+        for request in &cycle[1..] {
             match *request {
                 AstConvRequest::GetItemTypeScheme(def_id) |
                 AstConvRequest::GetTraitDef(def_id) => {
@@ -279,7 +276,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                     tcx.sess.note(
                         &format!("...which then requires computing the bounds \
                                   for type parameter `{}`...",
-                                 def.name.user_string(tcx)));
+                                 def.name));
                 }
             }
         }
@@ -302,7 +299,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                 tcx.sess.note(
                     &format!("...which then again requires computing the bounds \
                               for type parameter `{}`, completing the cycle.",
-                             def.name.user_string(tcx)));
+                             def.name));
             }
         }
     }
@@ -319,7 +316,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
 
         let item = match tcx.map.get(trait_id.node) {
             ast_map::NodeItem(item) => item,
-            _ => tcx.sess.bug(&format!("get_trait_def({}): not an item", trait_id.repr(tcx)))
+            _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
         };
 
         trait_def_of_item(self, &*item)
@@ -373,8 +370,8 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
                                trait_def_id: ast::DefId)
                                -> Result<(), ErrorReported>
     {
-        debug!("ensure_super_predicates(trait_def_id={})",
-               trait_def_id.repr(self.tcx()));
+        debug!("ensure_super_predicates(trait_def_id={:?})",
+               trait_def_id);
 
         self.ccx.ensure_super_predicates(span, trait_def_id)
     }
@@ -444,7 +441,7 @@ impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
                                  -> Vec<ty::Predicate<'tcx>>
     {
         let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
-        v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id).into_iter());
+        v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id));
         v
     }
 }
@@ -518,7 +515,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
                 .iter()
                 .filter(|p| p.id == node_id)
                 .flat_map(|p| p.bounds.iter())
-                .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter());
+                .flat_map(|b| predicates_from_bound(astconv, ty, b));
 
         let from_where_clauses =
             self.where_clause
@@ -530,7 +527,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
                 })
                 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
                 .flat_map(|bp| bp.bounds.iter())
-                .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter());
+                .flat_map(|b| predicates_from_bound(astconv, ty, b));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -636,8 +633,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let fty = ty::mk_bare_fn(ccx.tcx, Some(def_id),
                              ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
-    debug!("method {} (id {}) has type {}",
-            ident.repr(ccx.tcx), id, fty.repr(ccx.tcx));
+    debug!("method {} (id {}) has type {:?}",
+            ident, id, fty);
     ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
         generics: ty_method.generics.clone(),
         ty: fty
@@ -646,8 +643,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     write_ty_to_tcx(ccx.tcx, id, fty);
 
-    debug!("writing method type: def_id={:?} mty={}",
-            def_id, ty_method.repr(ccx.tcx));
+    debug!("writing method type: def_id={:?} mty={:?}",
+            def_id, ty_method);
 
     ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
         ty::MethodTraitItem(Rc::new(ty_method)));
@@ -718,15 +715,17 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
        .insert(local_def(id), ty::ConstTraitItem(associated_const));
 }
 
-fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                 container: ImplOrTraitItemContainer,
-                                 ident: ast::Ident,
-                                 id: ast::NodeId,
-                                 vis: ast::Visibility)
+fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                     container: ImplOrTraitItemContainer,
+                                     ident: ast::Ident,
+                                     id: ast::NodeId,
+                                     vis: ast::Visibility,
+                                     ty: Option<Ty<'tcx>>)
 {
     let associated_type = Rc::new(ty::AssociatedType {
         name: ident.name,
         vis: vis,
+        ty: ty,
         def_id: local_def(id),
         container: container
     });
@@ -742,16 +741,21 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                  rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
     where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
 {
-    debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={}, rcvr_ty_predicates={})",
-           untransformed_rcvr_ty.repr(ccx.tcx),
-           rcvr_ty_generics.repr(ccx.tcx),
-           rcvr_ty_predicates.repr(ccx.tcx));
+    debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
+                            rcvr_ty_predicates={:?})",
+           untransformed_rcvr_ty,
+           rcvr_ty_generics,
+           rcvr_ty_predicates);
 
     let tcx = ccx.tcx;
     let mut seen_methods = FnvHashSet();
     for (sig, id, ident, vis, span) in methods {
         if !seen_methods.insert(ident.name) {
-            span_err!(tcx.sess, span, E0201, "duplicate method");
+            let fn_desc = match sig.explicit_self.node {
+                ast::SelfStatic => "associated function",
+                _               => "method",
+            };
+            span_err!(tcx.sess, span, E0201, "duplicate {}", fn_desc);
         }
 
         convert_method(ccx,
@@ -772,8 +776,8 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  thing: &'static str) {
     let mut warn = false;
 
-    for ty_param in &*generics.ty_params {
-        for bound in &*ty_param.bounds {
+    for ty_param in generics.ty_params.iter() {
+        for bound in ty_param.bounds.iter() {
             match *bound {
                 ast::TraitTyParamBound(..) => {
                     warn = true;
@@ -820,7 +824,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
 
-            tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
+            tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
         }
         ast::ItemImpl(_, _,
                       ref generics,
@@ -828,7 +832,6 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                       ref selfty,
                       ref impl_items) => {
             // Create generics from the generics specified in the impl head.
-
             debug!("convert: ast_generics={:?}", generics);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
@@ -877,21 +880,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 if let ast::TypeImplItem(ref ty) = impl_item.node {
                     if opt_trait_ref.is_none() {
                         span_err!(tcx.sess, impl_item.span, E0202,
-                                  "associated items are not allowed in inherent impls");
+                                  "associated types are not allowed in inherent impls");
                     }
 
-                    as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
-                                        impl_item.ident, impl_item.id, impl_item.vis);
-
                     let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
-                    tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
-                                                   TypeScheme {
-                                                       generics: ty::Generics::empty(),
-                                                       ty: typ,
-                                                   });
-                    tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
-                                                       ty::GenericPredicates::empty());
-                    write_ty_to_tcx(tcx, impl_item.id, typ);
+
+                    convert_associated_type(ccx, ImplContainer(local_def(it.id)),
+                                            impl_item.ident, impl_item.id, impl_item.vis,
+                                            Some(typ));
                 }
             }
 
@@ -926,14 +922,16 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 }
             }
 
-            if let Some(ref ast_trait_ref) = *opt_trait_ref {
-                let trait_ref =
-                    astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
-                                                        &ExplicitRscope,
-                                                        ast_trait_ref,
-                                                        Some(selfty));
-
-                tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
+            if let &Some(ref ast_trait_ref) = opt_trait_ref {
+                tcx.impl_trait_refs.borrow_mut().insert(
+                    local_def(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(local_def(it.id), None);
             }
 
             enforce_impl_params_are_constrained(tcx,
@@ -972,9 +970,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // Convert all the associated types.
             for trait_item in trait_items {
                 match trait_item.node {
-                    ast::TypeTraitItem(..) => {
-                        as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
-                                                trait_item.ident, trait_item.id, ast::Public);
+                    ast::TypeTraitItem(_, ref opt_ty) => {
+                        let typ = opt_ty.as_ref().map({
+                            |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
+                        });
+
+                        convert_associated_type(ccx, TraitContainer(local_def(it.id)),
+                                                trait_item.ident, trait_item.id, ast::Public,
+                                                typ);
                     }
                     _ => {}
                 }
@@ -1136,7 +1139,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
 {
     let tcx = ccx.tcx;
 
-    debug!("ensure_super_predicates_step(trait_def_id={})", trait_def_id.repr(tcx));
+    debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
 
     if trait_def_id.krate != ast::LOCAL_CRATE {
         // If this trait comes from an external crate, then all of the
@@ -1175,22 +1178,26 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
 
         // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
         let self_param_ty = ty::mk_self_type(tcx);
-        let superbounds1 = compute_bounds(&ccx.icx(scope), self_param_ty, bounds,
-                                          SizedByDefault::No, item.span);
-        let superbounds1 = ty::predicates(tcx, self_param_ty, &superbounds1);
+        let superbounds1 = compute_bounds(&ccx.icx(scope),
+                                    self_param_ty,
+                                    bounds,
+                                    SizedByDefault::No,
+                                    item.span);
+
+        let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
 
         // Convert any explicit superbounds in the where clause,
         // e.g. `trait Foo where Self : Bar`:
         let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
 
         // Combine the two lists to form the complete set of superbounds:
-        let superbounds = superbounds1.into_iter().chain(superbounds2.into_iter()).collect();
+        let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
         let superpredicates = ty::GenericPredicates {
             predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
         };
-        debug!("superpredicates for trait {} = {}",
-               local_def(item.id).repr(ccx.tcx),
-               superpredicates.repr(ccx.tcx));
+        debug!("superpredicates for trait {:?} = {:?}",
+               local_def(item.id),
+               superpredicates);
 
         tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
 
@@ -1203,7 +1210,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
                                          .map(|tr| tr.def_id())
                                          .collect();
 
-    debug!("ensure_super_predicates_step: def_ids={}", def_ids.repr(tcx));
+    debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
 
     def_ids
 }
@@ -1392,7 +1399,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
                                         SizedByDefault::Yes,
                                         trait_item.span);
 
-            ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
+            bounds.predicates(ccx.tcx, assoc_ty).into_iter()
         }).collect()
     }
 }
@@ -1440,7 +1447,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
         }
-        ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
+        ast::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 = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
@@ -1492,7 +1499,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         ast::ItemStatic(..) | ast::ItemConst(..) => {
             ty::GenericPredicates::empty()
         }
-        ast::ItemFn(_, _, _, ref ast_generics, _) => {
+        ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
             ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
         }
         ast::ItemTy(_, ref generics) => {
@@ -1528,10 +1535,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let object_lifetime_default_reprs: String =
             scheme.generics.types.iter()
                                  .map(|t| match t.object_lifetime_default {
-                                     Some(ty::ObjectLifetimeDefault::Specific(r)) =>
-                                         r.user_string(tcx),
-                                     d =>
-                                         d.repr(ccx.tcx),
+                                     ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
+                                     d => format!("{:?}", d),
                                  })
                                  .collect::<Vec<String>>()
                                  .connect(",");
@@ -1617,8 +1622,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    ast_generics: &ast::Generics)
                                    -> ty::Generics<'tcx>
 {
-    debug!("ty_generics_for_trait(trait_id={}, substs={})",
-           local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
+    debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
+           local_def(trait_id), substs);
 
     let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
 
@@ -1634,7 +1639,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         name: special_idents::type_self.name,
         def_id: local_def(param_id),
         default: None,
-        object_lifetime_default: None,
+        object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
     };
 
     ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
@@ -1741,7 +1746,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     &param.bounds,
                                     SizedByDefault::Yes,
                                     param.span);
-        let predicates = ty::predicates(ccx.tcx, param_ty, &bounds);
+        let predicates = bounds.predicates(ccx.tcx, param_ty);
         result.predicates.extend(space, predicates.into_iter());
     }
 
@@ -1774,7 +1779,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                       &ExplicitRscope,
                                       &*bound_pred.bounded_ty);
 
-                for bound in &*bound_pred.bounds {
+                for bound in bound_pred.bounds.iter() {
                     match bound {
                         &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
                             let mut projections = Vec::new();
@@ -1878,7 +1883,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
             ty::walk_ty(ty, |t| {
                 match t.sty {
-                    ty::ty_param(p) => if p.idx > cur_idx {
+                    ty::TyParam(p) => if p.idx > cur_idx {
                         span_err!(tcx.sess, path.span, E0128,
                                   "type parameters with a default cannot use \
                                    forward declared identifiers");
@@ -1919,19 +1924,20 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                             param_id: ast::NodeId,
                                             param_bounds: &[ast::TyParamBound],
                                             where_clause: &ast::WhereClause)
-                                            -> Option<ty::ObjectLifetimeDefault>
+                                            -> ty::ObjectLifetimeDefault
 {
     let inline_bounds = from_bounds(ccx, param_bounds);
     let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
     let all_bounds: HashSet<_> = inline_bounds.into_iter()
-                                              .chain(where_bounds.into_iter())
+                                              .chain(where_bounds)
                                               .collect();
     return if all_bounds.len() > 1 {
-        Some(ty::ObjectLifetimeDefault::Ambiguous)
+        ty::ObjectLifetimeDefault::Ambiguous
+    } else if all_bounds.len() == 0 {
+        ty::ObjectLifetimeDefault::BaseDefault
     } else {
-        all_bounds.into_iter()
-                  .next()
-                  .map(ty::ObjectLifetimeDefault::Specific)
+        ty::ObjectLifetimeDefault::Specific(
+            all_bounds.into_iter().next().unwrap())
     };
 
     fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
@@ -1987,23 +1993,24 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
                         ast_bounds: &[ast::TyParamBound],
                         sized_by_default: SizedByDefault,
                         span: Span)
-                        -> ty::ParamBounds<'tcx>
+                        -> astconv::Bounds<'tcx>
 {
-    let mut param_bounds = conv_param_bounds(astconv,
-                                             span,
-                                             param_ty,
-                                             ast_bounds);
+    let mut bounds =
+        conv_param_bounds(astconv,
+                          span,
+                          param_ty,
+                          ast_bounds);
 
     if let SizedByDefault::Yes = sized_by_default {
         add_unsized_bound(astconv,
-                          &mut param_bounds.builtin_bounds,
+                          &mut bounds.builtin_bounds,
                           ast_bounds,
                           span);
     }
 
-    param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
+    bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
 
-    param_bounds
+    bounds
 }
 
 /// Converts a specific TyParamBound from the AST into a set of
@@ -2022,7 +2029,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
             let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
             projections.into_iter()
                        .map(|p| p.as_predicate())
-                       .chain(Some(pred.as_predicate()).into_iter())
+                       .chain(Some(pred.as_predicate()))
                        .collect()
         }
         ast::RegionTyParamBound(ref lifetime) => {
@@ -2053,7 +2060,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[ast::TyParamBound])
-                              -> ty::ParamBounds<'tcx>
+                              -> astconv::Bounds<'tcx>
 {
     let tcx = astconv.tcx();
     let astconv::PartitionedBounds {
@@ -2077,7 +2084,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
                      .map(|r| ast_region_to_region(tcx, r))
                      .collect();
 
-    ty::ParamBounds {
+    astconv::Bounds {
         region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: trait_bounds,
@@ -2092,7 +2099,7 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
-    for i in decl.inputs.iter() {
+    for i in &decl.inputs {
         match (*i).pat.node {
             ast::PatIdent(_, _, _) => (),
             ast::PatWild(ast::PatWildSingle) => (),
@@ -2170,8 +2177,8 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
     if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
         let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
         let base_type = match typ.sty {
-            ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
-            ty::ty_uniq(typ) => typ,
+            ty::TyRef(_, tm) => tm.ty,
+            ty::TyBox(typ) => typ,
             _ => typ,
         };
 
@@ -2197,12 +2204,12 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                 &ty::liberate_late_bound_regions(
                     tcx, body_scope, &ty::Binder(base_type)));
 
-        debug!("required_type={} required_type_free={} \
-                base_type={} base_type_free={}",
-               required_type.repr(tcx),
-               required_type_free.repr(tcx),
-               base_type.repr(tcx),
-               base_type_free.repr(tcx));
+        debug!("required_type={:?} required_type_free={:?} \
+                base_type={:?} base_type_free={:?}",
+               required_type,
+               required_type_free,
+               base_type,
+               base_type_free);
 
         let infcx = infer::new_infer_ctxt(tcx);
         drop(::require_same_types(tcx,
@@ -2213,10 +2220,10 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                                   required_type_free,
                                   || {
                 format!("mismatched self type: expected `{}`",
-                        ppaux::ty_to_string(tcx, required_type))
+                         required_type)
         }));
 
-        // We could conceviably add more free-reion relations here,
+        // We could conceviably add more free-region relations here,
         // but since this code is just concerned with checking that
         // the `&Self` types etc match up, it's not really necessary.
         // It would just allow people to be more approximate in some
@@ -2232,7 +2239,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         scope: region::DestructionScopeData,
         value: &T)
         -> T
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx>
     {
         /*!
          * Convert early-bound regions into free regions; normally this is done by
@@ -2283,7 +2290,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      idx: index as u32,
                                      name: ty_param.ident.name };
         if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
-            report_unused_parameter(tcx, ty_param.span, "type", &param_ty.user_string(tcx));
+            report_unused_parameter(tcx, ty_param.span, "type", &param_ty.to_string());
         }
     }
 
@@ -2291,12 +2298,12 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     let lifetimes_in_associated_types: HashSet<_> =
         impl_items.iter()
-                  .filter_map(|item| match item.node {
-                      ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
-                      ast::ConstImplItem(..) | ast::MethodImplItem(..) |
-                      ast::MacImplItem(..) => None,
+                  .map(|item| ty::impl_or_trait_item(tcx, local_def(item.id)))
+                  .filter_map(|item| match item {
+                      ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
+                      ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
                   })
-                  .flat_map(|ty| ctp::parameters_for_type(ty).into_iter())
+                  .flat_map(|ty| ctp::parameters_for_type(ty))
                   .filter_map(|p| match p {
                       ctp::Parameter::Type(_) => None,
                       ctp::Parameter::Region(r) => Some(r),
@@ -2313,7 +2320,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
             !input_parameters.contains(&ctp::Parameter::Region(region))
         {
             report_unused_parameter(tcx, lifetime_def.lifetime.span,
-                                    "lifetime", &region.name.user_string(tcx));
+                                    "lifetime", &region.name.to_string());
         }
     }
 
index 3c8aab8447a2f14e9d670360e4ae82809db3824f..b1580a74876c1f61109af0ec2093cf424e416c36 100644 (file)
@@ -19,10 +19,21 @@ pub enum Parameter {
     Region(ty::EarlyBoundRegion),
 }
 
+/// Returns the list of parameters that are constrained by the type `ty`
+/// - i.e. the value of each parameter in the list is uniquely determined
+/// by `ty` (see RFC 447).
 pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
-    ty.walk()
-      .flat_map(|ty| parameters_for_type_shallow(ty).into_iter())
-      .collect()
+    let mut result = vec![];
+    ty::maybe_walk_ty(ty, |t| {
+        if let ty::TyProjection(..) = t.sty {
+            false // projections are not injective.
+        } else {
+            result.append(&mut parameters_for_type_shallow(t));
+            // non-projection type constructors are injective.
+            true
+        }
+    });
+    result
 }
 
 pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>) -> Vec<Parameter> {
@@ -31,7 +42,7 @@ pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>) -> Vec<Par
 
     let type_parameters =
         trait_ref.substs.types.iter()
-                              .flat_map(|ty| parameters_for_type(ty).into_iter());
+                              .flat_map(|ty| parameters_for_type(ty));
 
     region_parameters.extend(type_parameters);
 
@@ -40,14 +51,14 @@ pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>) -> Vec<Par
 
 fn parameters_for_type_shallow<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
     match ty.sty {
-        ty::ty_param(ref d) =>
+        ty::TyParam(ref d) =>
             vec![Parameter::Type(d.clone())],
-        ty::ty_rptr(region, _) =>
+        ty::TyRef(region, _) =>
             parameters_for_region(region).into_iter().collect(),
-        ty::ty_struct(_, substs) |
-        ty::ty_enum(_, substs) =>
+        ty::TyStruct(_, substs) |
+        ty::TyEnum(_, substs) =>
             parameters_for_regions_in_substs(substs),
-        ty::ty_trait(ref data) =>
+        ty::TyTrait(ref data) =>
             parameters_for_regions_in_substs(&data.principal.skip_binder().substs),
         _ =>
             vec![],
index 58d0963274181153b923e7562b1f4d98ac4076df..16af8c6961ef67c45c615dbd9b55f897db54b9c3 100644 (file)
 
 register_long_diagnostics! {
 
+E0023: r##"
+A pattern used to match against an enum variant must provide a sub-pattern for
+each field of the enum variant. This error indicates that a pattern attempted to
+extract an incorrect number of fields from a variant.
+
+```
+enum Fruit {
+    Apple(String, String)
+    Pear(u32)
+}
+```
+
+Here the `Apple` variant has two fields, and should be matched against like so:
+
+```
+// Correct.
+match x {
+    Apple(a, b) => ...
+}
+```
+
+Matching with the wrong number of fields has no sensible interpretation:
+
+```
+// Incorrect.
+match x {
+    Apple(a) => ...,
+    Apple(a, b, c) => ...
+}
+```
+
+Check how many fields the enum was declared with and ensure that your pattern
+uses the same number.
+"##,
+
+E0024: r##"
+This error indicates that a pattern attempted to extract the fields of an enum
+variant with no fields. Here's a tiny example of this error:
+
+```
+// This enum has two variants.
+enum Number {
+    // This variant has no fields.
+    Zero,
+    // This variant has one field.
+    One(u32)
+}
+
+// Assuming x is a Number we can pattern match on its contents.
+match x {
+    Zero(inside) => ...,
+    One(inside) => ...
+}
+```
+
+The pattern match `Zero(inside)` is incorrect because the `Zero` variant
+contains no fields, yet the `inside` name attempts to bind the first field of
+the enum.
+"##,
+
+E0025: r##"
+Each field of a struct can only be bound once in a pattern. Each occurrence of a
+field name binds the value of that field, so to fix this error you will have to
+remove or alter the duplicate uses of the field name. Perhaps you misspelt
+another field name?
+"##,
+
+E0026: r##"
+This error indicates that a struct pattern attempted to extract a non-existant
+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.
+
+```
+// Correct matching.
+struct Thing {
+    x: u32,
+    y: u32
+}
+
+let thing = Thing { x: 1, y: 2 };
+match thing {
+    Thing { x: xfield, y: yfield } => ...
+}
+```
+
+If you are using shorthand field patterns but want to refer to the struct field
+by a different name, you should rename it explicitly.
+
+```
+// Change this:
+match thing {
+    Thing { x, z } => ...
+}
+
+// To this:
+match thing {
+    Thing { x, y: z } => ...
+}
+```
+"##,
+
+E0027: r##"
+This error indicates that a pattern for a struct fails to specify a sub-pattern
+for every one of the struct's fields. Ensure that each field from the struct's
+definition is mentioned in the pattern, or use `..` to ignore unwanted fields.
+
+For example:
+
+```
+struct Dog {
+    name: String,
+    age: u32
+}
+
+let d = Dog { name: "Rusty".to_string(), age: 8 };
+
+// This is incorrect.
+match d {
+    Dog { age: x } => ...
+}
+
+// This is correct (explicit).
+match d {
+    Dog { name: n, age: x } => ...
+}
+
+// This is also correct (ignore unused fields).
+match d {
+    Dog { age: x, .. } => ...
+}
+```
+"##,
+
+E0029: r##"
+In a match expression, only numbers and characters can be matched against a
+range. This is because the compiler checks that the range is non-empty at
+compile-time, and is unable to evaluate arbitrary comparison functions. If you
+want to capture values of an orderable type between two end-points, you can use
+a guard.
+
+```
+// The ordering relation for strings can't be evaluated at compile time,
+// so this doesn't work:
+match string {
+    "hello" ... "world" => ...
+    _ => ...
+}
+
+// This is a more general version, using a guard:
+match string {
+    s if s >= "hello" && s <= "world" => ...
+    _ => ...
+}
+```
+"##,
+
+E0030: r##"
+When matching against a range, the compiler verifies that the range is
+non-empty.  Range patterns include both end-points, so this is equivalent to
+requiring the start of the range to be less than or equal to the end of the
+range.
+
+For example:
+
+```
+match 5u32 {
+    // This range is ok, albeit pointless.
+    1 ... 1 => ...
+    // This range is empty, and the compiler can tell.
+    1000 ... 5 => ...
+}
+```
+"##,
+
+E0033: r##"
+This error indicates that a pointer to a trait type cannot be implicitly
+dereferenced by a pattern. Every trait defines a type, but because the
+size of trait implementors isn't fixed, this type has no compile-time size.
+Therefore, all accesses to trait types must be through pointers. If you
+encounter this error you should try to avoid dereferencing the pointer.
+
+```
+let trait_obj: &SomeTrait = ...;
+
+// This tries to implicitly dereference to create an unsized local variable.
+let &invalid = trait_obj;
+
+// You can call methods without binding to the value being pointed at.
+trait_obj.method_one();
+trait_obj.method_two();
+```
+
+You can read more about trait objects in the Trait Object section of the
+Reference:
+
+http://doc.rust-lang.org/reference.html#trait-objects
+"##,
+
+E0034: r##"
+The compiler doesn't know what method to call because more than one method
+has the same prototype. Example:
+
+```
+struct Test;
+
+trait Trait1 {
+    fn foo();
+}
+
+trait Trait2 {
+    fn foo();
+}
+
+impl Trait1 for Test { fn foo() {} }
+impl Trait2 for Test { fn foo() {} }
+
+fn main() {
+    Test::foo() // error, which foo() to call?
+}
+```
+
+To avoid this error, you have to keep only one of them and remove the others.
+So let's take our example and fix it:
+
+```
+struct Test;
+
+trait Trait1 {
+    fn foo();
+}
+
+impl Trait1 for Test { fn foo() {} }
+
+fn main() {
+    Test::foo() // and now that's good!
+}
+```
+
+However, a better solution would be using fully explicit naming of type and
+trait:
+
+```
+struct Test;
+
+trait Trait1 {
+    fn foo();
+}
+
+trait Trait2 {
+    fn foo();
+}
+
+impl Trait1 for Test { fn foo() {} }
+impl Trait2 for Test { fn foo() {} }
+
+fn main() {
+    <Test as Trait1>::foo()
+}
+```
+"##,
+
+E0035: r##"
+You tried to give a type parameter where it wasn't needed. Bad example:
+
+```
+struct Test;
+
+impl Test {
+    fn method(&self) {}
+}
+
+fn main() {
+    let x = Test;
+
+    x.method::<i32>(); // Error: Test::method doesn't need type parameter!
+}
+```
+
+To fix this error, just remove the type parameter:
+
+```
+struct Test;
+
+impl Test {
+    fn method(&self) {}
+}
+
+fn main() {
+    let x = Test;
+
+    x.method(); // OK, we're good!
+}
+```
+"##,
+
+E0036: r##"
+This error occurrs when you pass too many or not enough type parameters to
+a method. Example:
+
+```
+struct Test;
+
+impl Test {
+    fn method<T>(&self, v: &[T]) -> usize {
+        v.len()
+    }
+}
+
+fn main() {
+    let x = Test;
+    let v = &[0i32];
+
+    x.method::<i32, i32>(v); // error: only one type parameter is expected!
+}
+```
+
+To fix it, just specify a correct number of type parameters:
+
+```
+struct Test;
+
+impl Test {
+    fn method<T>(&self, v: &[T]) -> usize {
+        v.len()
+    }
+}
+
+fn main() {
+    let x = Test;
+    let v = &[0i32];
+
+    x.method::<i32>(v); // OK, we're good!
+}
+```
+
+Please note on the last example that we could have called `method` like this:
+
+```
+x.method(v);
+```
+"##,
+
+E0040: r##"
+It is not allowed to manually call destructors in Rust. It is also not
+necessary to do this since `drop` is called automatically whenever a value goes
+out of scope.
+
+Here's an example of this error:
+
+```
+struct Foo {
+    x: i32,
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("kaboom");
+    }
+}
+
+fn main() {
+    let mut x = Foo { x: -7 };
+    x.drop(); // error: explicit use of destructor method
+}
+```
+"##,
+
+E0045: r##"
+Rust only supports variadic parameters for interoperability with C code in its
+FFI. As such, variadic parameters can only be used with functions which are
+using the C ABI. Examples of erroneous code:
+
+```
+extern "rust-call" { fn foo(x: u8, ...); }
+// or
+fn foo(x: u8, ...) {}
+```
+
+To fix such code, put them in an extern "C" block:
+
+```
+extern "C" fn foo (x: u8, ...);
+// or:
+extern "C" {
+    fn foo (x: u8, ...);
+}
+```
+"##,
+
 E0046: r##"
 When trying to make some type implement a trait `Foo`, you must, at minimum,
 provide implementations for all of `Foo`'s required methods (meaning the
@@ -65,55 +455,164 @@ impl Foo for Bar {
 "##,
 
 E0053: r##"
-For any given method of a trait, the mutabilities of the parameters must match
-between the trait definition and the implementation.
+The parameters of any trait method must match between a trait implementation
+and the trait definition.
 
-Here's an example where the mutability of the `self` parameter is wrong:
+Here are a couple examples of this error:
 
 ```
-trait Foo { fn foo(&self); }
+trait Foo {
+    fn foo(x: u16);
+    fn bar(&self);
+}
 
 struct Bar;
 
 impl Foo for Bar {
-    // error, the signature should be `fn foo(&self)` instead
-    fn foo(&mut self) { }
+    // error, expected u16, found i16
+    fn foo(x: i16) { }
+
+    // error, values differ in mutability
+    fn bar(&mut self) { }
 }
+```
+"##,
+
+E0054: r##"
+It is not allowed to cast to a bool. If you are trying to cast a numeric type
+to a bool, you can compare it with zero instead:
 
-fn main() {}
 ```
+let x = 5;
 
-Here's another example, this time for a non-`self` parameter:
+// Ok
+let x_is_nonzero = x != 0;
 
+// Not allowed, won't compile
+let x_is_nonzero = x as bool;
 ```
-trait Foo { fn foo(x: &mut bool) -> bool; }
+"##,
 
-struct Bar;
+E0055: r##"
+During a method call, a value is automatically dereferenced as many times as
+needed to make the value's type match the method's receiver. The catch is that
+the compiler will only attempt to dereference a number of times up to the
+recursion limit (which can be set via the `recursion_limit` attribute).
 
-impl Foo for Bar {
-    // error, the type of `x` should be `&mut bool` instead
-    fn foo(x: &bool) -> bool { *x }
+For a somewhat artificial example:
+
+```
+#![recursion_limit="2"]
+
+struct Foo;
+
+impl Foo {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+    let ref_foo = &&Foo;
+
+    // error, reached the recursion limit while auto-dereferencing &&Foo
+    ref_foo.foo();
+}
+```
+
+One fix may be to increase the recursion limit. Note that it is possible to
+create an infinite recursion of dereferencing, in which case the only fix is to
+somehow break the recursion.
+"##,
+
+E0057: r##"
+When invoking closures or other implementations of the function traits `Fn`,
+`FnMut` or `FnOnce` using call notation, the number of parameters passed to the
+function must match its definition.
+
+An example using a closure:
+
+```
+let f = |x| x * 3;
+let a = f();        // invalid, too few parameters
+let b = f(4);       // this works!
+let c = f(2, 3);    // invalid, too many parameters
+```
+
+A generic function must be treated similarly:
+
+```
+fn foo<F: Fn()>(f: F) {
+    f(); // this is valid, but f(3) would not work
 }
+```
+"##,
+
+E0059: r##"
+The built-in function traits are generic over a tuple of the function arguments.
+If one uses angle-bracket notation (`Fn<(T,), Output=U>`) instead of parentheses
+(`Fn(T) -> U`) to denote the function trait, the type parameter should be a
+tuple. Otherwise function call notation cannot be used and the trait will not be
+implemented by closures.
 
-fn main() {}
+The most likely source of this error is using angle-bracket notation without
+wrapping the function argument type into a tuple, for example:
+
+```
+fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
 ```
 
+It can be fixed by adjusting the trait bound like this:
+
+```
+fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
+```
 
+Note that `(T,)` always denotes the type of a 1-tuple containing an element of
+type `T`. The comma is necessary for syntactic disambiguation.
 "##,
 
-E0054: r##"
-It is not allowed to cast to a bool. If you are trying to cast a numeric type
-to a bool, you can compare it with zero instead:
+E0060: r##"
+External C functions are allowed to be variadic. However, a variadic function
+takes a minimum number of arguments. For example, consider C's variadic `printf`
+function:
 
 ```
-let x = 5;
+extern crate libc;
+use libc::{ c_char, c_int };
 
-// Ok
-let x_is_nonzero = x != 0;
+extern "C" {
+    fn printf(_: *const c_char, ...) -> c_int;
+}
+```
+
+Using this declaration, it must be called with at least one argument, so
+simply calling `printf()` is illegal. But the following uses are allowed:
 
-// Not allowed, won't compile
-let x_is_nonzero = x as bool;
 ```
+unsafe {
+    use std::ffi::CString;
+
+    printf(CString::new("test\n").unwrap().as_ptr());
+    printf(CString::new("number = %d\n").unwrap().as_ptr(), 3);
+    printf(CString::new("%d, %d\n").unwrap().as_ptr(), 10, 5);
+}
+```
+"##,
+
+E0061: r##"
+The number of arguments passed to a function must match the number of arguments
+specified in the function signature.
+
+For example, a function like
+
+```
+fn f(a: u16, b: &str) {}
+```
+
+must always be called with exactly two arguments, e.g. `f(2, "test")`.
+
+Note, that Rust does not have a notion of optional function arguments or
+variadic functions (except for its C-FFI).
 "##,
 
 E0062: r##"
@@ -124,8 +623,8 @@ be specified exactly one time.
 
 E0063: r##"
 This error indicates that during an attempt to build a struct or struct-like
-enum variant, one of the fields was not provided. Each field should be specified
-exactly once.
+enum variant, one of the fields was not provided. Each field should be
+specified exactly once.
 "##,
 
 E0066: r##"
@@ -139,19 +638,36 @@ and [RFC 809] for more details.
 "##,
 
 E0067: r##"
-The left-hand side of an assignment operator must be an lvalue expression. An
-lvalue expression represents a memory location and includes item paths (ie,
-namespaced variables), dereferences, indexing expressions, and field references.
+The left-hand side of a compound assignment expression must be an lvalue
+expression. An lvalue expression represents a memory location and includes
+item paths (ie, namespaced variables), dereferences, indexing expressions,
+and field references.
 
+Let's start with some bad examples:
 ```
 use std::collections::LinkedList;
 
-// Good
-let mut list = LinkedList::new();
-
-
 // Bad: assignment to non-lvalue expression
 LinkedList::new() += 1;
+
+// ...
+
+fn some_func(i: &mut i32) {
+    i += 12; // Error : '+=' operation cannot be applied on a reference !
+}
+
+And now some good examples:
+```
+let mut i : i32 = 0;
+
+i += 12; // Good !
+
+// ...
+
+fn some_func(i: &mut i32) {
+    *i += 12; // Good !
+}
+
 ```
 "##,
 
@@ -170,6 +686,110 @@ Since `return;` is just like `return ();`, there is a mismatch between the
 function's return type and the value being returned.
 "##,
 
+E0070: r##"
+The left-hand side of an assignment operator must be an lvalue expression. An
+lvalue expression represents a memory location and can be a variable (with
+optional namespacing), a dereference, an indexing expression or a field
+reference.
+
+More details can be found here:
+https://doc.rust-lang.org/reference.html#lvalues,-rvalues-and-temporaries
+
+Now, we can go further. Here are some bad examples:
+```
+struct SomeStruct {
+    x: i32,
+    y: i32
+}
+const SOME_CONST : i32 = 12;
+
+fn some_other_func() {}
+
+fn some_function() {
+    SOME_CONST = 14; // error : a constant value cannot be changed!
+    1 = 3; // error : 1 isn't a valid lvalue!
+    some_other_func() = 4; // error : we can't assign value to a function!
+    SomeStruct.x = 12; // error : SomeStruct a structure name but it is used
+                       // like a variable!
+}
+```
+
+And now let's give good examples:
+
+```
+struct SomeStruct {
+    x: i32,
+    y: i32
+}
+let mut s = SomeStruct {x: 0, y: 0};
+
+s.x = 3; // that's good !
+
+// ...
+
+fn some_func(x: &mut i32) {
+    *x = 12; // that's good !
+}
+```
+"##,
+
+E0072: r##"
+When defining a recursive struct or enum, any use of the type being defined
+from inside the definition must occur behind a pointer (like `Box` or `&`).
+This is because structs and enums must have a well-defined size, and without
+the pointer the size of the type would need to be unbounded.
+
+Consider the following erroneous definition of a type for a list of bytes:
+
+```
+// error, illegal recursive struct type
+struct ListNode {
+    head: u8,
+    tail: Option<ListNode>,
+}
+```
+
+This type cannot have a well-defined size, because it needs to be arbitrarily
+large (since we would be able to nest `ListNode`s to any depth). Specifically,
+
+```plain
+size of `ListNode` = 1 byte for `head`
+                   + 1 byte for the discriminant of the `Option`
+                   + size of `ListNode`
+```
+
+One way to fix this is by wrapping `ListNode` in a `Box`, like so:
+
+```
+struct ListNode {
+    head: u8,
+    tail: Option<Box<ListNode>>,
+}
+```
+
+This works because `Box` is a pointer, so its size is well-known.
+"##,
+
+E0073: r##"
+You cannot define a struct (or enum) `Foo` that requires an instance of `Foo`
+in order to make a new `Foo` value. This is because there would be no way a
+first instance of `Foo` could be made to initialize another instance!
+
+Here's an example of a struct that has this problem:
+
+```
+struct Foo { x: Box<Foo> } // error
+```
+
+One fix is to use `Option`, like so:
+
+```
+struct Foo { x: Option<Box<Foo>> }
+```
+
+Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`.
+"##,
+
 E0081: r##"
 Enum discriminants are used to differentiate enum variants stored in memory.
 This error indicates that the same value was used for two or more variants,
@@ -245,6 +865,46 @@ enum Empty {}
 ```
 "##,
 
+E0087: r##"
+Too many type parameters were supplied for a function. For example:
+
+```
+fn foo<T>() {}
+
+fn main() {
+    foo::<f64, bool>(); // error, expected 1 parameter, found 2 parameters
+}
+```
+
+The number of supplied parameters much exactly match the number of defined type
+parameters.
+"##,
+
+E0089: r##"
+Not enough type parameters were supplied for a function. For example:
+
+```
+fn foo<T, U>() {}
+
+fn main() {
+    foo::<f64>(); // error, expected 2 parameters, found 1 parameter
+}
+```
+
+Note that if a function takes multiple type parameters but you want the compiler
+to infer some of them, you can use type placeholders:
+
+```
+fn foo<T, U>(x: T) {}
+
+fn main() {
+    let x: bool = true;
+    foo::<f64>(x);    // error, expected 2 parameters, found 1 parameter
+    foo::<_, f64>(x); // same as `foo::<bool, f64>(x)`
+}
+```
+"##,
+
 E0106: r##"
 This error indicates that a lifetime is missing from a type. If it is an error
 inside a function signature, the problem may be with failing to adhere to the
@@ -327,6 +987,45 @@ RFC. It is, however, [currently unimplemented][iss15872].
 [iss15872]: https://github.com/rust-lang/rust/issues/15872
 "##,
 
+E0116: r##"
+You can only define an inherent implementation for a type in the same crate
+where the type was defined. For example, an `impl` block as below is not allowed
+since `Vec` is defined in the standard library:
+
+```
+impl Vec<u8> { ... } // error
+```
+
+To fix this problem, you can do either of these things:
+
+ - define a trait that has the desired associated functions/types/constants and
+   implement the trait for the type in question
+ - define a new type wrapping the type and define an implementation on the new
+   type
+
+Note that using the `type` keyword does not work here because `type` only
+introduces a type alias:
+
+```
+type Bytes = Vec<u8>;
+
+impl Bytes { ... } // error, same as above
+```
+"##,
+
+E0121: r##"
+In order to be consistent with Rust's lack of global type inference, type
+placeholders are disallowed by design in item signatures.
+
+Examples of this error include:
+
+```
+fn foo() -> _ { 5 } // error, explicitly write out the return type instead
+
+static BAR: _ = "test"; // error, explicitly write out the type instead
+```
+"##,
+
 E0131: r##"
 It is not possible to define `main` with type parameters, or even with function
 parameters. When `main` is present, it must take no arguments and return `()`.
@@ -355,6 +1054,28 @@ return, for example with a `loop` that never breaks or a call to another
 diverging function (such as `panic!()`).
 "##,
 
+E0178: r##"
+In types, the `+` type operator has low precedence, so it is often necessary
+to use parentheses.
+
+For example:
+
+```
+trait Foo {}
+
+struct Bar<'a> {
+    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)
+    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)
+    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
+    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
+}
+```
+
+More details can be found in [RFC 438].
+
+[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
+"##,
+
 E0184: r##"
 Explicitly implementing both Drop and Copy for a type is currently disallowed.
 This feature can make some sense in theory, but the current implementation is
@@ -364,6 +1085,54 @@ it has been disabled for now.
 [iss20126]: https://github.com/rust-lang/rust/issues/20126
 "##,
 
+E0185: r##"
+An associated function for a trait was defined to be static, but an
+implementation of the trait declared the same function to be a method (i.e. to
+take a `self` parameter).
+
+Here's an example of this error:
+
+```
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    // error, method `foo` has a `&self` declaration in the impl, but not in
+    // the trait
+    fn foo(&self) {}
+}
+"##,
+
+E0186: r##"
+An associated function for a trait was defined to be a method (i.e. to take a
+`self` parameter), but an implementation of the trait declared the same function
+to be static.
+
+Here's an example of this error:
+
+```
+trait Foo {
+    fn foo(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    // error, method `foo` has a `&self` declaration in the trait, but not in
+    // the impl
+    fn foo() {}
+}
+"##,
+
+E0192: r##"
+Negative impls are only allowed for traits with default impls. For more
+information see the [opt-in builtin traits RFC](https://github.com/rust-lang/
+rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+"##,
+
 E0197: r##"
 Inherent implementations (one that do not implement a trait but provide
 methods associated with a type) are always safe because they are not
@@ -435,23 +1204,41 @@ unsafe impl Bar for Foo { }
 "##,
 
 E0201: r##"
-It is an error to define a method--a trait method or an inherent method--more
-than once.
+It is an error to define an associated function more than once.
 
-For example,
+For example:
 
 ```
 struct Foo(u8);
 
 impl Foo {
+    fn bar(&self) -> bool { self.0 > 5 }
+
+    // error: duplicate associated function
     fn bar() {}
+}
+
+trait Baz {
+    fn baz(&self) -> bool;
+}
+
+impl Baz for Foo {
+    fn baz(&self) -> bool { true }
 
     // error: duplicate method
-    fn bar(&self) -> bool { self.0 > 5 }
+    fn baz(&self) -> bool { self.0 > 5 }
 }
 ```
 "##,
 
+E0202: r##"
+Inherent associated types were part of [RFC 195] but are not yet implemented.
+See [the tracking issue][iss8995] for the status of this implementation.
+
+[RFC 195]: https://github.com/rust-lang/rfcs/pull/195
+[iss8995]: https://github.com/rust-lang/rust/issues/8995
+"##,
+
 E0204: r##"
 An attempt to implement the `Copy` trait for a struct failed because one of the
 fields does not implement `Copy`. To fix this, you must implement `Copy` for the
@@ -566,10 +1353,10 @@ const C: [u32; 0.0] = []; // error
 "##,
 
 E0250: r##"
-This means there was an error while evaluating the expression for the length of
-a fixed-size array type.
+There was an error while evaluating the expression for the length of a fixed-
+size array type.
 
-Some examples of code that produces this error are:
+Some examples of this error are:
 
 ```
 // divide by zero in the length expression
@@ -585,6 +1372,12 @@ const C: [u32; u8::MAX + f64::EPSILON] = [];
 ```
 "##,
 
+E0318: r##"
+Default impls for a trait must be located in the same crate where the trait was
+defined. For more information see the [opt-in builtin traits RFC](https://github
+.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+"##,
+
 E0322: r##"
 The `Sized` trait is a special trait built-in to the compiler for types with a
 constant size known at compile-time. This trait is automatically implemented
@@ -592,11 +1385,28 @@ for types as needed by the compiler, and it is currently disallowed to
 explicitly implement it for a type.
 "##,
 
+E0326: r##"
+The types of any associated constants in a trait implementation must match the
+types in the trait definition. This error indicates that there was a mismatch.
+
+Here's an example of this error:
+
+```
+trait Foo {
+    const BAR: bool;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    const BAR: u32 = 5; // error, expected bool, found u32
+}
+```
+"##,
+
 E0368: r##"
 This error indicates that a binary assignment operator like `+=` or `^=` was
-applied to the wrong types.
-
-A couple examples of this are as follows:
+applied to the wrong types. For example:
 
 ```
 let mut x: u16 = 5;
@@ -632,45 +1442,62 @@ 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
+"##,
+
+E0371: r##"
+When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
+definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
+`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by
+definition, so it is not useful to do this.
+
+Example:
+
+```
+trait Foo { fn foo(&self) { } }
+trait Bar: Foo { }
+trait Baz: Bar { }
+
+impl Bar for Baz { } // error, `Baz` implements `Bar` by definition
+impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo`
+impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz`
+impl Baz for Bar { } // Note: This is OK
+```
+"##,
+
+E0372: r##"
+Trying to implement a trait for a trait object (as in `impl Trait1 for
+Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
+[RFC 255] for more details on object safety rules.
+
+[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
+"##,
+
+E0379: r##"
+Trait methods cannot be declared `const` by design. For more information, see
+[RFC 911].
+
+[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
+"##,
+
+E0380: r##"
+Default impls are only allowed for traits with no methods or associated items.
+For more information see the [opt-in builtin traits RFC](https://github.com/rust
+-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
 "##
 
 }
 
 register_diagnostics! {
-    E0023,
-    E0024,
-    E0025,
-    E0026,
-    E0027,
-    E0029,
-    E0030,
-    E0031,
-    E0033,
-    E0034, // multiple applicable methods in scope
-    E0035, // does not take type parameters
-    E0036, // incorrect number of type parameters given for this method
-    E0040, // explicit use of destructor method
     E0044, // foreign items may not have type parameters
-    E0045, // variadic function must have C calling convention
-    E0055, // method has an incompatible type for trait
-    E0057, // method has an incompatible type for trait
-    E0059,
-    E0060,
-    E0061,
     E0068,
-    E0070,
     E0071,
-    E0072,
-    E0073,
     E0074,
     E0075,
     E0076,
     E0077,
     E0085,
     E0086,
-    E0087,
     E0088,
-    E0089,
     E0090,
     E0091,
     E0092,
@@ -680,12 +1507,10 @@ register_diagnostics! {
     E0102,
     E0103,
     E0104,
-    E0116,
     E0117,
     E0118,
     E0119,
     E0120,
-    E0121,
     E0122,
     E0123,
     E0124,
@@ -702,23 +1527,18 @@ register_diagnostics! {
     E0172,
     E0173, // manual implementations of unboxed closure traits are experimental
     E0174, // explicit use of unboxed closure methods are experimental
-    E0178,
     E0182,
     E0183,
-    E0185,
-    E0186,
     E0187, // can't infer the kind of the closure
-    E0188, // types differ in mutability
-    E0189, // can only cast a boxed pointer to a boxed object
-    E0190, // can only cast a &-pointer to an &-object
+    E0188, // can not cast a 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
     E0191, // value of the associated type must be specified
-    E0192, // negative imples are allowed just for `Send` and `Sync`
     E0193, // cannot bound type where clause bounds may only be attached to types
            // involving type parameters
     E0194,
     E0195, // lifetime parameters or bounds on method do not match the trait declaration
     E0196, // cannot determine a type for this closure
-    E0202, // associated items are not allowed in inherent impls
     E0203, // type parameter has more than one relaxed default bound,
            // and only one is supported
     E0207, // type parameter is not constrained by the impl trait, self type, or predicate
@@ -736,7 +1556,8 @@ register_diagnostics! {
     E0219, // associated type defined in higher-ranked supertrait
     E0220, // associated type not found for type parameter
     E0221, // ambiguous associated type in bounds
-    E0222, // variadic function must have C calling convention
+    //E0222, // Error code E0045 (variadic function must have C calling
+             // convention) duplicate
     E0223, // ambiguous associated type
     E0224, // at least one non-builtin train is required for an object type
     E0225, // only the builtin traits can be used as closure or object bounds
@@ -761,21 +1582,18 @@ register_diagnostics! {
     E0246, // illegal recursive type
     E0247, // found module name used as a type
     E0248, // found value name used as a type
-    E0318, // can't create default impls for traits outside their crates
     E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0321, // extended coherence rules for defaulted traits violated
     E0323, // implemented an associated const when another trait item expected
     E0324, // implemented a method when another trait item expected
     E0325, // implemented an associated type when another trait item expected
-    E0326, // associated const implemented with different type from trait
     E0327, // referred to method instead of constant in match pattern
     E0328, // cannot implement Unsize explicitly
+    E0329, // associated const depends on type parameter or Self.
     E0366, // dropck forbid specialization to concrete type or region
     E0367, // dropck forbid specialization to predicate not in struct/enum
     E0369, // binary operation `<op>` cannot be applied to types
-    E0371, // impl Trait for Trait is illegal
-    E0372, // impl Trait for Trait where Trait is not object safe
     E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with one field being coerced, none found
     E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
@@ -783,6 +1601,12 @@ register_diagnostics! {
            // fields need coercions
     E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures
-    E0377  // the trait `CoerceUnsized` may only be implemented for a coercion
+    E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
+    E0390, // only a single inherent implementation marked with
+           // `#[lang = \"{}\"]` is allowed for the `{}` primitive
+    E0391, // unsupported cyclic reference between types/traits detected
+    E0392, // parameter `{}` is never used
+    E0393  // the type parameter `{}` must be explicitly specified in an object
+           // type because its default value `{}` references the type `Self`"
 }
index e50693ea804b6993a852ea82bbcea5ae054dccb5..8feecd15613119931074cec6ad343c157bedb675 100644 (file)
@@ -70,19 +70,24 @@ This API is completely unstable and subject to change.
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![allow(non_camel_case_types)]
 
+#![feature(append)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(core)]
+#![feature(drain)]
+#![feature(iter_cmp)]
+#![feature(iter_arith)]
 #![feature(quote)]
+#![feature(ref_slice)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
+#![feature(slice_extras)]
 #![feature(staged_api)]
+#![feature(vec_push_all)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -101,14 +106,13 @@ use middle::def;
 use middle::infer;
 use middle::subst;
 use middle::ty::{self, Ty};
+use rustc::ast_map;
 use session::config;
 use util::common::time;
-use util::ppaux::Repr;
-use util::ppaux;
 
 use syntax::codemap::Span;
 use syntax::print::pprust::*;
-use syntax::{ast, ast_map, abi};
+use syntax::{ast, abi};
 use syntax::ast_util::local_def;
 
 use std::cell::RefCell;
@@ -117,13 +121,13 @@ use std::cell::RefCell;
 // registered before they are used.
 pub mod diagnostics;
 
-mod check;
+pub mod check;
 mod rscope;
 mod astconv;
-mod collect;
+pub mod collect;
 mod constrained_type_params;
-mod coherence;
-mod variance;
+pub mod coherence;
+pub mod variance;
 
 pub struct TypeAndSubsts<'tcx> {
     pub substs: subst::Substs<'tcx>,
@@ -132,18 +136,18 @@ pub struct TypeAndSubsts<'tcx> {
 
 pub struct CrateCtxt<'a, 'tcx: 'a> {
     // A mapping from method call sites to traits that have that method.
-    trait_map: ty::TraitMap,
+    pub trait_map: ty::TraitMap,
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
     /// error reporting, and so is lazily initialised and generally
     /// shouldn't taint the common path (hence the RefCell).
-    all_traits: RefCell<Option<check::method::AllTraitsVec>>,
-    tcx: &'a ty::ctxt<'tcx>,
+    pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
+    pub tcx: &'a ty::ctxt<'tcx>,
 }
 
 // Functions that write types into the node type table
 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
-    debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty));
+    debug!("write_ty_to_tcx({}, {:?})", node_id,  ty);
     assert!(!ty::type_needs_infer(ty));
     tcx.node_type_insert(node_id, ty);
 }
@@ -152,9 +156,9 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  node_id: ast::NodeId,
                                  item_substs: ty::ItemSubsts<'tcx>) {
     if !item_substs.is_noop() {
-        debug!("write_substs_to_tcx({}, {})",
+        debug!("write_substs_to_tcx({}, {:?})",
                node_id,
-               item_substs.repr(tcx));
+               item_substs);
 
         assert!(item_substs.substs.types.all(|t| !ty::type_needs_infer(*t)));
 
@@ -194,11 +198,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
     match result {
         Ok(_) => true,
         Err(ref terr) => {
-            span_err!(tcx.sess, span, E0211,
-                              "{}: {}",
-                                      msg(),
-                                      ty::type_err_to_str(tcx,
-                                                          terr));
+            span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
             ty::note_and_explain_type_err(tcx, terr, span);
             false
         }
@@ -211,11 +211,11 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
     let tcx = ccx.tcx;
     let main_t = ty::node_id_to_type(tcx, main_id);
     match main_t.sty {
-        ty::ty_bare_fn(..) => {
+        ty::TyBareFn(..) => {
             match tcx.map.find(main_id) {
                 Some(ast_map::NodeItem(it)) => {
                     match it.node {
-                        ast::ItemFn(_, _, _, ref ps, _)
+                        ast::ItemFn(_, _, _, _, ref ps, _)
                         if ps.is_parameterized() => {
                             span_err!(ccx.tcx.sess, main_span, E0131,
                                       "main function is not allowed to have type parameters");
@@ -239,15 +239,13 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
             require_same_types(tcx, None, false, main_span, main_t, se_ty,
                 || {
                     format!("main function expects type: `{}`",
-                            ppaux::ty_to_string(ccx.tcx, se_ty))
+                             se_ty)
                 });
         }
         _ => {
             tcx.sess.span_bug(main_span,
-                              &format!("main has a non-function type: found \
-                                       `{}`",
-                                      ppaux::ty_to_string(tcx,
-                                                       main_t)));
+                              &format!("main has a non-function type: found `{}`",
+                                       main_t));
         }
     }
 }
@@ -258,11 +256,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
     let tcx = ccx.tcx;
     let start_t = ty::node_id_to_type(tcx, start_id);
     match start_t.sty {
-        ty::ty_bare_fn(..) => {
+        ty::TyBareFn(..) => {
             match tcx.map.find(start_id) {
                 Some(ast_map::NodeItem(it)) => {
                     match it.node {
-                        ast::ItemFn(_,_,_,ref ps,_)
+                        ast::ItemFn(_,_,_,_,ref ps,_)
                         if ps.is_parameterized() => {
                             span_err!(tcx.sess, start_span, E0132,
                                       "start function is not allowed to have type parameters");
@@ -290,15 +288,14 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
             require_same_types(tcx, None, false, start_span, start_t, se_ty,
                 || {
                     format!("start function expects type: `{}`",
-                            ppaux::ty_to_string(ccx.tcx, se_ty))
+                             se_ty)
                 });
 
         }
         _ => {
             tcx.sess.span_bug(start_span,
-                              &format!("start has a non-function type: found \
-                                       `{}`",
-                                      ppaux::ty_to_string(tcx, start_t)));
+                              &format!("start has a non-function type: found `{}`",
+                                       start_t));
         }
     }
 }
@@ -344,7 +341,4 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     tcx.sess.abort_if_errors();
 }
 
-#[cfg(stage0)]
-__build_diagnostic_array! { DIAGNOSTICS }
-#[cfg(not(stage0))]
 __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }
index c908e21626e56eaa33c616f1ed044210a3ebdc3d..2dcb7a0efccd534160144cdb9d0b86ecdad85ca3 100644 (file)
@@ -36,6 +36,26 @@ pub trait RegionScope {
     /// be derived from the object traits, what should we use? If
     /// `None` is returned, an explicit annotation is required.
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
+
+    /// The "base" default is the initial default for a scope. This is
+    /// 'static except for in fn bodies, where it is a fresh inference
+    /// variable. You shouldn't call this except for as part of
+    /// computing `object_lifetime_default` (in particular, in legacy
+    /// modes, it may not be relevant).
+    fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
+
+    /// Used to issue warnings in Rust 1.2, not needed after that.
+    /// True if the result of `object_lifetime_default` will change in 1.3.
+    fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
+        false
+    }
+
+    /// Used to issue warnings in Rust 1.2, not needed after that.
+    /// True if the result of `base_object_lifetime_default` differs
+    /// from the result of `object_lifetime_default`.
+    fn base_object_lifetime_default_differs(&self) -> bool {
+        false
+    }
 }
 
 // A scope in which all regions must be explicitly named. This is used
@@ -44,16 +64,20 @@ pub trait RegionScope {
 pub struct ExplicitRscope;
 
 impl RegionScope for ExplicitRscope {
-    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
-        Some(ty::ReStatic)
-    }
-
     fn anon_regions(&self,
                     _span: Span,
                     _count: usize)
                     -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
         Err(None)
     }
+
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
+        ty::ReStatic
+    }
 }
 
 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
@@ -66,10 +90,6 @@ impl UnelidableRscope {
 }
 
 impl RegionScope for UnelidableRscope {
-    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
-        Some(ty::ReStatic)
-    }
-
     fn anon_regions(&self,
                     _span: Span,
                     _count: usize)
@@ -77,6 +97,14 @@ impl RegionScope for UnelidableRscope {
         let UnelidableRscope(ref v) = *self;
         Err(Some(v.clone()))
     }
+
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
+        ty::ReStatic
+    }
 }
 
 // A scope in which omitted anonymous region defaults to
@@ -94,11 +122,15 @@ impl ElidableRscope {
 }
 
 impl RegionScope for ElidableRscope {
-    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         // Per RFC #599, object-lifetimes default to 'static unless
         // overridden by context, and this takes precedence over
         // lifetime elision.
-        Some(ty::ReStatic)
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
+        ty::ReStatic
     }
 
     fn anon_regions(&self,
@@ -131,11 +163,15 @@ impl BindingRscope {
 }
 
 impl RegionScope for BindingRscope {
-    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         // Per RFC #599, object-lifetimes default to 'static unless
         // overridden by context, and this takes precedence over the
-        // binding defaults.
-        Some(ty::ReStatic)
+        // binding defaults in a fn signature.
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
+        ty::ReStatic
     }
 
     fn anon_regions(&self,
@@ -150,12 +186,12 @@ impl RegionScope for BindingRscope {
 /// A scope which overrides the default object lifetime but has no other effect.
 pub struct ObjectLifetimeDefaultRscope<'r> {
     base_scope: &'r (RegionScope+'r),
-    default: Option<ty::ObjectLifetimeDefault>,
+    default: ty::ObjectLifetimeDefault,
 }
 
 impl<'r> ObjectLifetimeDefaultRscope<'r> {
     pub fn new(base_scope: &'r (RegionScope+'r),
-               default: Option<ty::ObjectLifetimeDefault>)
+               default: ty::ObjectLifetimeDefault)
                -> ObjectLifetimeDefaultRscope<'r>
     {
         ObjectLifetimeDefaultRscope {
@@ -168,9 +204,49 @@ impl<'r> ObjectLifetimeDefaultRscope<'r> {
 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         match self.default {
-            None => self.base_scope.object_lifetime_default(span),
-            Some(ty::ObjectLifetimeDefault::Ambiguous) => None,
-            Some(ty::ObjectLifetimeDefault::Specific(r)) => Some(r),
+            ty::ObjectLifetimeDefault::Ambiguous =>
+                None,
+
+            ty::ObjectLifetimeDefault::BaseDefault =>
+                if false { // this will become the behavior in Rust 1.3
+                    Some(self.base_object_lifetime_default(span))
+                } else {
+                    self.base_scope.object_lifetime_default(span)
+                },
+
+            ty::ObjectLifetimeDefault::Specific(r) =>
+                Some(r),
+        }
+    }
+
+    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
+        assert!(false, "this code should not execute until Rust 1.3");
+        self.base_scope.base_object_lifetime_default(span)
+    }
+
+    fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
+        debug!("object_lifetime_default_will_change_in_1_3: {:?}", self.default);
+
+        match self.default {
+            ty::ObjectLifetimeDefault::Ambiguous |
+            ty::ObjectLifetimeDefault::Specific(_) =>
+                false,
+
+            ty::ObjectLifetimeDefault::BaseDefault =>
+                self.base_scope.base_object_lifetime_default_differs()
+        }
+    }
+
+    fn base_object_lifetime_default_differs(&self) -> bool {
+        debug!("base_object_lifetime_default_differs: {:?}", self.default);
+
+        match self.default {
+            ty::ObjectLifetimeDefault::Ambiguous |
+            ty::ObjectLifetimeDefault::Specific(_) =>
+                true,
+
+            ty::ObjectLifetimeDefault::BaseDefault =>
+                self.base_scope.base_object_lifetime_default_differs(),
         }
     }
 
@@ -201,6 +277,10 @@ impl<'r> RegionScope for ShiftedRscope<'r> {
             .map(|r| ty_fold::shift_region(r, 1))
     }
 
+    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
+        ty_fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
+    }
+
     fn anon_regions(&self,
                     span: Span,
                     count: usize)
index 7c062d354d395f2d2cf2408fee973a56be7cd74b..1f4e13436512179f729084b162d2d566b81e2a33 100644 (file)
@@ -270,15 +270,14 @@ use middle::resolve_lifetime as rl;
 use middle::subst;
 use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
 use middle::ty::{self, Ty};
+use rustc::ast_map;
 use std::fmt;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ast_map;
 use syntax::ast_util;
 use syntax::visit;
 use syntax::visit::Visitor;
 use util::nodemap::NodeMap;
-use util::ppaux::Repr;
 
 pub fn infer_variance(tcx: &ty::ctxt) {
     let krate = tcx.map.krate();
@@ -518,7 +517,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
-        debug!("add_inferreds for item {}", item.repr(self.tcx));
+        debug!("add_inferreds for item {}", self.tcx.map.node_to_string(item.id));
 
         match item.node {
             ast::ItemEnum(_, ref generics) |
@@ -600,8 +599,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
         let did = ast_util::local_def(item.id);
         let tcx = self.terms_cx.tcx;
 
-        debug!("visit_item item={}",
-               item.repr(tcx));
+        debug!("visit_item item={}", tcx.map.node_to_string(item.id));
 
         match item.node {
             ast::ItemEnum(ref enum_definition, _) => {
@@ -846,8 +844,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                       generics: &ty::Generics<'tcx>,
                                       trait_ref: ty::TraitRef<'tcx>,
                                       variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_trait_ref: trait_ref={} variance={:?}",
-               trait_ref.repr(self.tcx()),
+        debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
+               trait_ref,
                variance);
 
         let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
@@ -868,44 +866,44 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                generics: &ty::Generics<'tcx>,
                                ty: Ty<'tcx>,
                                variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_ty(ty={}, variance={:?})",
-               ty.repr(self.tcx()),
+        debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
+               ty,
                variance);
 
         match ty.sty {
-            ty::ty_bool |
-            ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
-            ty::ty_float(_) | ty::ty_str => {
+            ty::TyBool |
+            ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
+            ty::TyFloat(_) | ty::TyStr => {
                 /* leaf type -- noop */
             }
 
-            ty::ty_closure(..) => {
+            ty::TyClosure(..) => {
                 self.tcx().sess.bug("Unexpected closure type in variance computation");
             }
 
-            ty::ty_rptr(region, ref mt) => {
+            ty::TyRef(region, ref mt) => {
                 let contra = self.contravariant(variance);
                 self.add_constraints_from_region(generics, *region, contra);
                 self.add_constraints_from_mt(generics, mt, variance);
             }
 
-            ty::ty_uniq(typ) | ty::ty_vec(typ, _) => {
+            ty::TyBox(typ) | ty::TyArray(typ, _) | ty::TySlice(typ) => {
                 self.add_constraints_from_ty(generics, typ, variance);
             }
 
 
-            ty::ty_ptr(ref mt) => {
+            ty::TyRawPtr(ref mt) => {
                 self.add_constraints_from_mt(generics, mt, variance);
             }
 
-            ty::ty_tup(ref subtys) => {
+            ty::TyTuple(ref subtys) => {
                 for &subty in subtys {
                     self.add_constraints_from_ty(generics, subty, variance);
                 }
             }
 
-            ty::ty_enum(def_id, substs) |
-            ty::ty_struct(def_id, substs) => {
+            ty::TyEnum(def_id, substs) |
+            ty::TyStruct(def_id, substs) => {
                 let item_type = ty::lookup_item_type(self.tcx(), def_id);
 
                 // All type parameters on enums and structs should be
@@ -924,7 +922,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     variance);
             }
 
-            ty::ty_projection(ref data) => {
+            ty::TyProjection(ref data) => {
                 let trait_ref = &data.trait_ref;
                 let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
                 self.add_constraints_from_substs(
@@ -936,7 +934,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     variance);
             }
 
-            ty::ty_trait(ref data) => {
+            ty::TyTrait(ref data) => {
                 let poly_trait_ref =
                     data.principal_trait_ref_with_self_ty(self.tcx(),
                                                           self.tcx().types.err);
@@ -955,7 +953,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 }
             }
 
-            ty::ty_param(ref data) => {
+            ty::TyParam(ref data) => {
                 let def_id = generics.types.get(data.space, data.idx as usize).def_id;
                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
                 match self.terms_cx.inferred_map.get(&def_id.node) {
@@ -970,20 +968,19 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 }
             }
 
-            ty::ty_bare_fn(_, &ty::BareFnTy { ref sig, .. }) => {
+            ty::TyBareFn(_, &ty::BareFnTy { ref sig, .. }) => {
                 self.add_constraints_from_sig(generics, sig, variance);
             }
 
-            ty::ty_err => {
+            ty::TyError => {
                 // we encounter this when walking the trait references for object
-                // types, where we use ty_err as the Self type
+                // types, where we use TyError as the Self type
             }
 
-            ty::ty_infer(..) => {
+            ty::TyInfer(..) => {
                 self.tcx().sess.bug(
                     &format!("unexpected type encountered in \
-                            variance inference: {}",
-                            ty.repr(self.tcx())));
+                              variance inference: {}", ty));
             }
         }
     }
@@ -998,9 +995,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                    region_param_defs: &[ty::RegionParameterDef],
                                    substs: &subst::Substs<'tcx>,
                                    variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_substs(def_id={}, substs={}, variance={:?})",
-               def_id.repr(self.tcx()),
-               substs.repr(self.tcx()),
+        debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
+               def_id,
+               substs,
                variance);
 
         for p in type_param_defs {
@@ -1067,8 +1064,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.tcx()
                     .sess
                     .bug(&format!("unexpected region encountered in variance \
-                                  inference: {}",
-                                 region.repr(self.tcx())));
+                                  inference: {:?}",
+                                 region));
             }
         }
     }
@@ -1195,17 +1192,16 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                 types: types,
                 regions: regions
             };
-            debug!("item_id={} item_variances={}",
+            debug!("item_id={} item_variances={:?}",
                     item_id,
-                    item_variances.repr(tcx));
+                    item_variances);
 
             let item_def_id = ast_util::local_def(item_id);
 
             // For unit testing: check for a special "rustc_variance"
             // attribute and report an error with various results if found.
             if ty::has_attr(tcx, item_def_id, "rustc_variance") {
-                let found = item_variances.repr(tcx);
-                span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{}", &found[..]);
+                span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{:?}", item_variances);
             }
 
             let newly_added = tcx.item_variance_map.borrow_mut()
index 3118619220958a18c7b3b7799be624713d81b950..0ad5141c5bee69ff555e84018a32cede5656afd7 100644 (file)
@@ -29,7 +29,7 @@
 #![doc(primitive = "char")]
 
 use core::char::CharExt as C;
-use core::option::Option::{self, Some};
+use core::option::Option::{self, Some, None};
 use core::iter::Iterator;
 use tables::{derived_property, property, general_category, conversions, charwidth};
 
@@ -47,24 +47,79 @@ pub use tables::UNICODE_VERSION;
 /// the [`to_lowercase` method](../primitive.char.html#method.to_lowercase) on
 /// characters.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct ToLowercase(Option<char>);
+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.take() }
+    fn next(&mut self) -> Option<char> { self.0.next() }
 }
 
 /// An iterator over the uppercase mapping of a given character, returned from
 /// the [`to_uppercase` method](../primitive.char.html#method.to_uppercase) on
 /// characters.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct ToUppercase(Option<char>);
+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.take() }
+    fn next(&mut self) -> Option<char> { self.0.next() }
+}
+
+/// An iterator over the titlecase mapping of a given character, returned from
+/// the [`to_titlecase` method](../primitive.char.html#method.to_titlecase) on
+/// characters.
+#[unstable(feature = "unicode", reason = "recently added")]
+pub struct ToTitlecase(CaseMappingIter);
+
+#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
+impl Iterator for ToTitlecase {
+    type Item = char;
+    fn next(&mut self) -> Option<char> { self.0.next() }
+}
+
+
+enum CaseMappingIter {
+    Three(char, char, char),
+    Two(char, char),
+    One(char),
+    Zero
+}
+
+impl CaseMappingIter {
+    fn new(chars: [char; 3]) -> CaseMappingIter {
+        if chars[2] == '\0' {
+            if chars[1] == '\0' {
+                CaseMappingIter::One(chars[0])  // Including if chars[0] == '\0'
+            } else {
+                CaseMappingIter::Two(chars[0], chars[1])
+            }
+        } else {
+            CaseMappingIter::Three(chars[0], chars[1], chars[2])
+        }
+    }
+}
+
+impl Iterator for CaseMappingIter {
+    type Item = char;
+    fn next(&mut self) -> Option<char> {
+        match *self {
+            CaseMappingIter::Three(a, b, c) => {
+                *self = CaseMappingIter::Two(b, c);
+                Some(a)
+            }
+            CaseMappingIter::Two(b, c) => {
+                *self = CaseMappingIter::One(c);
+                Some(b)
+            }
+            CaseMappingIter::One(c) => {
+                *self = CaseMappingIter::Zero;
+                Some(c)
+            }
+            CaseMappingIter::Zero => None,
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -119,6 +174,7 @@ impl char {
     /// assert_eq!('f'.to_digit(16), Some(15));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     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
@@ -131,22 +187,16 @@ impl char {
     /// # Examples
     ///
     /// ```
-    /// for i in '❤'.escape_unicode() {
-    ///     println!("{}", i);
+    /// for c in '❤'.escape_unicode() {
+    ///     print!("{}", c);
     /// }
+    /// println!("");
     /// ```
     ///
     /// This prints:
     ///
     /// ```text
-    /// \
-    /// u
-    /// {
-    /// 2
-    /// 7
-    /// 6
-    /// 4
-    /// }
+    /// \u{2764}
     /// ```
     ///
     /// Collecting into a `String`:
@@ -157,6 +207,7 @@ impl char {
     /// assert_eq!(heart, r"\u{2764}");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) }
 
     /// Returns an iterator that yields the 'default' ASCII and
@@ -195,6 +246,7 @@ impl char {
     /// assert_eq!(quote, "\\\"");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) }
 
     /// Returns the number of bytes this character would need if encoded in
@@ -208,6 +260,7 @@ impl char {
     /// assert_eq!(n, 2);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn len_utf8(self) -> usize { C::len_utf8(self) }
 
     /// Returns the number of 16-bit code units this character would need if
@@ -221,6 +274,7 @@ impl char {
     /// assert_eq!(n, 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn len_utf16(self) -> usize { C::len_utf16(self) }
 
     /// Encodes this character as UTF-8 into the provided byte buffer, and then
@@ -255,7 +309,10 @@ impl char {
     /// ```
     #[unstable(feature = "unicode",
                reason = "pending decision about Iterator/Writer/Reader")]
-    pub fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> { C::encode_utf8(self, dst) }
+    #[inline]
+    pub fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> {
+        C::encode_utf8(self, dst)
+    }
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer, and
     /// then returns the number of `u16`s written.
@@ -289,7 +346,10 @@ impl char {
     /// ```
     #[unstable(feature = "unicode",
                reason = "pending decision about Iterator/Writer/Reader")]
-    pub fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> { C::encode_utf16(self, dst) }
+    #[inline]
+    pub fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> {
+        C::encode_utf16(self, dst)
+    }
 
     /// Returns whether the specified character is considered a Unicode
     /// alphabetic code point.
@@ -397,27 +457,54 @@ impl char {
 
     /// Converts a character to its lowercase equivalent.
     ///
-    /// The case-folding performed is the common or simple mapping. See
-    /// `to_uppercase()` for references and more information.
+    /// This performs complex unconditional mappings with no tailoring.
+    /// See `to_uppercase()` for references and more information.
     ///
     /// # Return value
     ///
     /// Returns an iterator which yields the characters corresponding to the
     /// lowercase equivalent of the character. If no conversion is possible then
-    /// the input character is returned.
+    /// an iterator with just the input character is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Some('c'), 'C'.to_lowercase().next());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_lowercase(self) -> ToLowercase {
-        ToLowercase(Some(conversions::to_lower(self)))
+        ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
+    }
+
+    /// Converts a character to its titlecase equivalent.
+    ///
+    /// This performs complex unconditional mappings with no tailoring.
+    /// See `to_uppercase()` for references and more information.
+    ///
+    /// This differs from `to_uppercase()` since Unicode contains
+    /// digraphs and ligature characters.
+    /// For example, U+01F3 “dz” and U+FB01 “fi”
+    /// map to U+01F1 “DZ” and U+0046 U+0069 “Fi”, respectively.
+    ///
+    /// # Return value
+    ///
+    /// Returns an iterator which yields the characters corresponding to the
+    /// titlecase equivalent of the character. If no conversion is possible then
+    /// an iterator with just the input character is returned.
+    #[unstable(feature = "unicode", reason = "recently added")]
+    #[inline]
+    pub fn to_titlecase(self) -> ToTitlecase {
+        ToTitlecase(CaseMappingIter::new(conversions::to_title(self)))
     }
 
     /// Converts a character to its uppercase equivalent.
     ///
-    /// The case-folding performed is the common or simple mapping: it maps
-    /// one Unicode codepoint to its uppercase equivalent according to the
-    /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet
-    /// considered here, but the iterator returned will soon support this form
-    /// of case folding.
+    /// 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 considerd here.
     ///
     /// A full reference can be found here [2].
     ///
@@ -425,17 +512,23 @@ impl char {
     ///
     /// Returns an iterator which yields the characters corresponding to the
     /// uppercase equivalent of the character. If no conversion is possible then
-    /// the input character is returned.
+    /// an iterator with just the input character is returned.
     ///
     /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
     ///
-    /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+    /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+    ///
+    /// [2]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
     ///
-    /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Some('C'), 'c'.to_uppercase().next());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_uppercase(self) -> ToUppercase {
-        ToUppercase(Some(conversions::to_upper(self)))
+        ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
     }
 
     /// Returns this character's displayed width in columns, or `None` if it is a
@@ -451,5 +544,8 @@ impl char {
                  since = "1.0.0")]
     #[unstable(feature = "unicode",
                reason = "needs expert opinion. is_cjk flag stands out as ugly")]
-    pub fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) }
+    #[inline]
+    pub fn width(self, is_cjk: bool) -> Option<usize> {
+        charwidth::width(self, is_cjk)
+    }
 }
index edfa8db311f358d7da8bd1ab0c4a38545b9478eb..b420444d1f5c813b440e6ebcfbaa0ba624a7d3d4 100644 (file)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "rustc_unicode"]
 #![unstable(feature = "unicode")]
-#![feature(lang_items)]
-#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
-       html_playground_url = "http://play.rust-lang.org/")]
-#![feature(no_std)]
+       html_playground_url = "http://play.rust-lang.org/",
+       test(no_crate_inject))]
 #![no_std]
+
 #![feature(core)]
-#![doc(test(no_crate_inject))]
+#![feature(core_char_ext)]
+#![feature(core_prelude)]
+#![feature(core_slice_ext)]
+#![feature(core_str_ext)]
+#![feature(iter_arith)]
+#![feature(lang_items)]
+#![feature(no_std)]
+#![feature(staged_api)]
 
 extern crate core;
 
@@ -49,3 +55,8 @@ pub mod str {
     pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item};
     pub use u_str::{utf16_items, Utf16Encoder};
 }
+
+// For use in libcollections, not re-exported in libstd.
+pub mod derived_property {
+    pub use tables::derived_property::{Cased, Case_Ignorable};
+}
index 3343bc401835c882780aee2c21f0be29c52172eb..4ebb6a70d291c300cc588ca9aadc7e111be598d2 100644 (file)
@@ -28,7 +28,7 @@ fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
 
 pub mod general_category {
     pub const Cc_table: &'static [(char, char)] = &[
-        ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}')
+        ('\0', '\u{1f}'), ('\u{7f}', '\u{9f}')
     ];
 
     pub fn Cc(c: char) -> bool {
@@ -251,6 +251,157 @@ pub mod derived_property {
         super::bsearch_range_table(c, Alphabetic_table)
     }
 
+    pub const Case_Ignorable_table: &'static [(char, char)] = &[
+        ('\u{27}', '\u{27}'), ('\u{2e}', '\u{2e}'), ('\u{3a}', '\u{3a}'), ('\u{5e}', '\u{5e}'),
+        ('\u{60}', '\u{60}'), ('\u{a8}', '\u{a8}'), ('\u{ad}', '\u{ad}'), ('\u{af}', '\u{af}'),
+        ('\u{b4}', '\u{b4}'), ('\u{b7}', '\u{b8}'), ('\u{2b0}', '\u{36f}'), ('\u{374}', '\u{375}'),
+        ('\u{37a}', '\u{37a}'), ('\u{384}', '\u{385}'), ('\u{387}', '\u{387}'), ('\u{483}',
+        '\u{489}'), ('\u{559}', '\u{559}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'),
+        ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{5f4}',
+        '\u{5f4}'), ('\u{600}', '\u{605}'), ('\u{610}', '\u{61a}'), ('\u{61c}', '\u{61c}'),
+        ('\u{640}', '\u{640}'), ('\u{64b}', '\u{65f}'), ('\u{670}', '\u{670}'), ('\u{6d6}',
+        '\u{6dd}'), ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{70f}', '\u{70f}'),
+        ('\u{711}', '\u{711}'), ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}',
+        '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), ('\u{816}', '\u{82d}'), ('\u{859}', '\u{85b}'),
+        ('\u{8e4}', '\u{902}'), ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}',
+        '\u{948}'), ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'),
+        ('\u{971}', '\u{971}'), ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9c1}',
+        '\u{9c4}'), ('\u{9cd}', '\u{9cd}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'),
+        ('\u{a3c}', '\u{a3c}'), ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}',
+        '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'), ('\u{a75}', '\u{a75}'),
+        ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'), ('\u{ac1}', '\u{ac5}'), ('\u{ac7}',
+        '\u{ac8}'), ('\u{acd}', '\u{acd}'), ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b01}'),
+        ('\u{b3c}', '\u{b3c}'), ('\u{b3f}', '\u{b3f}'), ('\u{b41}', '\u{b44}'), ('\u{b4d}',
+        '\u{b4d}'), ('\u{b56}', '\u{b56}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'),
+        ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{c00}', '\u{c00}'), ('\u{c3e}',
+        '\u{c40}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
+        ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c81}'), ('\u{cbc}', '\u{cbc}'), ('\u{cbf}',
+        '\u{cbf}'), ('\u{cc6}', '\u{cc6}'), ('\u{ccc}', '\u{ccd}'), ('\u{ce2}', '\u{ce3}'),
+        ('\u{d01}', '\u{d01}'), ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'), ('\u{d62}',
+        '\u{d63}'), ('\u{dca}', '\u{dca}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+        ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'), ('\u{e46}', '\u{e4e}'), ('\u{eb1}',
+        '\u{eb1}'), ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'), ('\u{f37}',
+        '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f71}', '\u{f7e}'), ('\u{f80}', '\u{f84}'),
+        ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{fc6}',
+        '\u{fc6}'), ('\u{102d}', '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}', '\u{103a}'),
+        ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'), ('\u{105e}', '\u{1060}'), ('\u{1071}',
+        '\u{1074}'), ('\u{1082}', '\u{1082}'), ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'),
+        ('\u{109d}', '\u{109d}'), ('\u{10fc}', '\u{10fc}'), ('\u{135d}', '\u{135f}'), ('\u{1712}',
+        '\u{1714}'), ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}', '\u{1773}'),
+        ('\u{17b4}', '\u{17b5}'), ('\u{17b7}', '\u{17bd}'), ('\u{17c6}', '\u{17c6}'), ('\u{17c9}',
+        '\u{17d3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dd}', '\u{17dd}'), ('\u{180b}', '\u{180e}'),
+        ('\u{1843}', '\u{1843}'), ('\u{18a9}', '\u{18a9}'), ('\u{1920}', '\u{1922}'), ('\u{1927}',
+        '\u{1928}'), ('\u{1932}', '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}', '\u{1a18}'),
+        ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'), ('\u{1a58}', '\u{1a5e}'), ('\u{1a60}',
+        '\u{1a60}'), ('\u{1a62}', '\u{1a62}'), ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'),
+        ('\u{1a7f}', '\u{1a7f}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}',
+        '\u{1b03}'), ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'), ('\u{1b3c}', '\u{1b3c}'),
+        ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}',
+        '\u{1ba5}'), ('\u{1ba8}', '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}', '\u{1be6}'),
+        ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bef}', '\u{1bf1}'), ('\u{1c2c}',
+        '\u{1c33}'), ('\u{1c36}', '\u{1c37}'), ('\u{1c78}', '\u{1c7d}'), ('\u{1cd0}', '\u{1cd2}'),
+        ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}',
+        '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1d2c}', '\u{1d6a}'), ('\u{1d78}', '\u{1d78}'),
+        ('\u{1d9b}', '\u{1df5}'), ('\u{1dfc}', '\u{1dff}'), ('\u{1fbd}', '\u{1fbd}'), ('\u{1fbf}',
+        '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'), ('\u{1fdd}', '\u{1fdf}'), ('\u{1fed}', '\u{1fef}'),
+        ('\u{1ffd}', '\u{1ffe}'), ('\u{200b}', '\u{200f}'), ('\u{2018}', '\u{2019}'), ('\u{2024}',
+        '\u{2024}'), ('\u{2027}', '\u{2027}'), ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{2064}'),
+        ('\u{2066}', '\u{206f}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}',
+        '\u{209c}'), ('\u{20d0}', '\u{20f0}'), ('\u{2c7c}', '\u{2c7d}'), ('\u{2cef}', '\u{2cf1}'),
+        ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}',
+        '\u{2e2f}'), ('\u{3005}', '\u{3005}'), ('\u{302a}', '\u{302d}'), ('\u{3031}', '\u{3035}'),
+        ('\u{303b}', '\u{303b}'), ('\u{3099}', '\u{309e}'), ('\u{30fc}', '\u{30fe}'), ('\u{a015}',
+        '\u{a015}'), ('\u{a4f8}', '\u{a4fd}'), ('\u{a60c}', '\u{a60c}'), ('\u{a66f}', '\u{a672}'),
+        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a67f}'), ('\u{a69c}', '\u{a69d}'), ('\u{a69f}',
+        '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'), ('\u{a700}', '\u{a721}'), ('\u{a770}', '\u{a770}'),
+        ('\u{a788}', '\u{a78a}'), ('\u{a7f8}', '\u{a7f9}'), ('\u{a802}', '\u{a802}'), ('\u{a806}',
+        '\u{a806}'), ('\u{a80b}', '\u{a80b}'), ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'),
+        ('\u{a8e0}', '\u{a8f1}'), ('\u{a926}', '\u{a92d}'), ('\u{a947}', '\u{a951}'), ('\u{a980}',
+        '\u{a982}'), ('\u{a9b3}', '\u{a9b3}'), ('\u{a9b6}', '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'),
+        ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e5}', '\u{a9e6}'), ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}',
+        '\u{aa32}'), ('\u{aa35}', '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4c}'),
+        ('\u{aa70}', '\u{aa70}'), ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}',
+        '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'), ('\u{aac1}', '\u{aac1}'),
+        ('\u{aadd}', '\u{aadd}'), ('\u{aaec}', '\u{aaed}'), ('\u{aaf3}', '\u{aaf4}'), ('\u{aaf6}',
+        '\u{aaf6}'), ('\u{ab5b}', '\u{ab5f}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}', '\u{abe8}'),
+        ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'), ('\u{fbb2}', '\u{fbc1}'), ('\u{fe00}',
+        '\u{fe0f}'), ('\u{fe13}', '\u{fe13}'), ('\u{fe20}', '\u{fe2d}'), ('\u{fe52}', '\u{fe52}'),
+        ('\u{fe55}', '\u{fe55}'), ('\u{feff}', '\u{feff}'), ('\u{ff07}', '\u{ff07}'), ('\u{ff0e}',
+        '\u{ff0e}'), ('\u{ff1a}', '\u{ff1a}'), ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'),
+        ('\u{ff70}', '\u{ff70}'), ('\u{ff9e}', '\u{ff9f}'), ('\u{ffe3}', '\u{ffe3}'), ('\u{fff9}',
+        '\u{fffb}'), ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}',
+        '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
+        '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'), ('\u{10ae5}',
+        '\u{10ae6}'), ('\u{11001}', '\u{11001}'), ('\u{11038}', '\u{11046}'), ('\u{1107f}',
+        '\u{11081}'), ('\u{110b3}', '\u{110b6}'), ('\u{110b9}', '\u{110ba}'), ('\u{110bd}',
+        '\u{110bd}'), ('\u{11100}', '\u{11102}'), ('\u{11127}', '\u{1112b}'), ('\u{1112d}',
+        '\u{11134}'), ('\u{11173}', '\u{11173}'), ('\u{11180}', '\u{11181}'), ('\u{111b6}',
+        '\u{111be}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}', '\u{11234}'), ('\u{11236}',
+        '\u{11237}'), ('\u{112df}', '\u{112df}'), ('\u{112e3}', '\u{112ea}'), ('\u{11301}',
+        '\u{11301}'), ('\u{1133c}', '\u{1133c}'), ('\u{11340}', '\u{11340}'), ('\u{11366}',
+        '\u{1136c}'), ('\u{11370}', '\u{11374}'), ('\u{114b3}', '\u{114b8}'), ('\u{114ba}',
+        '\u{114ba}'), ('\u{114bf}', '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115b2}',
+        '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}', '\u{115c0}'), ('\u{11633}',
+        '\u{1163a}'), ('\u{1163d}', '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}',
+        '\u{116ab}'), ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', '\u{116b5}'), ('\u{116b7}',
+        '\u{116b7}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b30}', '\u{16b36}'), ('\u{16b40}',
+        '\u{16b43}'), ('\u{16f8f}', '\u{16f9f}'), ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1bca0}',
+        '\u{1bca3}'), ('\u{1d167}', '\u{1d169}'), ('\u{1d173}', '\u{1d182}'), ('\u{1d185}',
+        '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'), ('\u{1e8d0}',
+        '\u{1e8d6}'), ('\u{e0001}', '\u{e0001}'), ('\u{e0020}', '\u{e007f}'), ('\u{e0100}',
+        '\u{e01ef}')
+    ];
+
+    pub fn Case_Ignorable(c: char) -> bool {
+        super::bsearch_range_table(c, Case_Ignorable_table)
+    }
+
+    pub const Cased_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
+        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'),
+        ('\u{1bc}', '\u{1bf}'), ('\u{1c4}', '\u{293}'), ('\u{295}', '\u{2b8}'), ('\u{2c0}',
+        '\u{2c1}'), ('\u{2e0}', '\u{2e4}'), ('\u{345}', '\u{345}'), ('\u{370}', '\u{373}'),
+        ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{386}',
+        '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'),
+        ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}',
+        '\u{556}'), ('\u{561}', '\u{587}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'),
+        ('\u{10cd}', '\u{10cd}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}', '\u{1f15}'), ('\u{1f18}',
+        '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'),
+        ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
+        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'),
+        ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
+        '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'),
+        ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}',
+        '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'),
+        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}',
+        '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2134}'), ('\u{2139}', '\u{2139}'),
+        ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}',
+        '\u{217f}'), ('\u{2183}', '\u{2184}'), ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2c2e}'),
+        ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}',
+        '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'),
+        ('\u{a640}', '\u{a66d}'), ('\u{a680}', '\u{a69d}'), ('\u{a722}', '\u{a787}'), ('\u{a78b}',
+        '\u{a78e}'), ('\u{a790}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b1}'), ('\u{a7f8}', '\u{a7fa}'),
+        ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab5f}'), ('\u{ab64}', '\u{ab65}'), ('\u{fb00}',
+        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
+        ('\u{10400}', '\u{1044f}'), ('\u{118a0}', '\u{118df}'), ('\u{1d400}', '\u{1d454}'),
+        ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
+        ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'),
+        ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'),
+        ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
+        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
+        ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'),
+        ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'),
+        ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'),
+        ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
+        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1f130}', '\u{1f149}'),
+        ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}')
+    ];
+
+    pub fn Cased(c: char) -> bool {
+        super::bsearch_range_table(c, Cased_table)
+    }
+
     pub const Lowercase_table: &'static [(char, char)] = &[
         ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'),
         ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'),
@@ -3726,21 +3877,28 @@ pub mod conversions {
     use core::option::Option::{Some, None};
     use core::result::Result::{Ok, Err};
 
-    pub fn to_lower(c: char) -> char {
-        match bsearch_case_table(c, LuLl_table) {
-          None        => c,
-          Some(index) => LuLl_table[index].1
+    pub fn to_lower(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_lowercase_table) {
+          None        => [c, '\0', '\0'],
+          Some(index) => to_lowercase_table[index].1
+        }
+    }
+
+    pub fn to_upper(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_uppercase_table) {
+            None        => [c, '\0', '\0'],
+            Some(index) => to_uppercase_table[index].1
         }
     }
 
-    pub fn to_upper(c: char) -> char {
-        match bsearch_case_table(c, LlLu_table) {
-            None        => c,
-            Some(index) => LlLu_table[index].1
+    pub fn to_title(c: char) -> [char; 3] {
+        match bsearch_case_table(c, to_titlecase_table) {
+            None        => [c, '\0', '\0'],
+            Some(index) => to_titlecase_table[index].1
         }
     }
 
-    fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<usize> {
+    fn bsearch_case_table(c: char, table: &'static [(char, [char; 3])]) -> Option<usize> {
         match table.binary_search_by(|&(key, _)| {
             if c == key { Equal }
             else if key < c { Less }
@@ -3751,606 +3909,1527 @@ pub mod conversions {
         }
     }
 
-    const LuLl_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{61}'), ('\u{42}', '\u{62}'), ('\u{43}', '\u{63}'), ('\u{44}', '\u{64}'),
-        ('\u{45}', '\u{65}'), ('\u{46}', '\u{66}'), ('\u{47}', '\u{67}'), ('\u{48}', '\u{68}'),
-        ('\u{49}', '\u{69}'), ('\u{4a}', '\u{6a}'), ('\u{4b}', '\u{6b}'), ('\u{4c}', '\u{6c}'),
-        ('\u{4d}', '\u{6d}'), ('\u{4e}', '\u{6e}'), ('\u{4f}', '\u{6f}'), ('\u{50}', '\u{70}'),
-        ('\u{51}', '\u{71}'), ('\u{52}', '\u{72}'), ('\u{53}', '\u{73}'), ('\u{54}', '\u{74}'),
-        ('\u{55}', '\u{75}'), ('\u{56}', '\u{76}'), ('\u{57}', '\u{77}'), ('\u{58}', '\u{78}'),
-        ('\u{59}', '\u{79}'), ('\u{5a}', '\u{7a}'), ('\u{c0}', '\u{e0}'), ('\u{c1}', '\u{e1}'),
-        ('\u{c2}', '\u{e2}'), ('\u{c3}', '\u{e3}'), ('\u{c4}', '\u{e4}'), ('\u{c5}', '\u{e5}'),
-        ('\u{c6}', '\u{e6}'), ('\u{c7}', '\u{e7}'), ('\u{c8}', '\u{e8}'), ('\u{c9}', '\u{e9}'),
-        ('\u{ca}', '\u{ea}'), ('\u{cb}', '\u{eb}'), ('\u{cc}', '\u{ec}'), ('\u{cd}', '\u{ed}'),
-        ('\u{ce}', '\u{ee}'), ('\u{cf}', '\u{ef}'), ('\u{d0}', '\u{f0}'), ('\u{d1}', '\u{f1}'),
-        ('\u{d2}', '\u{f2}'), ('\u{d3}', '\u{f3}'), ('\u{d4}', '\u{f4}'), ('\u{d5}', '\u{f5}'),
-        ('\u{d6}', '\u{f6}'), ('\u{d8}', '\u{f8}'), ('\u{d9}', '\u{f9}'), ('\u{da}', '\u{fa}'),
-        ('\u{db}', '\u{fb}'), ('\u{dc}', '\u{fc}'), ('\u{dd}', '\u{fd}'), ('\u{de}', '\u{fe}'),
-        ('\u{100}', '\u{101}'), ('\u{102}', '\u{103}'), ('\u{104}', '\u{105}'), ('\u{106}',
-        '\u{107}'), ('\u{108}', '\u{109}'), ('\u{10a}', '\u{10b}'), ('\u{10c}', '\u{10d}'),
-        ('\u{10e}', '\u{10f}'), ('\u{110}', '\u{111}'), ('\u{112}', '\u{113}'), ('\u{114}',
-        '\u{115}'), ('\u{116}', '\u{117}'), ('\u{118}', '\u{119}'), ('\u{11a}', '\u{11b}'),
-        ('\u{11c}', '\u{11d}'), ('\u{11e}', '\u{11f}'), ('\u{120}', '\u{121}'), ('\u{122}',
-        '\u{123}'), ('\u{124}', '\u{125}'), ('\u{126}', '\u{127}'), ('\u{128}', '\u{129}'),
-        ('\u{12a}', '\u{12b}'), ('\u{12c}', '\u{12d}'), ('\u{12e}', '\u{12f}'), ('\u{130}',
-        '\u{69}'), ('\u{132}', '\u{133}'), ('\u{134}', '\u{135}'), ('\u{136}', '\u{137}'),
-        ('\u{139}', '\u{13a}'), ('\u{13b}', '\u{13c}'), ('\u{13d}', '\u{13e}'), ('\u{13f}',
-        '\u{140}'), ('\u{141}', '\u{142}'), ('\u{143}', '\u{144}'), ('\u{145}', '\u{146}'),
-        ('\u{147}', '\u{148}'), ('\u{14a}', '\u{14b}'), ('\u{14c}', '\u{14d}'), ('\u{14e}',
-        '\u{14f}'), ('\u{150}', '\u{151}'), ('\u{152}', '\u{153}'), ('\u{154}', '\u{155}'),
-        ('\u{156}', '\u{157}'), ('\u{158}', '\u{159}'), ('\u{15a}', '\u{15b}'), ('\u{15c}',
-        '\u{15d}'), ('\u{15e}', '\u{15f}'), ('\u{160}', '\u{161}'), ('\u{162}', '\u{163}'),
-        ('\u{164}', '\u{165}'), ('\u{166}', '\u{167}'), ('\u{168}', '\u{169}'), ('\u{16a}',
-        '\u{16b}'), ('\u{16c}', '\u{16d}'), ('\u{16e}', '\u{16f}'), ('\u{170}', '\u{171}'),
-        ('\u{172}', '\u{173}'), ('\u{174}', '\u{175}'), ('\u{176}', '\u{177}'), ('\u{178}',
-        '\u{ff}'), ('\u{179}', '\u{17a}'), ('\u{17b}', '\u{17c}'), ('\u{17d}', '\u{17e}'),
-        ('\u{181}', '\u{253}'), ('\u{182}', '\u{183}'), ('\u{184}', '\u{185}'), ('\u{186}',
-        '\u{254}'), ('\u{187}', '\u{188}'), ('\u{189}', '\u{256}'), ('\u{18a}', '\u{257}'),
-        ('\u{18b}', '\u{18c}'), ('\u{18e}', '\u{1dd}'), ('\u{18f}', '\u{259}'), ('\u{190}',
-        '\u{25b}'), ('\u{191}', '\u{192}'), ('\u{193}', '\u{260}'), ('\u{194}', '\u{263}'),
-        ('\u{196}', '\u{269}'), ('\u{197}', '\u{268}'), ('\u{198}', '\u{199}'), ('\u{19c}',
-        '\u{26f}'), ('\u{19d}', '\u{272}'), ('\u{19f}', '\u{275}'), ('\u{1a0}', '\u{1a1}'),
-        ('\u{1a2}', '\u{1a3}'), ('\u{1a4}', '\u{1a5}'), ('\u{1a6}', '\u{280}'), ('\u{1a7}',
-        '\u{1a8}'), ('\u{1a9}', '\u{283}'), ('\u{1ac}', '\u{1ad}'), ('\u{1ae}', '\u{288}'),
-        ('\u{1af}', '\u{1b0}'), ('\u{1b1}', '\u{28a}'), ('\u{1b2}', '\u{28b}'), ('\u{1b3}',
-        '\u{1b4}'), ('\u{1b5}', '\u{1b6}'), ('\u{1b7}', '\u{292}'), ('\u{1b8}', '\u{1b9}'),
-        ('\u{1bc}', '\u{1bd}'), ('\u{1c4}', '\u{1c6}'), ('\u{1c7}', '\u{1c9}'), ('\u{1ca}',
-        '\u{1cc}'), ('\u{1cd}', '\u{1ce}'), ('\u{1cf}', '\u{1d0}'), ('\u{1d1}', '\u{1d2}'),
-        ('\u{1d3}', '\u{1d4}'), ('\u{1d5}', '\u{1d6}'), ('\u{1d7}', '\u{1d8}'), ('\u{1d9}',
-        '\u{1da}'), ('\u{1db}', '\u{1dc}'), ('\u{1de}', '\u{1df}'), ('\u{1e0}', '\u{1e1}'),
-        ('\u{1e2}', '\u{1e3}'), ('\u{1e4}', '\u{1e5}'), ('\u{1e6}', '\u{1e7}'), ('\u{1e8}',
-        '\u{1e9}'), ('\u{1ea}', '\u{1eb}'), ('\u{1ec}', '\u{1ed}'), ('\u{1ee}', '\u{1ef}'),
-        ('\u{1f1}', '\u{1f3}'), ('\u{1f4}', '\u{1f5}'), ('\u{1f6}', '\u{195}'), ('\u{1f7}',
-        '\u{1bf}'), ('\u{1f8}', '\u{1f9}'), ('\u{1fa}', '\u{1fb}'), ('\u{1fc}', '\u{1fd}'),
-        ('\u{1fe}', '\u{1ff}'), ('\u{200}', '\u{201}'), ('\u{202}', '\u{203}'), ('\u{204}',
-        '\u{205}'), ('\u{206}', '\u{207}'), ('\u{208}', '\u{209}'), ('\u{20a}', '\u{20b}'),
-        ('\u{20c}', '\u{20d}'), ('\u{20e}', '\u{20f}'), ('\u{210}', '\u{211}'), ('\u{212}',
-        '\u{213}'), ('\u{214}', '\u{215}'), ('\u{216}', '\u{217}'), ('\u{218}', '\u{219}'),
-        ('\u{21a}', '\u{21b}'), ('\u{21c}', '\u{21d}'), ('\u{21e}', '\u{21f}'), ('\u{220}',
-        '\u{19e}'), ('\u{222}', '\u{223}'), ('\u{224}', '\u{225}'), ('\u{226}', '\u{227}'),
-        ('\u{228}', '\u{229}'), ('\u{22a}', '\u{22b}'), ('\u{22c}', '\u{22d}'), ('\u{22e}',
-        '\u{22f}'), ('\u{230}', '\u{231}'), ('\u{232}', '\u{233}'), ('\u{23a}', '\u{2c65}'),
-        ('\u{23b}', '\u{23c}'), ('\u{23d}', '\u{19a}'), ('\u{23e}', '\u{2c66}'), ('\u{241}',
-        '\u{242}'), ('\u{243}', '\u{180}'), ('\u{244}', '\u{289}'), ('\u{245}', '\u{28c}'),
-        ('\u{246}', '\u{247}'), ('\u{248}', '\u{249}'), ('\u{24a}', '\u{24b}'), ('\u{24c}',
-        '\u{24d}'), ('\u{24e}', '\u{24f}'), ('\u{370}', '\u{371}'), ('\u{372}', '\u{373}'),
-        ('\u{376}', '\u{377}'), ('\u{37f}', '\u{3f3}'), ('\u{386}', '\u{3ac}'), ('\u{388}',
-        '\u{3ad}'), ('\u{389}', '\u{3ae}'), ('\u{38a}', '\u{3af}'), ('\u{38c}', '\u{3cc}'),
-        ('\u{38e}', '\u{3cd}'), ('\u{38f}', '\u{3ce}'), ('\u{391}', '\u{3b1}'), ('\u{392}',
-        '\u{3b2}'), ('\u{393}', '\u{3b3}'), ('\u{394}', '\u{3b4}'), ('\u{395}', '\u{3b5}'),
-        ('\u{396}', '\u{3b6}'), ('\u{397}', '\u{3b7}'), ('\u{398}', '\u{3b8}'), ('\u{399}',
-        '\u{3b9}'), ('\u{39a}', '\u{3ba}'), ('\u{39b}', '\u{3bb}'), ('\u{39c}', '\u{3bc}'),
-        ('\u{39d}', '\u{3bd}'), ('\u{39e}', '\u{3be}'), ('\u{39f}', '\u{3bf}'), ('\u{3a0}',
-        '\u{3c0}'), ('\u{3a1}', '\u{3c1}'), ('\u{3a3}', '\u{3c3}'), ('\u{3a4}', '\u{3c4}'),
-        ('\u{3a5}', '\u{3c5}'), ('\u{3a6}', '\u{3c6}'), ('\u{3a7}', '\u{3c7}'), ('\u{3a8}',
-        '\u{3c8}'), ('\u{3a9}', '\u{3c9}'), ('\u{3aa}', '\u{3ca}'), ('\u{3ab}', '\u{3cb}'),
-        ('\u{3cf}', '\u{3d7}'), ('\u{3d8}', '\u{3d9}'), ('\u{3da}', '\u{3db}'), ('\u{3dc}',
-        '\u{3dd}'), ('\u{3de}', '\u{3df}'), ('\u{3e0}', '\u{3e1}'), ('\u{3e2}', '\u{3e3}'),
-        ('\u{3e4}', '\u{3e5}'), ('\u{3e6}', '\u{3e7}'), ('\u{3e8}', '\u{3e9}'), ('\u{3ea}',
-        '\u{3eb}'), ('\u{3ec}', '\u{3ed}'), ('\u{3ee}', '\u{3ef}'), ('\u{3f4}', '\u{3b8}'),
-        ('\u{3f7}', '\u{3f8}'), ('\u{3f9}', '\u{3f2}'), ('\u{3fa}', '\u{3fb}'), ('\u{3fd}',
-        '\u{37b}'), ('\u{3fe}', '\u{37c}'), ('\u{3ff}', '\u{37d}'), ('\u{400}', '\u{450}'),
-        ('\u{401}', '\u{451}'), ('\u{402}', '\u{452}'), ('\u{403}', '\u{453}'), ('\u{404}',
-        '\u{454}'), ('\u{405}', '\u{455}'), ('\u{406}', '\u{456}'), ('\u{407}', '\u{457}'),
-        ('\u{408}', '\u{458}'), ('\u{409}', '\u{459}'), ('\u{40a}', '\u{45a}'), ('\u{40b}',
-        '\u{45b}'), ('\u{40c}', '\u{45c}'), ('\u{40d}', '\u{45d}'), ('\u{40e}', '\u{45e}'),
-        ('\u{40f}', '\u{45f}'), ('\u{410}', '\u{430}'), ('\u{411}', '\u{431}'), ('\u{412}',
-        '\u{432}'), ('\u{413}', '\u{433}'), ('\u{414}', '\u{434}'), ('\u{415}', '\u{435}'),
-        ('\u{416}', '\u{436}'), ('\u{417}', '\u{437}'), ('\u{418}', '\u{438}'), ('\u{419}',
-        '\u{439}'), ('\u{41a}', '\u{43a}'), ('\u{41b}', '\u{43b}'), ('\u{41c}', '\u{43c}'),
-        ('\u{41d}', '\u{43d}'), ('\u{41e}', '\u{43e}'), ('\u{41f}', '\u{43f}'), ('\u{420}',
-        '\u{440}'), ('\u{421}', '\u{441}'), ('\u{422}', '\u{442}'), ('\u{423}', '\u{443}'),
-        ('\u{424}', '\u{444}'), ('\u{425}', '\u{445}'), ('\u{426}', '\u{446}'), ('\u{427}',
-        '\u{447}'), ('\u{428}', '\u{448}'), ('\u{429}', '\u{449}'), ('\u{42a}', '\u{44a}'),
-        ('\u{42b}', '\u{44b}'), ('\u{42c}', '\u{44c}'), ('\u{42d}', '\u{44d}'), ('\u{42e}',
-        '\u{44e}'), ('\u{42f}', '\u{44f}'), ('\u{460}', '\u{461}'), ('\u{462}', '\u{463}'),
-        ('\u{464}', '\u{465}'), ('\u{466}', '\u{467}'), ('\u{468}', '\u{469}'), ('\u{46a}',
-        '\u{46b}'), ('\u{46c}', '\u{46d}'), ('\u{46e}', '\u{46f}'), ('\u{470}', '\u{471}'),
-        ('\u{472}', '\u{473}'), ('\u{474}', '\u{475}'), ('\u{476}', '\u{477}'), ('\u{478}',
-        '\u{479}'), ('\u{47a}', '\u{47b}'), ('\u{47c}', '\u{47d}'), ('\u{47e}', '\u{47f}'),
-        ('\u{480}', '\u{481}'), ('\u{48a}', '\u{48b}'), ('\u{48c}', '\u{48d}'), ('\u{48e}',
-        '\u{48f}'), ('\u{490}', '\u{491}'), ('\u{492}', '\u{493}'), ('\u{494}', '\u{495}'),
-        ('\u{496}', '\u{497}'), ('\u{498}', '\u{499}'), ('\u{49a}', '\u{49b}'), ('\u{49c}',
-        '\u{49d}'), ('\u{49e}', '\u{49f}'), ('\u{4a0}', '\u{4a1}'), ('\u{4a2}', '\u{4a3}'),
-        ('\u{4a4}', '\u{4a5}'), ('\u{4a6}', '\u{4a7}'), ('\u{4a8}', '\u{4a9}'), ('\u{4aa}',
-        '\u{4ab}'), ('\u{4ac}', '\u{4ad}'), ('\u{4ae}', '\u{4af}'), ('\u{4b0}', '\u{4b1}'),
-        ('\u{4b2}', '\u{4b3}'), ('\u{4b4}', '\u{4b5}'), ('\u{4b6}', '\u{4b7}'), ('\u{4b8}',
-        '\u{4b9}'), ('\u{4ba}', '\u{4bb}'), ('\u{4bc}', '\u{4bd}'), ('\u{4be}', '\u{4bf}'),
-        ('\u{4c0}', '\u{4cf}'), ('\u{4c1}', '\u{4c2}'), ('\u{4c3}', '\u{4c4}'), ('\u{4c5}',
-        '\u{4c6}'), ('\u{4c7}', '\u{4c8}'), ('\u{4c9}', '\u{4ca}'), ('\u{4cb}', '\u{4cc}'),
-        ('\u{4cd}', '\u{4ce}'), ('\u{4d0}', '\u{4d1}'), ('\u{4d2}', '\u{4d3}'), ('\u{4d4}',
-        '\u{4d5}'), ('\u{4d6}', '\u{4d7}'), ('\u{4d8}', '\u{4d9}'), ('\u{4da}', '\u{4db}'),
-        ('\u{4dc}', '\u{4dd}'), ('\u{4de}', '\u{4df}'), ('\u{4e0}', '\u{4e1}'), ('\u{4e2}',
-        '\u{4e3}'), ('\u{4e4}', '\u{4e5}'), ('\u{4e6}', '\u{4e7}'), ('\u{4e8}', '\u{4e9}'),
-        ('\u{4ea}', '\u{4eb}'), ('\u{4ec}', '\u{4ed}'), ('\u{4ee}', '\u{4ef}'), ('\u{4f0}',
-        '\u{4f1}'), ('\u{4f2}', '\u{4f3}'), ('\u{4f4}', '\u{4f5}'), ('\u{4f6}', '\u{4f7}'),
-        ('\u{4f8}', '\u{4f9}'), ('\u{4fa}', '\u{4fb}'), ('\u{4fc}', '\u{4fd}'), ('\u{4fe}',
-        '\u{4ff}'), ('\u{500}', '\u{501}'), ('\u{502}', '\u{503}'), ('\u{504}', '\u{505}'),
-        ('\u{506}', '\u{507}'), ('\u{508}', '\u{509}'), ('\u{50a}', '\u{50b}'), ('\u{50c}',
-        '\u{50d}'), ('\u{50e}', '\u{50f}'), ('\u{510}', '\u{511}'), ('\u{512}', '\u{513}'),
-        ('\u{514}', '\u{515}'), ('\u{516}', '\u{517}'), ('\u{518}', '\u{519}'), ('\u{51a}',
-        '\u{51b}'), ('\u{51c}', '\u{51d}'), ('\u{51e}', '\u{51f}'), ('\u{520}', '\u{521}'),
-        ('\u{522}', '\u{523}'), ('\u{524}', '\u{525}'), ('\u{526}', '\u{527}'), ('\u{528}',
-        '\u{529}'), ('\u{52a}', '\u{52b}'), ('\u{52c}', '\u{52d}'), ('\u{52e}', '\u{52f}'),
-        ('\u{531}', '\u{561}'), ('\u{532}', '\u{562}'), ('\u{533}', '\u{563}'), ('\u{534}',
-        '\u{564}'), ('\u{535}', '\u{565}'), ('\u{536}', '\u{566}'), ('\u{537}', '\u{567}'),
-        ('\u{538}', '\u{568}'), ('\u{539}', '\u{569}'), ('\u{53a}', '\u{56a}'), ('\u{53b}',
-        '\u{56b}'), ('\u{53c}', '\u{56c}'), ('\u{53d}', '\u{56d}'), ('\u{53e}', '\u{56e}'),
-        ('\u{53f}', '\u{56f}'), ('\u{540}', '\u{570}'), ('\u{541}', '\u{571}'), ('\u{542}',
-        '\u{572}'), ('\u{543}', '\u{573}'), ('\u{544}', '\u{574}'), ('\u{545}', '\u{575}'),
-        ('\u{546}', '\u{576}'), ('\u{547}', '\u{577}'), ('\u{548}', '\u{578}'), ('\u{549}',
-        '\u{579}'), ('\u{54a}', '\u{57a}'), ('\u{54b}', '\u{57b}'), ('\u{54c}', '\u{57c}'),
-        ('\u{54d}', '\u{57d}'), ('\u{54e}', '\u{57e}'), ('\u{54f}', '\u{57f}'), ('\u{550}',
-        '\u{580}'), ('\u{551}', '\u{581}'), ('\u{552}', '\u{582}'), ('\u{553}', '\u{583}'),
-        ('\u{554}', '\u{584}'), ('\u{555}', '\u{585}'), ('\u{556}', '\u{586}'), ('\u{10a0}',
-        '\u{2d00}'), ('\u{10a1}', '\u{2d01}'), ('\u{10a2}', '\u{2d02}'), ('\u{10a3}', '\u{2d03}'),
-        ('\u{10a4}', '\u{2d04}'), ('\u{10a5}', '\u{2d05}'), ('\u{10a6}', '\u{2d06}'), ('\u{10a7}',
-        '\u{2d07}'), ('\u{10a8}', '\u{2d08}'), ('\u{10a9}', '\u{2d09}'), ('\u{10aa}', '\u{2d0a}'),
-        ('\u{10ab}', '\u{2d0b}'), ('\u{10ac}', '\u{2d0c}'), ('\u{10ad}', '\u{2d0d}'), ('\u{10ae}',
-        '\u{2d0e}'), ('\u{10af}', '\u{2d0f}'), ('\u{10b0}', '\u{2d10}'), ('\u{10b1}', '\u{2d11}'),
-        ('\u{10b2}', '\u{2d12}'), ('\u{10b3}', '\u{2d13}'), ('\u{10b4}', '\u{2d14}'), ('\u{10b5}',
-        '\u{2d15}'), ('\u{10b6}', '\u{2d16}'), ('\u{10b7}', '\u{2d17}'), ('\u{10b8}', '\u{2d18}'),
-        ('\u{10b9}', '\u{2d19}'), ('\u{10ba}', '\u{2d1a}'), ('\u{10bb}', '\u{2d1b}'), ('\u{10bc}',
-        '\u{2d1c}'), ('\u{10bd}', '\u{2d1d}'), ('\u{10be}', '\u{2d1e}'), ('\u{10bf}', '\u{2d1f}'),
-        ('\u{10c0}', '\u{2d20}'), ('\u{10c1}', '\u{2d21}'), ('\u{10c2}', '\u{2d22}'), ('\u{10c3}',
-        '\u{2d23}'), ('\u{10c4}', '\u{2d24}'), ('\u{10c5}', '\u{2d25}'), ('\u{10c7}', '\u{2d27}'),
-        ('\u{10cd}', '\u{2d2d}'), ('\u{1e00}', '\u{1e01}'), ('\u{1e02}', '\u{1e03}'), ('\u{1e04}',
-        '\u{1e05}'), ('\u{1e06}', '\u{1e07}'), ('\u{1e08}', '\u{1e09}'), ('\u{1e0a}', '\u{1e0b}'),
-        ('\u{1e0c}', '\u{1e0d}'), ('\u{1e0e}', '\u{1e0f}'), ('\u{1e10}', '\u{1e11}'), ('\u{1e12}',
-        '\u{1e13}'), ('\u{1e14}', '\u{1e15}'), ('\u{1e16}', '\u{1e17}'), ('\u{1e18}', '\u{1e19}'),
-        ('\u{1e1a}', '\u{1e1b}'), ('\u{1e1c}', '\u{1e1d}'), ('\u{1e1e}', '\u{1e1f}'), ('\u{1e20}',
-        '\u{1e21}'), ('\u{1e22}', '\u{1e23}'), ('\u{1e24}', '\u{1e25}'), ('\u{1e26}', '\u{1e27}'),
-        ('\u{1e28}', '\u{1e29}'), ('\u{1e2a}', '\u{1e2b}'), ('\u{1e2c}', '\u{1e2d}'), ('\u{1e2e}',
-        '\u{1e2f}'), ('\u{1e30}', '\u{1e31}'), ('\u{1e32}', '\u{1e33}'), ('\u{1e34}', '\u{1e35}'),
-        ('\u{1e36}', '\u{1e37}'), ('\u{1e38}', '\u{1e39}'), ('\u{1e3a}', '\u{1e3b}'), ('\u{1e3c}',
-        '\u{1e3d}'), ('\u{1e3e}', '\u{1e3f}'), ('\u{1e40}', '\u{1e41}'), ('\u{1e42}', '\u{1e43}'),
-        ('\u{1e44}', '\u{1e45}'), ('\u{1e46}', '\u{1e47}'), ('\u{1e48}', '\u{1e49}'), ('\u{1e4a}',
-        '\u{1e4b}'), ('\u{1e4c}', '\u{1e4d}'), ('\u{1e4e}', '\u{1e4f}'), ('\u{1e50}', '\u{1e51}'),
-        ('\u{1e52}', '\u{1e53}'), ('\u{1e54}', '\u{1e55}'), ('\u{1e56}', '\u{1e57}'), ('\u{1e58}',
-        '\u{1e59}'), ('\u{1e5a}', '\u{1e5b}'), ('\u{1e5c}', '\u{1e5d}'), ('\u{1e5e}', '\u{1e5f}'),
-        ('\u{1e60}', '\u{1e61}'), ('\u{1e62}', '\u{1e63}'), ('\u{1e64}', '\u{1e65}'), ('\u{1e66}',
-        '\u{1e67}'), ('\u{1e68}', '\u{1e69}'), ('\u{1e6a}', '\u{1e6b}'), ('\u{1e6c}', '\u{1e6d}'),
-        ('\u{1e6e}', '\u{1e6f}'), ('\u{1e70}', '\u{1e71}'), ('\u{1e72}', '\u{1e73}'), ('\u{1e74}',
-        '\u{1e75}'), ('\u{1e76}', '\u{1e77}'), ('\u{1e78}', '\u{1e79}'), ('\u{1e7a}', '\u{1e7b}'),
-        ('\u{1e7c}', '\u{1e7d}'), ('\u{1e7e}', '\u{1e7f}'), ('\u{1e80}', '\u{1e81}'), ('\u{1e82}',
-        '\u{1e83}'), ('\u{1e84}', '\u{1e85}'), ('\u{1e86}', '\u{1e87}'), ('\u{1e88}', '\u{1e89}'),
-        ('\u{1e8a}', '\u{1e8b}'), ('\u{1e8c}', '\u{1e8d}'), ('\u{1e8e}', '\u{1e8f}'), ('\u{1e90}',
-        '\u{1e91}'), ('\u{1e92}', '\u{1e93}'), ('\u{1e94}', '\u{1e95}'), ('\u{1e9e}', '\u{df}'),
-        ('\u{1ea0}', '\u{1ea1}'), ('\u{1ea2}', '\u{1ea3}'), ('\u{1ea4}', '\u{1ea5}'), ('\u{1ea6}',
-        '\u{1ea7}'), ('\u{1ea8}', '\u{1ea9}'), ('\u{1eaa}', '\u{1eab}'), ('\u{1eac}', '\u{1ead}'),
-        ('\u{1eae}', '\u{1eaf}'), ('\u{1eb0}', '\u{1eb1}'), ('\u{1eb2}', '\u{1eb3}'), ('\u{1eb4}',
-        '\u{1eb5}'), ('\u{1eb6}', '\u{1eb7}'), ('\u{1eb8}', '\u{1eb9}'), ('\u{1eba}', '\u{1ebb}'),
-        ('\u{1ebc}', '\u{1ebd}'), ('\u{1ebe}', '\u{1ebf}'), ('\u{1ec0}', '\u{1ec1}'), ('\u{1ec2}',
-        '\u{1ec3}'), ('\u{1ec4}', '\u{1ec5}'), ('\u{1ec6}', '\u{1ec7}'), ('\u{1ec8}', '\u{1ec9}'),
-        ('\u{1eca}', '\u{1ecb}'), ('\u{1ecc}', '\u{1ecd}'), ('\u{1ece}', '\u{1ecf}'), ('\u{1ed0}',
-        '\u{1ed1}'), ('\u{1ed2}', '\u{1ed3}'), ('\u{1ed4}', '\u{1ed5}'), ('\u{1ed6}', '\u{1ed7}'),
-        ('\u{1ed8}', '\u{1ed9}'), ('\u{1eda}', '\u{1edb}'), ('\u{1edc}', '\u{1edd}'), ('\u{1ede}',
-        '\u{1edf}'), ('\u{1ee0}', '\u{1ee1}'), ('\u{1ee2}', '\u{1ee3}'), ('\u{1ee4}', '\u{1ee5}'),
-        ('\u{1ee6}', '\u{1ee7}'), ('\u{1ee8}', '\u{1ee9}'), ('\u{1eea}', '\u{1eeb}'), ('\u{1eec}',
-        '\u{1eed}'), ('\u{1eee}', '\u{1eef}'), ('\u{1ef0}', '\u{1ef1}'), ('\u{1ef2}', '\u{1ef3}'),
-        ('\u{1ef4}', '\u{1ef5}'), ('\u{1ef6}', '\u{1ef7}'), ('\u{1ef8}', '\u{1ef9}'), ('\u{1efa}',
-        '\u{1efb}'), ('\u{1efc}', '\u{1efd}'), ('\u{1efe}', '\u{1eff}'), ('\u{1f08}', '\u{1f00}'),
-        ('\u{1f09}', '\u{1f01}'), ('\u{1f0a}', '\u{1f02}'), ('\u{1f0b}', '\u{1f03}'), ('\u{1f0c}',
-        '\u{1f04}'), ('\u{1f0d}', '\u{1f05}'), ('\u{1f0e}', '\u{1f06}'), ('\u{1f0f}', '\u{1f07}'),
-        ('\u{1f18}', '\u{1f10}'), ('\u{1f19}', '\u{1f11}'), ('\u{1f1a}', '\u{1f12}'), ('\u{1f1b}',
-        '\u{1f13}'), ('\u{1f1c}', '\u{1f14}'), ('\u{1f1d}', '\u{1f15}'), ('\u{1f28}', '\u{1f20}'),
-        ('\u{1f29}', '\u{1f21}'), ('\u{1f2a}', '\u{1f22}'), ('\u{1f2b}', '\u{1f23}'), ('\u{1f2c}',
-        '\u{1f24}'), ('\u{1f2d}', '\u{1f25}'), ('\u{1f2e}', '\u{1f26}'), ('\u{1f2f}', '\u{1f27}'),
-        ('\u{1f38}', '\u{1f30}'), ('\u{1f39}', '\u{1f31}'), ('\u{1f3a}', '\u{1f32}'), ('\u{1f3b}',
-        '\u{1f33}'), ('\u{1f3c}', '\u{1f34}'), ('\u{1f3d}', '\u{1f35}'), ('\u{1f3e}', '\u{1f36}'),
-        ('\u{1f3f}', '\u{1f37}'), ('\u{1f48}', '\u{1f40}'), ('\u{1f49}', '\u{1f41}'), ('\u{1f4a}',
-        '\u{1f42}'), ('\u{1f4b}', '\u{1f43}'), ('\u{1f4c}', '\u{1f44}'), ('\u{1f4d}', '\u{1f45}'),
-        ('\u{1f59}', '\u{1f51}'), ('\u{1f5b}', '\u{1f53}'), ('\u{1f5d}', '\u{1f55}'), ('\u{1f5f}',
-        '\u{1f57}'), ('\u{1f68}', '\u{1f60}'), ('\u{1f69}', '\u{1f61}'), ('\u{1f6a}', '\u{1f62}'),
-        ('\u{1f6b}', '\u{1f63}'), ('\u{1f6c}', '\u{1f64}'), ('\u{1f6d}', '\u{1f65}'), ('\u{1f6e}',
-        '\u{1f66}'), ('\u{1f6f}', '\u{1f67}'), ('\u{1fb8}', '\u{1fb0}'), ('\u{1fb9}', '\u{1fb1}'),
-        ('\u{1fba}', '\u{1f70}'), ('\u{1fbb}', '\u{1f71}'), ('\u{1fc8}', '\u{1f72}'), ('\u{1fc9}',
-        '\u{1f73}'), ('\u{1fca}', '\u{1f74}'), ('\u{1fcb}', '\u{1f75}'), ('\u{1fd8}', '\u{1fd0}'),
-        ('\u{1fd9}', '\u{1fd1}'), ('\u{1fda}', '\u{1f76}'), ('\u{1fdb}', '\u{1f77}'), ('\u{1fe8}',
-        '\u{1fe0}'), ('\u{1fe9}', '\u{1fe1}'), ('\u{1fea}', '\u{1f7a}'), ('\u{1feb}', '\u{1f7b}'),
-        ('\u{1fec}', '\u{1fe5}'), ('\u{1ff8}', '\u{1f78}'), ('\u{1ff9}', '\u{1f79}'), ('\u{1ffa}',
-        '\u{1f7c}'), ('\u{1ffb}', '\u{1f7d}'), ('\u{2126}', '\u{3c9}'), ('\u{212a}', '\u{6b}'),
-        ('\u{212b}', '\u{e5}'), ('\u{2132}', '\u{214e}'), ('\u{2183}', '\u{2184}'), ('\u{2c00}',
-        '\u{2c30}'), ('\u{2c01}', '\u{2c31}'), ('\u{2c02}', '\u{2c32}'), ('\u{2c03}', '\u{2c33}'),
-        ('\u{2c04}', '\u{2c34}'), ('\u{2c05}', '\u{2c35}'), ('\u{2c06}', '\u{2c36}'), ('\u{2c07}',
-        '\u{2c37}'), ('\u{2c08}', '\u{2c38}'), ('\u{2c09}', '\u{2c39}'), ('\u{2c0a}', '\u{2c3a}'),
-        ('\u{2c0b}', '\u{2c3b}'), ('\u{2c0c}', '\u{2c3c}'), ('\u{2c0d}', '\u{2c3d}'), ('\u{2c0e}',
-        '\u{2c3e}'), ('\u{2c0f}', '\u{2c3f}'), ('\u{2c10}', '\u{2c40}'), ('\u{2c11}', '\u{2c41}'),
-        ('\u{2c12}', '\u{2c42}'), ('\u{2c13}', '\u{2c43}'), ('\u{2c14}', '\u{2c44}'), ('\u{2c15}',
-        '\u{2c45}'), ('\u{2c16}', '\u{2c46}'), ('\u{2c17}', '\u{2c47}'), ('\u{2c18}', '\u{2c48}'),
-        ('\u{2c19}', '\u{2c49}'), ('\u{2c1a}', '\u{2c4a}'), ('\u{2c1b}', '\u{2c4b}'), ('\u{2c1c}',
-        '\u{2c4c}'), ('\u{2c1d}', '\u{2c4d}'), ('\u{2c1e}', '\u{2c4e}'), ('\u{2c1f}', '\u{2c4f}'),
-        ('\u{2c20}', '\u{2c50}'), ('\u{2c21}', '\u{2c51}'), ('\u{2c22}', '\u{2c52}'), ('\u{2c23}',
-        '\u{2c53}'), ('\u{2c24}', '\u{2c54}'), ('\u{2c25}', '\u{2c55}'), ('\u{2c26}', '\u{2c56}'),
-        ('\u{2c27}', '\u{2c57}'), ('\u{2c28}', '\u{2c58}'), ('\u{2c29}', '\u{2c59}'), ('\u{2c2a}',
-        '\u{2c5a}'), ('\u{2c2b}', '\u{2c5b}'), ('\u{2c2c}', '\u{2c5c}'), ('\u{2c2d}', '\u{2c5d}'),
-        ('\u{2c2e}', '\u{2c5e}'), ('\u{2c60}', '\u{2c61}'), ('\u{2c62}', '\u{26b}'), ('\u{2c63}',
-        '\u{1d7d}'), ('\u{2c64}', '\u{27d}'), ('\u{2c67}', '\u{2c68}'), ('\u{2c69}', '\u{2c6a}'),
-        ('\u{2c6b}', '\u{2c6c}'), ('\u{2c6d}', '\u{251}'), ('\u{2c6e}', '\u{271}'), ('\u{2c6f}',
-        '\u{250}'), ('\u{2c70}', '\u{252}'), ('\u{2c72}', '\u{2c73}'), ('\u{2c75}', '\u{2c76}'),
-        ('\u{2c7e}', '\u{23f}'), ('\u{2c7f}', '\u{240}'), ('\u{2c80}', '\u{2c81}'), ('\u{2c82}',
-        '\u{2c83}'), ('\u{2c84}', '\u{2c85}'), ('\u{2c86}', '\u{2c87}'), ('\u{2c88}', '\u{2c89}'),
-        ('\u{2c8a}', '\u{2c8b}'), ('\u{2c8c}', '\u{2c8d}'), ('\u{2c8e}', '\u{2c8f}'), ('\u{2c90}',
-        '\u{2c91}'), ('\u{2c92}', '\u{2c93}'), ('\u{2c94}', '\u{2c95}'), ('\u{2c96}', '\u{2c97}'),
-        ('\u{2c98}', '\u{2c99}'), ('\u{2c9a}', '\u{2c9b}'), ('\u{2c9c}', '\u{2c9d}'), ('\u{2c9e}',
-        '\u{2c9f}'), ('\u{2ca0}', '\u{2ca1}'), ('\u{2ca2}', '\u{2ca3}'), ('\u{2ca4}', '\u{2ca5}'),
-        ('\u{2ca6}', '\u{2ca7}'), ('\u{2ca8}', '\u{2ca9}'), ('\u{2caa}', '\u{2cab}'), ('\u{2cac}',
-        '\u{2cad}'), ('\u{2cae}', '\u{2caf}'), ('\u{2cb0}', '\u{2cb1}'), ('\u{2cb2}', '\u{2cb3}'),
-        ('\u{2cb4}', '\u{2cb5}'), ('\u{2cb6}', '\u{2cb7}'), ('\u{2cb8}', '\u{2cb9}'), ('\u{2cba}',
-        '\u{2cbb}'), ('\u{2cbc}', '\u{2cbd}'), ('\u{2cbe}', '\u{2cbf}'), ('\u{2cc0}', '\u{2cc1}'),
-        ('\u{2cc2}', '\u{2cc3}'), ('\u{2cc4}', '\u{2cc5}'), ('\u{2cc6}', '\u{2cc7}'), ('\u{2cc8}',
-        '\u{2cc9}'), ('\u{2cca}', '\u{2ccb}'), ('\u{2ccc}', '\u{2ccd}'), ('\u{2cce}', '\u{2ccf}'),
-        ('\u{2cd0}', '\u{2cd1}'), ('\u{2cd2}', '\u{2cd3}'), ('\u{2cd4}', '\u{2cd5}'), ('\u{2cd6}',
-        '\u{2cd7}'), ('\u{2cd8}', '\u{2cd9}'), ('\u{2cda}', '\u{2cdb}'), ('\u{2cdc}', '\u{2cdd}'),
-        ('\u{2cde}', '\u{2cdf}'), ('\u{2ce0}', '\u{2ce1}'), ('\u{2ce2}', '\u{2ce3}'), ('\u{2ceb}',
-        '\u{2cec}'), ('\u{2ced}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{a640}', '\u{a641}'),
-        ('\u{a642}', '\u{a643}'), ('\u{a644}', '\u{a645}'), ('\u{a646}', '\u{a647}'), ('\u{a648}',
-        '\u{a649}'), ('\u{a64a}', '\u{a64b}'), ('\u{a64c}', '\u{a64d}'), ('\u{a64e}', '\u{a64f}'),
-        ('\u{a650}', '\u{a651}'), ('\u{a652}', '\u{a653}'), ('\u{a654}', '\u{a655}'), ('\u{a656}',
-        '\u{a657}'), ('\u{a658}', '\u{a659}'), ('\u{a65a}', '\u{a65b}'), ('\u{a65c}', '\u{a65d}'),
-        ('\u{a65e}', '\u{a65f}'), ('\u{a660}', '\u{a661}'), ('\u{a662}', '\u{a663}'), ('\u{a664}',
-        '\u{a665}'), ('\u{a666}', '\u{a667}'), ('\u{a668}', '\u{a669}'), ('\u{a66a}', '\u{a66b}'),
-        ('\u{a66c}', '\u{a66d}'), ('\u{a680}', '\u{a681}'), ('\u{a682}', '\u{a683}'), ('\u{a684}',
-        '\u{a685}'), ('\u{a686}', '\u{a687}'), ('\u{a688}', '\u{a689}'), ('\u{a68a}', '\u{a68b}'),
-        ('\u{a68c}', '\u{a68d}'), ('\u{a68e}', '\u{a68f}'), ('\u{a690}', '\u{a691}'), ('\u{a692}',
-        '\u{a693}'), ('\u{a694}', '\u{a695}'), ('\u{a696}', '\u{a697}'), ('\u{a698}', '\u{a699}'),
-        ('\u{a69a}', '\u{a69b}'), ('\u{a722}', '\u{a723}'), ('\u{a724}', '\u{a725}'), ('\u{a726}',
-        '\u{a727}'), ('\u{a728}', '\u{a729}'), ('\u{a72a}', '\u{a72b}'), ('\u{a72c}', '\u{a72d}'),
-        ('\u{a72e}', '\u{a72f}'), ('\u{a732}', '\u{a733}'), ('\u{a734}', '\u{a735}'), ('\u{a736}',
-        '\u{a737}'), ('\u{a738}', '\u{a739}'), ('\u{a73a}', '\u{a73b}'), ('\u{a73c}', '\u{a73d}'),
-        ('\u{a73e}', '\u{a73f}'), ('\u{a740}', '\u{a741}'), ('\u{a742}', '\u{a743}'), ('\u{a744}',
-        '\u{a745}'), ('\u{a746}', '\u{a747}'), ('\u{a748}', '\u{a749}'), ('\u{a74a}', '\u{a74b}'),
-        ('\u{a74c}', '\u{a74d}'), ('\u{a74e}', '\u{a74f}'), ('\u{a750}', '\u{a751}'), ('\u{a752}',
-        '\u{a753}'), ('\u{a754}', '\u{a755}'), ('\u{a756}', '\u{a757}'), ('\u{a758}', '\u{a759}'),
-        ('\u{a75a}', '\u{a75b}'), ('\u{a75c}', '\u{a75d}'), ('\u{a75e}', '\u{a75f}'), ('\u{a760}',
-        '\u{a761}'), ('\u{a762}', '\u{a763}'), ('\u{a764}', '\u{a765}'), ('\u{a766}', '\u{a767}'),
-        ('\u{a768}', '\u{a769}'), ('\u{a76a}', '\u{a76b}'), ('\u{a76c}', '\u{a76d}'), ('\u{a76e}',
-        '\u{a76f}'), ('\u{a779}', '\u{a77a}'), ('\u{a77b}', '\u{a77c}'), ('\u{a77d}', '\u{1d79}'),
-        ('\u{a77e}', '\u{a77f}'), ('\u{a780}', '\u{a781}'), ('\u{a782}', '\u{a783}'), ('\u{a784}',
-        '\u{a785}'), ('\u{a786}', '\u{a787}'), ('\u{a78b}', '\u{a78c}'), ('\u{a78d}', '\u{265}'),
-        ('\u{a790}', '\u{a791}'), ('\u{a792}', '\u{a793}'), ('\u{a796}', '\u{a797}'), ('\u{a798}',
-        '\u{a799}'), ('\u{a79a}', '\u{a79b}'), ('\u{a79c}', '\u{a79d}'), ('\u{a79e}', '\u{a79f}'),
-        ('\u{a7a0}', '\u{a7a1}'), ('\u{a7a2}', '\u{a7a3}'), ('\u{a7a4}', '\u{a7a5}'), ('\u{a7a6}',
-        '\u{a7a7}'), ('\u{a7a8}', '\u{a7a9}'), ('\u{a7aa}', '\u{266}'), ('\u{a7ab}', '\u{25c}'),
-        ('\u{a7ac}', '\u{261}'), ('\u{a7ad}', '\u{26c}'), ('\u{a7b0}', '\u{29e}'), ('\u{a7b1}',
-        '\u{287}'), ('\u{ff21}', '\u{ff41}'), ('\u{ff22}', '\u{ff42}'), ('\u{ff23}', '\u{ff43}'),
-        ('\u{ff24}', '\u{ff44}'), ('\u{ff25}', '\u{ff45}'), ('\u{ff26}', '\u{ff46}'), ('\u{ff27}',
-        '\u{ff47}'), ('\u{ff28}', '\u{ff48}'), ('\u{ff29}', '\u{ff49}'), ('\u{ff2a}', '\u{ff4a}'),
-        ('\u{ff2b}', '\u{ff4b}'), ('\u{ff2c}', '\u{ff4c}'), ('\u{ff2d}', '\u{ff4d}'), ('\u{ff2e}',
-        '\u{ff4e}'), ('\u{ff2f}', '\u{ff4f}'), ('\u{ff30}', '\u{ff50}'), ('\u{ff31}', '\u{ff51}'),
-        ('\u{ff32}', '\u{ff52}'), ('\u{ff33}', '\u{ff53}'), ('\u{ff34}', '\u{ff54}'), ('\u{ff35}',
-        '\u{ff55}'), ('\u{ff36}', '\u{ff56}'), ('\u{ff37}', '\u{ff57}'), ('\u{ff38}', '\u{ff58}'),
-        ('\u{ff39}', '\u{ff59}'), ('\u{ff3a}', '\u{ff5a}'), ('\u{10400}', '\u{10428}'),
-        ('\u{10401}', '\u{10429}'), ('\u{10402}', '\u{1042a}'), ('\u{10403}', '\u{1042b}'),
-        ('\u{10404}', '\u{1042c}'), ('\u{10405}', '\u{1042d}'), ('\u{10406}', '\u{1042e}'),
-        ('\u{10407}', '\u{1042f}'), ('\u{10408}', '\u{10430}'), ('\u{10409}', '\u{10431}'),
-        ('\u{1040a}', '\u{10432}'), ('\u{1040b}', '\u{10433}'), ('\u{1040c}', '\u{10434}'),
-        ('\u{1040d}', '\u{10435}'), ('\u{1040e}', '\u{10436}'), ('\u{1040f}', '\u{10437}'),
-        ('\u{10410}', '\u{10438}'), ('\u{10411}', '\u{10439}'), ('\u{10412}', '\u{1043a}'),
-        ('\u{10413}', '\u{1043b}'), ('\u{10414}', '\u{1043c}'), ('\u{10415}', '\u{1043d}'),
-        ('\u{10416}', '\u{1043e}'), ('\u{10417}', '\u{1043f}'), ('\u{10418}', '\u{10440}'),
-        ('\u{10419}', '\u{10441}'), ('\u{1041a}', '\u{10442}'), ('\u{1041b}', '\u{10443}'),
-        ('\u{1041c}', '\u{10444}'), ('\u{1041d}', '\u{10445}'), ('\u{1041e}', '\u{10446}'),
-        ('\u{1041f}', '\u{10447}'), ('\u{10420}', '\u{10448}'), ('\u{10421}', '\u{10449}'),
-        ('\u{10422}', '\u{1044a}'), ('\u{10423}', '\u{1044b}'), ('\u{10424}', '\u{1044c}'),
-        ('\u{10425}', '\u{1044d}'), ('\u{10426}', '\u{1044e}'), ('\u{10427}', '\u{1044f}'),
-        ('\u{118a0}', '\u{118c0}'), ('\u{118a1}', '\u{118c1}'), ('\u{118a2}', '\u{118c2}'),
-        ('\u{118a3}', '\u{118c3}'), ('\u{118a4}', '\u{118c4}'), ('\u{118a5}', '\u{118c5}'),
-        ('\u{118a6}', '\u{118c6}'), ('\u{118a7}', '\u{118c7}'), ('\u{118a8}', '\u{118c8}'),
-        ('\u{118a9}', '\u{118c9}'), ('\u{118aa}', '\u{118ca}'), ('\u{118ab}', '\u{118cb}'),
-        ('\u{118ac}', '\u{118cc}'), ('\u{118ad}', '\u{118cd}'), ('\u{118ae}', '\u{118ce}'),
-        ('\u{118af}', '\u{118cf}'), ('\u{118b0}', '\u{118d0}'), ('\u{118b1}', '\u{118d1}'),
-        ('\u{118b2}', '\u{118d2}'), ('\u{118b3}', '\u{118d3}'), ('\u{118b4}', '\u{118d4}'),
-        ('\u{118b5}', '\u{118d5}'), ('\u{118b6}', '\u{118d6}'), ('\u{118b7}', '\u{118d7}'),
-        ('\u{118b8}', '\u{118d8}'), ('\u{118b9}', '\u{118d9}'), ('\u{118ba}', '\u{118da}'),
-        ('\u{118bb}', '\u{118db}'), ('\u{118bc}', '\u{118dc}'), ('\u{118bd}', '\u{118dd}'),
-        ('\u{118be}', '\u{118de}'), ('\u{118bf}', '\u{118df}')
+    const to_lowercase_table: &'static [(char, [char; 3])] = &[
+        ('\u{41}', ['\u{61}', '\0', '\0']), ('\u{42}', ['\u{62}', '\0', '\0']), ('\u{43}',
+        ['\u{63}', '\0', '\0']), ('\u{44}', ['\u{64}', '\0', '\0']), ('\u{45}', ['\u{65}', '\0',
+        '\0']), ('\u{46}', ['\u{66}', '\0', '\0']), ('\u{47}', ['\u{67}', '\0', '\0']), ('\u{48}',
+        ['\u{68}', '\0', '\0']), ('\u{49}', ['\u{69}', '\0', '\0']), ('\u{4a}', ['\u{6a}', '\0',
+        '\0']), ('\u{4b}', ['\u{6b}', '\0', '\0']), ('\u{4c}', ['\u{6c}', '\0', '\0']), ('\u{4d}',
+        ['\u{6d}', '\0', '\0']), ('\u{4e}', ['\u{6e}', '\0', '\0']), ('\u{4f}', ['\u{6f}', '\0',
+        '\0']), ('\u{50}', ['\u{70}', '\0', '\0']), ('\u{51}', ['\u{71}', '\0', '\0']), ('\u{52}',
+        ['\u{72}', '\0', '\0']), ('\u{53}', ['\u{73}', '\0', '\0']), ('\u{54}', ['\u{74}', '\0',
+        '\0']), ('\u{55}', ['\u{75}', '\0', '\0']), ('\u{56}', ['\u{76}', '\0', '\0']), ('\u{57}',
+        ['\u{77}', '\0', '\0']), ('\u{58}', ['\u{78}', '\0', '\0']), ('\u{59}', ['\u{79}', '\0',
+        '\0']), ('\u{5a}', ['\u{7a}', '\0', '\0']), ('\u{c0}', ['\u{e0}', '\0', '\0']), ('\u{c1}',
+        ['\u{e1}', '\0', '\0']), ('\u{c2}', ['\u{e2}', '\0', '\0']), ('\u{c3}', ['\u{e3}', '\0',
+        '\0']), ('\u{c4}', ['\u{e4}', '\0', '\0']), ('\u{c5}', ['\u{e5}', '\0', '\0']), ('\u{c6}',
+        ['\u{e6}', '\0', '\0']), ('\u{c7}', ['\u{e7}', '\0', '\0']), ('\u{c8}', ['\u{e8}', '\0',
+        '\0']), ('\u{c9}', ['\u{e9}', '\0', '\0']), ('\u{ca}', ['\u{ea}', '\0', '\0']), ('\u{cb}',
+        ['\u{eb}', '\0', '\0']), ('\u{cc}', ['\u{ec}', '\0', '\0']), ('\u{cd}', ['\u{ed}', '\0',
+        '\0']), ('\u{ce}', ['\u{ee}', '\0', '\0']), ('\u{cf}', ['\u{ef}', '\0', '\0']), ('\u{d0}',
+        ['\u{f0}', '\0', '\0']), ('\u{d1}', ['\u{f1}', '\0', '\0']), ('\u{d2}', ['\u{f2}', '\0',
+        '\0']), ('\u{d3}', ['\u{f3}', '\0', '\0']), ('\u{d4}', ['\u{f4}', '\0', '\0']), ('\u{d5}',
+        ['\u{f5}', '\0', '\0']), ('\u{d6}', ['\u{f6}', '\0', '\0']), ('\u{d8}', ['\u{f8}', '\0',
+        '\0']), ('\u{d9}', ['\u{f9}', '\0', '\0']), ('\u{da}', ['\u{fa}', '\0', '\0']), ('\u{db}',
+        ['\u{fb}', '\0', '\0']), ('\u{dc}', ['\u{fc}', '\0', '\0']), ('\u{dd}', ['\u{fd}', '\0',
+        '\0']), ('\u{de}', ['\u{fe}', '\0', '\0']), ('\u{100}', ['\u{101}', '\0', '\0']),
+        ('\u{102}', ['\u{103}', '\0', '\0']), ('\u{104}', ['\u{105}', '\0', '\0']), ('\u{106}',
+        ['\u{107}', '\0', '\0']), ('\u{108}', ['\u{109}', '\0', '\0']), ('\u{10a}', ['\u{10b}',
+        '\0', '\0']), ('\u{10c}', ['\u{10d}', '\0', '\0']), ('\u{10e}', ['\u{10f}', '\0', '\0']),
+        ('\u{110}', ['\u{111}', '\0', '\0']), ('\u{112}', ['\u{113}', '\0', '\0']), ('\u{114}',
+        ['\u{115}', '\0', '\0']), ('\u{116}', ['\u{117}', '\0', '\0']), ('\u{118}', ['\u{119}',
+        '\0', '\0']), ('\u{11a}', ['\u{11b}', '\0', '\0']), ('\u{11c}', ['\u{11d}', '\0', '\0']),
+        ('\u{11e}', ['\u{11f}', '\0', '\0']), ('\u{120}', ['\u{121}', '\0', '\0']), ('\u{122}',
+        ['\u{123}', '\0', '\0']), ('\u{124}', ['\u{125}', '\0', '\0']), ('\u{126}', ['\u{127}',
+        '\0', '\0']), ('\u{128}', ['\u{129}', '\0', '\0']), ('\u{12a}', ['\u{12b}', '\0', '\0']),
+        ('\u{12c}', ['\u{12d}', '\0', '\0']), ('\u{12e}', ['\u{12f}', '\0', '\0']), ('\u{130}',
+        ['\u{69}', '\u{307}', '\0']), ('\u{132}', ['\u{133}', '\0', '\0']), ('\u{134}', ['\u{135}',
+        '\0', '\0']), ('\u{136}', ['\u{137}', '\0', '\0']), ('\u{139}', ['\u{13a}', '\0', '\0']),
+        ('\u{13b}', ['\u{13c}', '\0', '\0']), ('\u{13d}', ['\u{13e}', '\0', '\0']), ('\u{13f}',
+        ['\u{140}', '\0', '\0']), ('\u{141}', ['\u{142}', '\0', '\0']), ('\u{143}', ['\u{144}',
+        '\0', '\0']), ('\u{145}', ['\u{146}', '\0', '\0']), ('\u{147}', ['\u{148}', '\0', '\0']),
+        ('\u{14a}', ['\u{14b}', '\0', '\0']), ('\u{14c}', ['\u{14d}', '\0', '\0']), ('\u{14e}',
+        ['\u{14f}', '\0', '\0']), ('\u{150}', ['\u{151}', '\0', '\0']), ('\u{152}', ['\u{153}',
+        '\0', '\0']), ('\u{154}', ['\u{155}', '\0', '\0']), ('\u{156}', ['\u{157}', '\0', '\0']),
+        ('\u{158}', ['\u{159}', '\0', '\0']), ('\u{15a}', ['\u{15b}', '\0', '\0']), ('\u{15c}',
+        ['\u{15d}', '\0', '\0']), ('\u{15e}', ['\u{15f}', '\0', '\0']), ('\u{160}', ['\u{161}',
+        '\0', '\0']), ('\u{162}', ['\u{163}', '\0', '\0']), ('\u{164}', ['\u{165}', '\0', '\0']),
+        ('\u{166}', ['\u{167}', '\0', '\0']), ('\u{168}', ['\u{169}', '\0', '\0']), ('\u{16a}',
+        ['\u{16b}', '\0', '\0']), ('\u{16c}', ['\u{16d}', '\0', '\0']), ('\u{16e}', ['\u{16f}',
+        '\0', '\0']), ('\u{170}', ['\u{171}', '\0', '\0']), ('\u{172}', ['\u{173}', '\0', '\0']),
+        ('\u{174}', ['\u{175}', '\0', '\0']), ('\u{176}', ['\u{177}', '\0', '\0']), ('\u{178}',
+        ['\u{ff}', '\0', '\0']), ('\u{179}', ['\u{17a}', '\0', '\0']), ('\u{17b}', ['\u{17c}', '\0',
+        '\0']), ('\u{17d}', ['\u{17e}', '\0', '\0']), ('\u{181}', ['\u{253}', '\0', '\0']),
+        ('\u{182}', ['\u{183}', '\0', '\0']), ('\u{184}', ['\u{185}', '\0', '\0']), ('\u{186}',
+        ['\u{254}', '\0', '\0']), ('\u{187}', ['\u{188}', '\0', '\0']), ('\u{189}', ['\u{256}',
+        '\0', '\0']), ('\u{18a}', ['\u{257}', '\0', '\0']), ('\u{18b}', ['\u{18c}', '\0', '\0']),
+        ('\u{18e}', ['\u{1dd}', '\0', '\0']), ('\u{18f}', ['\u{259}', '\0', '\0']), ('\u{190}',
+        ['\u{25b}', '\0', '\0']), ('\u{191}', ['\u{192}', '\0', '\0']), ('\u{193}', ['\u{260}',
+        '\0', '\0']), ('\u{194}', ['\u{263}', '\0', '\0']), ('\u{196}', ['\u{269}', '\0', '\0']),
+        ('\u{197}', ['\u{268}', '\0', '\0']), ('\u{198}', ['\u{199}', '\0', '\0']), ('\u{19c}',
+        ['\u{26f}', '\0', '\0']), ('\u{19d}', ['\u{272}', '\0', '\0']), ('\u{19f}', ['\u{275}',
+        '\0', '\0']), ('\u{1a0}', ['\u{1a1}', '\0', '\0']), ('\u{1a2}', ['\u{1a3}', '\0', '\0']),
+        ('\u{1a4}', ['\u{1a5}', '\0', '\0']), ('\u{1a6}', ['\u{280}', '\0', '\0']), ('\u{1a7}',
+        ['\u{1a8}', '\0', '\0']), ('\u{1a9}', ['\u{283}', '\0', '\0']), ('\u{1ac}', ['\u{1ad}',
+        '\0', '\0']), ('\u{1ae}', ['\u{288}', '\0', '\0']), ('\u{1af}', ['\u{1b0}', '\0', '\0']),
+        ('\u{1b1}', ['\u{28a}', '\0', '\0']), ('\u{1b2}', ['\u{28b}', '\0', '\0']), ('\u{1b3}',
+        ['\u{1b4}', '\0', '\0']), ('\u{1b5}', ['\u{1b6}', '\0', '\0']), ('\u{1b7}', ['\u{292}',
+        '\0', '\0']), ('\u{1b8}', ['\u{1b9}', '\0', '\0']), ('\u{1bc}', ['\u{1bd}', '\0', '\0']),
+        ('\u{1c4}', ['\u{1c6}', '\0', '\0']), ('\u{1c5}', ['\u{1c6}', '\0', '\0']), ('\u{1c7}',
+        ['\u{1c9}', '\0', '\0']), ('\u{1c8}', ['\u{1c9}', '\0', '\0']), ('\u{1ca}', ['\u{1cc}',
+        '\0', '\0']), ('\u{1cb}', ['\u{1cc}', '\0', '\0']), ('\u{1cd}', ['\u{1ce}', '\0', '\0']),
+        ('\u{1cf}', ['\u{1d0}', '\0', '\0']), ('\u{1d1}', ['\u{1d2}', '\0', '\0']), ('\u{1d3}',
+        ['\u{1d4}', '\0', '\0']), ('\u{1d5}', ['\u{1d6}', '\0', '\0']), ('\u{1d7}', ['\u{1d8}',
+        '\0', '\0']), ('\u{1d9}', ['\u{1da}', '\0', '\0']), ('\u{1db}', ['\u{1dc}', '\0', '\0']),
+        ('\u{1de}', ['\u{1df}', '\0', '\0']), ('\u{1e0}', ['\u{1e1}', '\0', '\0']), ('\u{1e2}',
+        ['\u{1e3}', '\0', '\0']), ('\u{1e4}', ['\u{1e5}', '\0', '\0']), ('\u{1e6}', ['\u{1e7}',
+        '\0', '\0']), ('\u{1e8}', ['\u{1e9}', '\0', '\0']), ('\u{1ea}', ['\u{1eb}', '\0', '\0']),
+        ('\u{1ec}', ['\u{1ed}', '\0', '\0']), ('\u{1ee}', ['\u{1ef}', '\0', '\0']), ('\u{1f1}',
+        ['\u{1f3}', '\0', '\0']), ('\u{1f2}', ['\u{1f3}', '\0', '\0']), ('\u{1f4}', ['\u{1f5}',
+        '\0', '\0']), ('\u{1f6}', ['\u{195}', '\0', '\0']), ('\u{1f7}', ['\u{1bf}', '\0', '\0']),
+        ('\u{1f8}', ['\u{1f9}', '\0', '\0']), ('\u{1fa}', ['\u{1fb}', '\0', '\0']), ('\u{1fc}',
+        ['\u{1fd}', '\0', '\0']), ('\u{1fe}', ['\u{1ff}', '\0', '\0']), ('\u{200}', ['\u{201}',
+        '\0', '\0']), ('\u{202}', ['\u{203}', '\0', '\0']), ('\u{204}', ['\u{205}', '\0', '\0']),
+        ('\u{206}', ['\u{207}', '\0', '\0']), ('\u{208}', ['\u{209}', '\0', '\0']), ('\u{20a}',
+        ['\u{20b}', '\0', '\0']), ('\u{20c}', ['\u{20d}', '\0', '\0']), ('\u{20e}', ['\u{20f}',
+        '\0', '\0']), ('\u{210}', ['\u{211}', '\0', '\0']), ('\u{212}', ['\u{213}', '\0', '\0']),
+        ('\u{214}', ['\u{215}', '\0', '\0']), ('\u{216}', ['\u{217}', '\0', '\0']), ('\u{218}',
+        ['\u{219}', '\0', '\0']), ('\u{21a}', ['\u{21b}', '\0', '\0']), ('\u{21c}', ['\u{21d}',
+        '\0', '\0']), ('\u{21e}', ['\u{21f}', '\0', '\0']), ('\u{220}', ['\u{19e}', '\0', '\0']),
+        ('\u{222}', ['\u{223}', '\0', '\0']), ('\u{224}', ['\u{225}', '\0', '\0']), ('\u{226}',
+        ['\u{227}', '\0', '\0']), ('\u{228}', ['\u{229}', '\0', '\0']), ('\u{22a}', ['\u{22b}',
+        '\0', '\0']), ('\u{22c}', ['\u{22d}', '\0', '\0']), ('\u{22e}', ['\u{22f}', '\0', '\0']),
+        ('\u{230}', ['\u{231}', '\0', '\0']), ('\u{232}', ['\u{233}', '\0', '\0']), ('\u{23a}',
+        ['\u{2c65}', '\0', '\0']), ('\u{23b}', ['\u{23c}', '\0', '\0']), ('\u{23d}', ['\u{19a}',
+        '\0', '\0']), ('\u{23e}', ['\u{2c66}', '\0', '\0']), ('\u{241}', ['\u{242}', '\0', '\0']),
+        ('\u{243}', ['\u{180}', '\0', '\0']), ('\u{244}', ['\u{289}', '\0', '\0']), ('\u{245}',
+        ['\u{28c}', '\0', '\0']), ('\u{246}', ['\u{247}', '\0', '\0']), ('\u{248}', ['\u{249}',
+        '\0', '\0']), ('\u{24a}', ['\u{24b}', '\0', '\0']), ('\u{24c}', ['\u{24d}', '\0', '\0']),
+        ('\u{24e}', ['\u{24f}', '\0', '\0']), ('\u{370}', ['\u{371}', '\0', '\0']), ('\u{372}',
+        ['\u{373}', '\0', '\0']), ('\u{376}', ['\u{377}', '\0', '\0']), ('\u{37f}', ['\u{3f3}',
+        '\0', '\0']), ('\u{386}', ['\u{3ac}', '\0', '\0']), ('\u{388}', ['\u{3ad}', '\0', '\0']),
+        ('\u{389}', ['\u{3ae}', '\0', '\0']), ('\u{38a}', ['\u{3af}', '\0', '\0']), ('\u{38c}',
+        ['\u{3cc}', '\0', '\0']), ('\u{38e}', ['\u{3cd}', '\0', '\0']), ('\u{38f}', ['\u{3ce}',
+        '\0', '\0']), ('\u{391}', ['\u{3b1}', '\0', '\0']), ('\u{392}', ['\u{3b2}', '\0', '\0']),
+        ('\u{393}', ['\u{3b3}', '\0', '\0']), ('\u{394}', ['\u{3b4}', '\0', '\0']), ('\u{395}',
+        ['\u{3b5}', '\0', '\0']), ('\u{396}', ['\u{3b6}', '\0', '\0']), ('\u{397}', ['\u{3b7}',
+        '\0', '\0']), ('\u{398}', ['\u{3b8}', '\0', '\0']), ('\u{399}', ['\u{3b9}', '\0', '\0']),
+        ('\u{39a}', ['\u{3ba}', '\0', '\0']), ('\u{39b}', ['\u{3bb}', '\0', '\0']), ('\u{39c}',
+        ['\u{3bc}', '\0', '\0']), ('\u{39d}', ['\u{3bd}', '\0', '\0']), ('\u{39e}', ['\u{3be}',
+        '\0', '\0']), ('\u{39f}', ['\u{3bf}', '\0', '\0']), ('\u{3a0}', ['\u{3c0}', '\0', '\0']),
+        ('\u{3a1}', ['\u{3c1}', '\0', '\0']), ('\u{3a3}', ['\u{3c3}', '\0', '\0']), ('\u{3a4}',
+        ['\u{3c4}', '\0', '\0']), ('\u{3a5}', ['\u{3c5}', '\0', '\0']), ('\u{3a6}', ['\u{3c6}',
+        '\0', '\0']), ('\u{3a7}', ['\u{3c7}', '\0', '\0']), ('\u{3a8}', ['\u{3c8}', '\0', '\0']),
+        ('\u{3a9}', ['\u{3c9}', '\0', '\0']), ('\u{3aa}', ['\u{3ca}', '\0', '\0']), ('\u{3ab}',
+        ['\u{3cb}', '\0', '\0']), ('\u{3cf}', ['\u{3d7}', '\0', '\0']), ('\u{3d8}', ['\u{3d9}',
+        '\0', '\0']), ('\u{3da}', ['\u{3db}', '\0', '\0']), ('\u{3dc}', ['\u{3dd}', '\0', '\0']),
+        ('\u{3de}', ['\u{3df}', '\0', '\0']), ('\u{3e0}', ['\u{3e1}', '\0', '\0']), ('\u{3e2}',
+        ['\u{3e3}', '\0', '\0']), ('\u{3e4}', ['\u{3e5}', '\0', '\0']), ('\u{3e6}', ['\u{3e7}',
+        '\0', '\0']), ('\u{3e8}', ['\u{3e9}', '\0', '\0']), ('\u{3ea}', ['\u{3eb}', '\0', '\0']),
+        ('\u{3ec}', ['\u{3ed}', '\0', '\0']), ('\u{3ee}', ['\u{3ef}', '\0', '\0']), ('\u{3f4}',
+        ['\u{3b8}', '\0', '\0']), ('\u{3f7}', ['\u{3f8}', '\0', '\0']), ('\u{3f9}', ['\u{3f2}',
+        '\0', '\0']), ('\u{3fa}', ['\u{3fb}', '\0', '\0']), ('\u{3fd}', ['\u{37b}', '\0', '\0']),
+        ('\u{3fe}', ['\u{37c}', '\0', '\0']), ('\u{3ff}', ['\u{37d}', '\0', '\0']), ('\u{400}',
+        ['\u{450}', '\0', '\0']), ('\u{401}', ['\u{451}', '\0', '\0']), ('\u{402}', ['\u{452}',
+        '\0', '\0']), ('\u{403}', ['\u{453}', '\0', '\0']), ('\u{404}', ['\u{454}', '\0', '\0']),
+        ('\u{405}', ['\u{455}', '\0', '\0']), ('\u{406}', ['\u{456}', '\0', '\0']), ('\u{407}',
+        ['\u{457}', '\0', '\0']), ('\u{408}', ['\u{458}', '\0', '\0']), ('\u{409}', ['\u{459}',
+        '\0', '\0']), ('\u{40a}', ['\u{45a}', '\0', '\0']), ('\u{40b}', ['\u{45b}', '\0', '\0']),
+        ('\u{40c}', ['\u{45c}', '\0', '\0']), ('\u{40d}', ['\u{45d}', '\0', '\0']), ('\u{40e}',
+        ['\u{45e}', '\0', '\0']), ('\u{40f}', ['\u{45f}', '\0', '\0']), ('\u{410}', ['\u{430}',
+        '\0', '\0']), ('\u{411}', ['\u{431}', '\0', '\0']), ('\u{412}', ['\u{432}', '\0', '\0']),
+        ('\u{413}', ['\u{433}', '\0', '\0']), ('\u{414}', ['\u{434}', '\0', '\0']), ('\u{415}',
+        ['\u{435}', '\0', '\0']), ('\u{416}', ['\u{436}', '\0', '\0']), ('\u{417}', ['\u{437}',
+        '\0', '\0']), ('\u{418}', ['\u{438}', '\0', '\0']), ('\u{419}', ['\u{439}', '\0', '\0']),
+        ('\u{41a}', ['\u{43a}', '\0', '\0']), ('\u{41b}', ['\u{43b}', '\0', '\0']), ('\u{41c}',
+        ['\u{43c}', '\0', '\0']), ('\u{41d}', ['\u{43d}', '\0', '\0']), ('\u{41e}', ['\u{43e}',
+        '\0', '\0']), ('\u{41f}', ['\u{43f}', '\0', '\0']), ('\u{420}', ['\u{440}', '\0', '\0']),
+        ('\u{421}', ['\u{441}', '\0', '\0']), ('\u{422}', ['\u{442}', '\0', '\0']), ('\u{423}',
+        ['\u{443}', '\0', '\0']), ('\u{424}', ['\u{444}', '\0', '\0']), ('\u{425}', ['\u{445}',
+        '\0', '\0']), ('\u{426}', ['\u{446}', '\0', '\0']), ('\u{427}', ['\u{447}', '\0', '\0']),
+        ('\u{428}', ['\u{448}', '\0', '\0']), ('\u{429}', ['\u{449}', '\0', '\0']), ('\u{42a}',
+        ['\u{44a}', '\0', '\0']), ('\u{42b}', ['\u{44b}', '\0', '\0']), ('\u{42c}', ['\u{44c}',
+        '\0', '\0']), ('\u{42d}', ['\u{44d}', '\0', '\0']), ('\u{42e}', ['\u{44e}', '\0', '\0']),
+        ('\u{42f}', ['\u{44f}', '\0', '\0']), ('\u{460}', ['\u{461}', '\0', '\0']), ('\u{462}',
+        ['\u{463}', '\0', '\0']), ('\u{464}', ['\u{465}', '\0', '\0']), ('\u{466}', ['\u{467}',
+        '\0', '\0']), ('\u{468}', ['\u{469}', '\0', '\0']), ('\u{46a}', ['\u{46b}', '\0', '\0']),
+        ('\u{46c}', ['\u{46d}', '\0', '\0']), ('\u{46e}', ['\u{46f}', '\0', '\0']), ('\u{470}',
+        ['\u{471}', '\0', '\0']), ('\u{472}', ['\u{473}', '\0', '\0']), ('\u{474}', ['\u{475}',
+        '\0', '\0']), ('\u{476}', ['\u{477}', '\0', '\0']), ('\u{478}', ['\u{479}', '\0', '\0']),
+        ('\u{47a}', ['\u{47b}', '\0', '\0']), ('\u{47c}', ['\u{47d}', '\0', '\0']), ('\u{47e}',
+        ['\u{47f}', '\0', '\0']), ('\u{480}', ['\u{481}', '\0', '\0']), ('\u{48a}', ['\u{48b}',
+        '\0', '\0']), ('\u{48c}', ['\u{48d}', '\0', '\0']), ('\u{48e}', ['\u{48f}', '\0', '\0']),
+        ('\u{490}', ['\u{491}', '\0', '\0']), ('\u{492}', ['\u{493}', '\0', '\0']), ('\u{494}',
+        ['\u{495}', '\0', '\0']), ('\u{496}', ['\u{497}', '\0', '\0']), ('\u{498}', ['\u{499}',
+        '\0', '\0']), ('\u{49a}', ['\u{49b}', '\0', '\0']), ('\u{49c}', ['\u{49d}', '\0', '\0']),
+        ('\u{49e}', ['\u{49f}', '\0', '\0']), ('\u{4a0}', ['\u{4a1}', '\0', '\0']), ('\u{4a2}',
+        ['\u{4a3}', '\0', '\0']), ('\u{4a4}', ['\u{4a5}', '\0', '\0']), ('\u{4a6}', ['\u{4a7}',
+        '\0', '\0']), ('\u{4a8}', ['\u{4a9}', '\0', '\0']), ('\u{4aa}', ['\u{4ab}', '\0', '\0']),
+        ('\u{4ac}', ['\u{4ad}', '\0', '\0']), ('\u{4ae}', ['\u{4af}', '\0', '\0']), ('\u{4b0}',
+        ['\u{4b1}', '\0', '\0']), ('\u{4b2}', ['\u{4b3}', '\0', '\0']), ('\u{4b4}', ['\u{4b5}',
+        '\0', '\0']), ('\u{4b6}', ['\u{4b7}', '\0', '\0']), ('\u{4b8}', ['\u{4b9}', '\0', '\0']),
+        ('\u{4ba}', ['\u{4bb}', '\0', '\0']), ('\u{4bc}', ['\u{4bd}', '\0', '\0']), ('\u{4be}',
+        ['\u{4bf}', '\0', '\0']), ('\u{4c0}', ['\u{4cf}', '\0', '\0']), ('\u{4c1}', ['\u{4c2}',
+        '\0', '\0']), ('\u{4c3}', ['\u{4c4}', '\0', '\0']), ('\u{4c5}', ['\u{4c6}', '\0', '\0']),
+        ('\u{4c7}', ['\u{4c8}', '\0', '\0']), ('\u{4c9}', ['\u{4ca}', '\0', '\0']), ('\u{4cb}',
+        ['\u{4cc}', '\0', '\0']), ('\u{4cd}', ['\u{4ce}', '\0', '\0']), ('\u{4d0}', ['\u{4d1}',
+        '\0', '\0']), ('\u{4d2}', ['\u{4d3}', '\0', '\0']), ('\u{4d4}', ['\u{4d5}', '\0', '\0']),
+        ('\u{4d6}', ['\u{4d7}', '\0', '\0']), ('\u{4d8}', ['\u{4d9}', '\0', '\0']), ('\u{4da}',
+        ['\u{4db}', '\0', '\0']), ('\u{4dc}', ['\u{4dd}', '\0', '\0']), ('\u{4de}', ['\u{4df}',
+        '\0', '\0']), ('\u{4e0}', ['\u{4e1}', '\0', '\0']), ('\u{4e2}', ['\u{4e3}', '\0', '\0']),
+        ('\u{4e4}', ['\u{4e5}', '\0', '\0']), ('\u{4e6}', ['\u{4e7}', '\0', '\0']), ('\u{4e8}',
+        ['\u{4e9}', '\0', '\0']), ('\u{4ea}', ['\u{4eb}', '\0', '\0']), ('\u{4ec}', ['\u{4ed}',
+        '\0', '\0']), ('\u{4ee}', ['\u{4ef}', '\0', '\0']), ('\u{4f0}', ['\u{4f1}', '\0', '\0']),
+        ('\u{4f2}', ['\u{4f3}', '\0', '\0']), ('\u{4f4}', ['\u{4f5}', '\0', '\0']), ('\u{4f6}',
+        ['\u{4f7}', '\0', '\0']), ('\u{4f8}', ['\u{4f9}', '\0', '\0']), ('\u{4fa}', ['\u{4fb}',
+        '\0', '\0']), ('\u{4fc}', ['\u{4fd}', '\0', '\0']), ('\u{4fe}', ['\u{4ff}', '\0', '\0']),
+        ('\u{500}', ['\u{501}', '\0', '\0']), ('\u{502}', ['\u{503}', '\0', '\0']), ('\u{504}',
+        ['\u{505}', '\0', '\0']), ('\u{506}', ['\u{507}', '\0', '\0']), ('\u{508}', ['\u{509}',
+        '\0', '\0']), ('\u{50a}', ['\u{50b}', '\0', '\0']), ('\u{50c}', ['\u{50d}', '\0', '\0']),
+        ('\u{50e}', ['\u{50f}', '\0', '\0']), ('\u{510}', ['\u{511}', '\0', '\0']), ('\u{512}',
+        ['\u{513}', '\0', '\0']), ('\u{514}', ['\u{515}', '\0', '\0']), ('\u{516}', ['\u{517}',
+        '\0', '\0']), ('\u{518}', ['\u{519}', '\0', '\0']), ('\u{51a}', ['\u{51b}', '\0', '\0']),
+        ('\u{51c}', ['\u{51d}', '\0', '\0']), ('\u{51e}', ['\u{51f}', '\0', '\0']), ('\u{520}',
+        ['\u{521}', '\0', '\0']), ('\u{522}', ['\u{523}', '\0', '\0']), ('\u{524}', ['\u{525}',
+        '\0', '\0']), ('\u{526}', ['\u{527}', '\0', '\0']), ('\u{528}', ['\u{529}', '\0', '\0']),
+        ('\u{52a}', ['\u{52b}', '\0', '\0']), ('\u{52c}', ['\u{52d}', '\0', '\0']), ('\u{52e}',
+        ['\u{52f}', '\0', '\0']), ('\u{531}', ['\u{561}', '\0', '\0']), ('\u{532}', ['\u{562}',
+        '\0', '\0']), ('\u{533}', ['\u{563}', '\0', '\0']), ('\u{534}', ['\u{564}', '\0', '\0']),
+        ('\u{535}', ['\u{565}', '\0', '\0']), ('\u{536}', ['\u{566}', '\0', '\0']), ('\u{537}',
+        ['\u{567}', '\0', '\0']), ('\u{538}', ['\u{568}', '\0', '\0']), ('\u{539}', ['\u{569}',
+        '\0', '\0']), ('\u{53a}', ['\u{56a}', '\0', '\0']), ('\u{53b}', ['\u{56b}', '\0', '\0']),
+        ('\u{53c}', ['\u{56c}', '\0', '\0']), ('\u{53d}', ['\u{56d}', '\0', '\0']), ('\u{53e}',
+        ['\u{56e}', '\0', '\0']), ('\u{53f}', ['\u{56f}', '\0', '\0']), ('\u{540}', ['\u{570}',
+        '\0', '\0']), ('\u{541}', ['\u{571}', '\0', '\0']), ('\u{542}', ['\u{572}', '\0', '\0']),
+        ('\u{543}', ['\u{573}', '\0', '\0']), ('\u{544}', ['\u{574}', '\0', '\0']), ('\u{545}',
+        ['\u{575}', '\0', '\0']), ('\u{546}', ['\u{576}', '\0', '\0']), ('\u{547}', ['\u{577}',
+        '\0', '\0']), ('\u{548}', ['\u{578}', '\0', '\0']), ('\u{549}', ['\u{579}', '\0', '\0']),
+        ('\u{54a}', ['\u{57a}', '\0', '\0']), ('\u{54b}', ['\u{57b}', '\0', '\0']), ('\u{54c}',
+        ['\u{57c}', '\0', '\0']), ('\u{54d}', ['\u{57d}', '\0', '\0']), ('\u{54e}', ['\u{57e}',
+        '\0', '\0']), ('\u{54f}', ['\u{57f}', '\0', '\0']), ('\u{550}', ['\u{580}', '\0', '\0']),
+        ('\u{551}', ['\u{581}', '\0', '\0']), ('\u{552}', ['\u{582}', '\0', '\0']), ('\u{553}',
+        ['\u{583}', '\0', '\0']), ('\u{554}', ['\u{584}', '\0', '\0']), ('\u{555}', ['\u{585}',
+        '\0', '\0']), ('\u{556}', ['\u{586}', '\0', '\0']), ('\u{10a0}', ['\u{2d00}', '\0', '\0']),
+        ('\u{10a1}', ['\u{2d01}', '\0', '\0']), ('\u{10a2}', ['\u{2d02}', '\0', '\0']), ('\u{10a3}',
+        ['\u{2d03}', '\0', '\0']), ('\u{10a4}', ['\u{2d04}', '\0', '\0']), ('\u{10a5}', ['\u{2d05}',
+        '\0', '\0']), ('\u{10a6}', ['\u{2d06}', '\0', '\0']), ('\u{10a7}', ['\u{2d07}', '\0',
+        '\0']), ('\u{10a8}', ['\u{2d08}', '\0', '\0']), ('\u{10a9}', ['\u{2d09}', '\0', '\0']),
+        ('\u{10aa}', ['\u{2d0a}', '\0', '\0']), ('\u{10ab}', ['\u{2d0b}', '\0', '\0']), ('\u{10ac}',
+        ['\u{2d0c}', '\0', '\0']), ('\u{10ad}', ['\u{2d0d}', '\0', '\0']), ('\u{10ae}', ['\u{2d0e}',
+        '\0', '\0']), ('\u{10af}', ['\u{2d0f}', '\0', '\0']), ('\u{10b0}', ['\u{2d10}', '\0',
+        '\0']), ('\u{10b1}', ['\u{2d11}', '\0', '\0']), ('\u{10b2}', ['\u{2d12}', '\0', '\0']),
+        ('\u{10b3}', ['\u{2d13}', '\0', '\0']), ('\u{10b4}', ['\u{2d14}', '\0', '\0']), ('\u{10b5}',
+        ['\u{2d15}', '\0', '\0']), ('\u{10b6}', ['\u{2d16}', '\0', '\0']), ('\u{10b7}', ['\u{2d17}',
+        '\0', '\0']), ('\u{10b8}', ['\u{2d18}', '\0', '\0']), ('\u{10b9}', ['\u{2d19}', '\0',
+        '\0']), ('\u{10ba}', ['\u{2d1a}', '\0', '\0']), ('\u{10bb}', ['\u{2d1b}', '\0', '\0']),
+        ('\u{10bc}', ['\u{2d1c}', '\0', '\0']), ('\u{10bd}', ['\u{2d1d}', '\0', '\0']), ('\u{10be}',
+        ['\u{2d1e}', '\0', '\0']), ('\u{10bf}', ['\u{2d1f}', '\0', '\0']), ('\u{10c0}', ['\u{2d20}',
+        '\0', '\0']), ('\u{10c1}', ['\u{2d21}', '\0', '\0']), ('\u{10c2}', ['\u{2d22}', '\0',
+        '\0']), ('\u{10c3}', ['\u{2d23}', '\0', '\0']), ('\u{10c4}', ['\u{2d24}', '\0', '\0']),
+        ('\u{10c5}', ['\u{2d25}', '\0', '\0']), ('\u{10c7}', ['\u{2d27}', '\0', '\0']), ('\u{10cd}',
+        ['\u{2d2d}', '\0', '\0']), ('\u{1e00}', ['\u{1e01}', '\0', '\0']), ('\u{1e02}', ['\u{1e03}',
+        '\0', '\0']), ('\u{1e04}', ['\u{1e05}', '\0', '\0']), ('\u{1e06}', ['\u{1e07}', '\0',
+        '\0']), ('\u{1e08}', ['\u{1e09}', '\0', '\0']), ('\u{1e0a}', ['\u{1e0b}', '\0', '\0']),
+        ('\u{1e0c}', ['\u{1e0d}', '\0', '\0']), ('\u{1e0e}', ['\u{1e0f}', '\0', '\0']), ('\u{1e10}',
+        ['\u{1e11}', '\0', '\0']), ('\u{1e12}', ['\u{1e13}', '\0', '\0']), ('\u{1e14}', ['\u{1e15}',
+        '\0', '\0']), ('\u{1e16}', ['\u{1e17}', '\0', '\0']), ('\u{1e18}', ['\u{1e19}', '\0',
+        '\0']), ('\u{1e1a}', ['\u{1e1b}', '\0', '\0']), ('\u{1e1c}', ['\u{1e1d}', '\0', '\0']),
+        ('\u{1e1e}', ['\u{1e1f}', '\0', '\0']), ('\u{1e20}', ['\u{1e21}', '\0', '\0']), ('\u{1e22}',
+        ['\u{1e23}', '\0', '\0']), ('\u{1e24}', ['\u{1e25}', '\0', '\0']), ('\u{1e26}', ['\u{1e27}',
+        '\0', '\0']), ('\u{1e28}', ['\u{1e29}', '\0', '\0']), ('\u{1e2a}', ['\u{1e2b}', '\0',
+        '\0']), ('\u{1e2c}', ['\u{1e2d}', '\0', '\0']), ('\u{1e2e}', ['\u{1e2f}', '\0', '\0']),
+        ('\u{1e30}', ['\u{1e31}', '\0', '\0']), ('\u{1e32}', ['\u{1e33}', '\0', '\0']), ('\u{1e34}',
+        ['\u{1e35}', '\0', '\0']), ('\u{1e36}', ['\u{1e37}', '\0', '\0']), ('\u{1e38}', ['\u{1e39}',
+        '\0', '\0']), ('\u{1e3a}', ['\u{1e3b}', '\0', '\0']), ('\u{1e3c}', ['\u{1e3d}', '\0',
+        '\0']), ('\u{1e3e}', ['\u{1e3f}', '\0', '\0']), ('\u{1e40}', ['\u{1e41}', '\0', '\0']),
+        ('\u{1e42}', ['\u{1e43}', '\0', '\0']), ('\u{1e44}', ['\u{1e45}', '\0', '\0']), ('\u{1e46}',
+        ['\u{1e47}', '\0', '\0']), ('\u{1e48}', ['\u{1e49}', '\0', '\0']), ('\u{1e4a}', ['\u{1e4b}',
+        '\0', '\0']), ('\u{1e4c}', ['\u{1e4d}', '\0', '\0']), ('\u{1e4e}', ['\u{1e4f}', '\0',
+        '\0']), ('\u{1e50}', ['\u{1e51}', '\0', '\0']), ('\u{1e52}', ['\u{1e53}', '\0', '\0']),
+        ('\u{1e54}', ['\u{1e55}', '\0', '\0']), ('\u{1e56}', ['\u{1e57}', '\0', '\0']), ('\u{1e58}',
+        ['\u{1e59}', '\0', '\0']), ('\u{1e5a}', ['\u{1e5b}', '\0', '\0']), ('\u{1e5c}', ['\u{1e5d}',
+        '\0', '\0']), ('\u{1e5e}', ['\u{1e5f}', '\0', '\0']), ('\u{1e60}', ['\u{1e61}', '\0',
+        '\0']), ('\u{1e62}', ['\u{1e63}', '\0', '\0']), ('\u{1e64}', ['\u{1e65}', '\0', '\0']),
+        ('\u{1e66}', ['\u{1e67}', '\0', '\0']), ('\u{1e68}', ['\u{1e69}', '\0', '\0']), ('\u{1e6a}',
+        ['\u{1e6b}', '\0', '\0']), ('\u{1e6c}', ['\u{1e6d}', '\0', '\0']), ('\u{1e6e}', ['\u{1e6f}',
+        '\0', '\0']), ('\u{1e70}', ['\u{1e71}', '\0', '\0']), ('\u{1e72}', ['\u{1e73}', '\0',
+        '\0']), ('\u{1e74}', ['\u{1e75}', '\0', '\0']), ('\u{1e76}', ['\u{1e77}', '\0', '\0']),
+        ('\u{1e78}', ['\u{1e79}', '\0', '\0']), ('\u{1e7a}', ['\u{1e7b}', '\0', '\0']), ('\u{1e7c}',
+        ['\u{1e7d}', '\0', '\0']), ('\u{1e7e}', ['\u{1e7f}', '\0', '\0']), ('\u{1e80}', ['\u{1e81}',
+        '\0', '\0']), ('\u{1e82}', ['\u{1e83}', '\0', '\0']), ('\u{1e84}', ['\u{1e85}', '\0',
+        '\0']), ('\u{1e86}', ['\u{1e87}', '\0', '\0']), ('\u{1e88}', ['\u{1e89}', '\0', '\0']),
+        ('\u{1e8a}', ['\u{1e8b}', '\0', '\0']), ('\u{1e8c}', ['\u{1e8d}', '\0', '\0']), ('\u{1e8e}',
+        ['\u{1e8f}', '\0', '\0']), ('\u{1e90}', ['\u{1e91}', '\0', '\0']), ('\u{1e92}', ['\u{1e93}',
+        '\0', '\0']), ('\u{1e94}', ['\u{1e95}', '\0', '\0']), ('\u{1e9e}', ['\u{df}', '\0', '\0']),
+        ('\u{1ea0}', ['\u{1ea1}', '\0', '\0']), ('\u{1ea2}', ['\u{1ea3}', '\0', '\0']), ('\u{1ea4}',
+        ['\u{1ea5}', '\0', '\0']), ('\u{1ea6}', ['\u{1ea7}', '\0', '\0']), ('\u{1ea8}', ['\u{1ea9}',
+        '\0', '\0']), ('\u{1eaa}', ['\u{1eab}', '\0', '\0']), ('\u{1eac}', ['\u{1ead}', '\0',
+        '\0']), ('\u{1eae}', ['\u{1eaf}', '\0', '\0']), ('\u{1eb0}', ['\u{1eb1}', '\0', '\0']),
+        ('\u{1eb2}', ['\u{1eb3}', '\0', '\0']), ('\u{1eb4}', ['\u{1eb5}', '\0', '\0']), ('\u{1eb6}',
+        ['\u{1eb7}', '\0', '\0']), ('\u{1eb8}', ['\u{1eb9}', '\0', '\0']), ('\u{1eba}', ['\u{1ebb}',
+        '\0', '\0']), ('\u{1ebc}', ['\u{1ebd}', '\0', '\0']), ('\u{1ebe}', ['\u{1ebf}', '\0',
+        '\0']), ('\u{1ec0}', ['\u{1ec1}', '\0', '\0']), ('\u{1ec2}', ['\u{1ec3}', '\0', '\0']),
+        ('\u{1ec4}', ['\u{1ec5}', '\0', '\0']), ('\u{1ec6}', ['\u{1ec7}', '\0', '\0']), ('\u{1ec8}',
+        ['\u{1ec9}', '\0', '\0']), ('\u{1eca}', ['\u{1ecb}', '\0', '\0']), ('\u{1ecc}', ['\u{1ecd}',
+        '\0', '\0']), ('\u{1ece}', ['\u{1ecf}', '\0', '\0']), ('\u{1ed0}', ['\u{1ed1}', '\0',
+        '\0']), ('\u{1ed2}', ['\u{1ed3}', '\0', '\0']), ('\u{1ed4}', ['\u{1ed5}', '\0', '\0']),
+        ('\u{1ed6}', ['\u{1ed7}', '\0', '\0']), ('\u{1ed8}', ['\u{1ed9}', '\0', '\0']), ('\u{1eda}',
+        ['\u{1edb}', '\0', '\0']), ('\u{1edc}', ['\u{1edd}', '\0', '\0']), ('\u{1ede}', ['\u{1edf}',
+        '\0', '\0']), ('\u{1ee0}', ['\u{1ee1}', '\0', '\0']), ('\u{1ee2}', ['\u{1ee3}', '\0',
+        '\0']), ('\u{1ee4}', ['\u{1ee5}', '\0', '\0']), ('\u{1ee6}', ['\u{1ee7}', '\0', '\0']),
+        ('\u{1ee8}', ['\u{1ee9}', '\0', '\0']), ('\u{1eea}', ['\u{1eeb}', '\0', '\0']), ('\u{1eec}',
+        ['\u{1eed}', '\0', '\0']), ('\u{1eee}', ['\u{1eef}', '\0', '\0']), ('\u{1ef0}', ['\u{1ef1}',
+        '\0', '\0']), ('\u{1ef2}', ['\u{1ef3}', '\0', '\0']), ('\u{1ef4}', ['\u{1ef5}', '\0',
+        '\0']), ('\u{1ef6}', ['\u{1ef7}', '\0', '\0']), ('\u{1ef8}', ['\u{1ef9}', '\0', '\0']),
+        ('\u{1efa}', ['\u{1efb}', '\0', '\0']), ('\u{1efc}', ['\u{1efd}', '\0', '\0']), ('\u{1efe}',
+        ['\u{1eff}', '\0', '\0']), ('\u{1f08}', ['\u{1f00}', '\0', '\0']), ('\u{1f09}', ['\u{1f01}',
+        '\0', '\0']), ('\u{1f0a}', ['\u{1f02}', '\0', '\0']), ('\u{1f0b}', ['\u{1f03}', '\0',
+        '\0']), ('\u{1f0c}', ['\u{1f04}', '\0', '\0']), ('\u{1f0d}', ['\u{1f05}', '\0', '\0']),
+        ('\u{1f0e}', ['\u{1f06}', '\0', '\0']), ('\u{1f0f}', ['\u{1f07}', '\0', '\0']), ('\u{1f18}',
+        ['\u{1f10}', '\0', '\0']), ('\u{1f19}', ['\u{1f11}', '\0', '\0']), ('\u{1f1a}', ['\u{1f12}',
+        '\0', '\0']), ('\u{1f1b}', ['\u{1f13}', '\0', '\0']), ('\u{1f1c}', ['\u{1f14}', '\0',
+        '\0']), ('\u{1f1d}', ['\u{1f15}', '\0', '\0']), ('\u{1f28}', ['\u{1f20}', '\0', '\0']),
+        ('\u{1f29}', ['\u{1f21}', '\0', '\0']), ('\u{1f2a}', ['\u{1f22}', '\0', '\0']), ('\u{1f2b}',
+        ['\u{1f23}', '\0', '\0']), ('\u{1f2c}', ['\u{1f24}', '\0', '\0']), ('\u{1f2d}', ['\u{1f25}',
+        '\0', '\0']), ('\u{1f2e}', ['\u{1f26}', '\0', '\0']), ('\u{1f2f}', ['\u{1f27}', '\0',
+        '\0']), ('\u{1f38}', ['\u{1f30}', '\0', '\0']), ('\u{1f39}', ['\u{1f31}', '\0', '\0']),
+        ('\u{1f3a}', ['\u{1f32}', '\0', '\0']), ('\u{1f3b}', ['\u{1f33}', '\0', '\0']), ('\u{1f3c}',
+        ['\u{1f34}', '\0', '\0']), ('\u{1f3d}', ['\u{1f35}', '\0', '\0']), ('\u{1f3e}', ['\u{1f36}',
+        '\0', '\0']), ('\u{1f3f}', ['\u{1f37}', '\0', '\0']), ('\u{1f48}', ['\u{1f40}', '\0',
+        '\0']), ('\u{1f49}', ['\u{1f41}', '\0', '\0']), ('\u{1f4a}', ['\u{1f42}', '\0', '\0']),
+        ('\u{1f4b}', ['\u{1f43}', '\0', '\0']), ('\u{1f4c}', ['\u{1f44}', '\0', '\0']), ('\u{1f4d}',
+        ['\u{1f45}', '\0', '\0']), ('\u{1f59}', ['\u{1f51}', '\0', '\0']), ('\u{1f5b}', ['\u{1f53}',
+        '\0', '\0']), ('\u{1f5d}', ['\u{1f55}', '\0', '\0']), ('\u{1f5f}', ['\u{1f57}', '\0',
+        '\0']), ('\u{1f68}', ['\u{1f60}', '\0', '\0']), ('\u{1f69}', ['\u{1f61}', '\0', '\0']),
+        ('\u{1f6a}', ['\u{1f62}', '\0', '\0']), ('\u{1f6b}', ['\u{1f63}', '\0', '\0']), ('\u{1f6c}',
+        ['\u{1f64}', '\0', '\0']), ('\u{1f6d}', ['\u{1f65}', '\0', '\0']), ('\u{1f6e}', ['\u{1f66}',
+        '\0', '\0']), ('\u{1f6f}', ['\u{1f67}', '\0', '\0']), ('\u{1f88}', ['\u{1f80}', '\0',
+        '\0']), ('\u{1f89}', ['\u{1f81}', '\0', '\0']), ('\u{1f8a}', ['\u{1f82}', '\0', '\0']),
+        ('\u{1f8b}', ['\u{1f83}', '\0', '\0']), ('\u{1f8c}', ['\u{1f84}', '\0', '\0']), ('\u{1f8d}',
+        ['\u{1f85}', '\0', '\0']), ('\u{1f8e}', ['\u{1f86}', '\0', '\0']), ('\u{1f8f}', ['\u{1f87}',
+        '\0', '\0']), ('\u{1f98}', ['\u{1f90}', '\0', '\0']), ('\u{1f99}', ['\u{1f91}', '\0',
+        '\0']), ('\u{1f9a}', ['\u{1f92}', '\0', '\0']), ('\u{1f9b}', ['\u{1f93}', '\0', '\0']),
+        ('\u{1f9c}', ['\u{1f94}', '\0', '\0']), ('\u{1f9d}', ['\u{1f95}', '\0', '\0']), ('\u{1f9e}',
+        ['\u{1f96}', '\0', '\0']), ('\u{1f9f}', ['\u{1f97}', '\0', '\0']), ('\u{1fa8}', ['\u{1fa0}',
+        '\0', '\0']), ('\u{1fa9}', ['\u{1fa1}', '\0', '\0']), ('\u{1faa}', ['\u{1fa2}', '\0',
+        '\0']), ('\u{1fab}', ['\u{1fa3}', '\0', '\0']), ('\u{1fac}', ['\u{1fa4}', '\0', '\0']),
+        ('\u{1fad}', ['\u{1fa5}', '\0', '\0']), ('\u{1fae}', ['\u{1fa6}', '\0', '\0']), ('\u{1faf}',
+        ['\u{1fa7}', '\0', '\0']), ('\u{1fb8}', ['\u{1fb0}', '\0', '\0']), ('\u{1fb9}', ['\u{1fb1}',
+        '\0', '\0']), ('\u{1fba}', ['\u{1f70}', '\0', '\0']), ('\u{1fbb}', ['\u{1f71}', '\0',
+        '\0']), ('\u{1fbc}', ['\u{1fb3}', '\0', '\0']), ('\u{1fc8}', ['\u{1f72}', '\0', '\0']),
+        ('\u{1fc9}', ['\u{1f73}', '\0', '\0']), ('\u{1fca}', ['\u{1f74}', '\0', '\0']), ('\u{1fcb}',
+        ['\u{1f75}', '\0', '\0']), ('\u{1fcc}', ['\u{1fc3}', '\0', '\0']), ('\u{1fd8}', ['\u{1fd0}',
+        '\0', '\0']), ('\u{1fd9}', ['\u{1fd1}', '\0', '\0']), ('\u{1fda}', ['\u{1f76}', '\0',
+        '\0']), ('\u{1fdb}', ['\u{1f77}', '\0', '\0']), ('\u{1fe8}', ['\u{1fe0}', '\0', '\0']),
+        ('\u{1fe9}', ['\u{1fe1}', '\0', '\0']), ('\u{1fea}', ['\u{1f7a}', '\0', '\0']), ('\u{1feb}',
+        ['\u{1f7b}', '\0', '\0']), ('\u{1fec}', ['\u{1fe5}', '\0', '\0']), ('\u{1ff8}', ['\u{1f78}',
+        '\0', '\0']), ('\u{1ff9}', ['\u{1f79}', '\0', '\0']), ('\u{1ffa}', ['\u{1f7c}', '\0',
+        '\0']), ('\u{1ffb}', ['\u{1f7d}', '\0', '\0']), ('\u{1ffc}', ['\u{1ff3}', '\0', '\0']),
+        ('\u{2126}', ['\u{3c9}', '\0', '\0']), ('\u{212a}', ['\u{6b}', '\0', '\0']), ('\u{212b}',
+        ['\u{e5}', '\0', '\0']), ('\u{2132}', ['\u{214e}', '\0', '\0']), ('\u{2160}', ['\u{2170}',
+        '\0', '\0']), ('\u{2161}', ['\u{2171}', '\0', '\0']), ('\u{2162}', ['\u{2172}', '\0',
+        '\0']), ('\u{2163}', ['\u{2173}', '\0', '\0']), ('\u{2164}', ['\u{2174}', '\0', '\0']),
+        ('\u{2165}', ['\u{2175}', '\0', '\0']), ('\u{2166}', ['\u{2176}', '\0', '\0']), ('\u{2167}',
+        ['\u{2177}', '\0', '\0']), ('\u{2168}', ['\u{2178}', '\0', '\0']), ('\u{2169}', ['\u{2179}',
+        '\0', '\0']), ('\u{216a}', ['\u{217a}', '\0', '\0']), ('\u{216b}', ['\u{217b}', '\0',
+        '\0']), ('\u{216c}', ['\u{217c}', '\0', '\0']), ('\u{216d}', ['\u{217d}', '\0', '\0']),
+        ('\u{216e}', ['\u{217e}', '\0', '\0']), ('\u{216f}', ['\u{217f}', '\0', '\0']), ('\u{2183}',
+        ['\u{2184}', '\0', '\0']), ('\u{24b6}', ['\u{24d0}', '\0', '\0']), ('\u{24b7}', ['\u{24d1}',
+        '\0', '\0']), ('\u{24b8}', ['\u{24d2}', '\0', '\0']), ('\u{24b9}', ['\u{24d3}', '\0',
+        '\0']), ('\u{24ba}', ['\u{24d4}', '\0', '\0']), ('\u{24bb}', ['\u{24d5}', '\0', '\0']),
+        ('\u{24bc}', ['\u{24d6}', '\0', '\0']), ('\u{24bd}', ['\u{24d7}', '\0', '\0']), ('\u{24be}',
+        ['\u{24d8}', '\0', '\0']), ('\u{24bf}', ['\u{24d9}', '\0', '\0']), ('\u{24c0}', ['\u{24da}',
+        '\0', '\0']), ('\u{24c1}', ['\u{24db}', '\0', '\0']), ('\u{24c2}', ['\u{24dc}', '\0',
+        '\0']), ('\u{24c3}', ['\u{24dd}', '\0', '\0']), ('\u{24c4}', ['\u{24de}', '\0', '\0']),
+        ('\u{24c5}', ['\u{24df}', '\0', '\0']), ('\u{24c6}', ['\u{24e0}', '\0', '\0']), ('\u{24c7}',
+        ['\u{24e1}', '\0', '\0']), ('\u{24c8}', ['\u{24e2}', '\0', '\0']), ('\u{24c9}', ['\u{24e3}',
+        '\0', '\0']), ('\u{24ca}', ['\u{24e4}', '\0', '\0']), ('\u{24cb}', ['\u{24e5}', '\0',
+        '\0']), ('\u{24cc}', ['\u{24e6}', '\0', '\0']), ('\u{24cd}', ['\u{24e7}', '\0', '\0']),
+        ('\u{24ce}', ['\u{24e8}', '\0', '\0']), ('\u{24cf}', ['\u{24e9}', '\0', '\0']), ('\u{2c00}',
+        ['\u{2c30}', '\0', '\0']), ('\u{2c01}', ['\u{2c31}', '\0', '\0']), ('\u{2c02}', ['\u{2c32}',
+        '\0', '\0']), ('\u{2c03}', ['\u{2c33}', '\0', '\0']), ('\u{2c04}', ['\u{2c34}', '\0',
+        '\0']), ('\u{2c05}', ['\u{2c35}', '\0', '\0']), ('\u{2c06}', ['\u{2c36}', '\0', '\0']),
+        ('\u{2c07}', ['\u{2c37}', '\0', '\0']), ('\u{2c08}', ['\u{2c38}', '\0', '\0']), ('\u{2c09}',
+        ['\u{2c39}', '\0', '\0']), ('\u{2c0a}', ['\u{2c3a}', '\0', '\0']), ('\u{2c0b}', ['\u{2c3b}',
+        '\0', '\0']), ('\u{2c0c}', ['\u{2c3c}', '\0', '\0']), ('\u{2c0d}', ['\u{2c3d}', '\0',
+        '\0']), ('\u{2c0e}', ['\u{2c3e}', '\0', '\0']), ('\u{2c0f}', ['\u{2c3f}', '\0', '\0']),
+        ('\u{2c10}', ['\u{2c40}', '\0', '\0']), ('\u{2c11}', ['\u{2c41}', '\0', '\0']), ('\u{2c12}',
+        ['\u{2c42}', '\0', '\0']), ('\u{2c13}', ['\u{2c43}', '\0', '\0']), ('\u{2c14}', ['\u{2c44}',
+        '\0', '\0']), ('\u{2c15}', ['\u{2c45}', '\0', '\0']), ('\u{2c16}', ['\u{2c46}', '\0',
+        '\0']), ('\u{2c17}', ['\u{2c47}', '\0', '\0']), ('\u{2c18}', ['\u{2c48}', '\0', '\0']),
+        ('\u{2c19}', ['\u{2c49}', '\0', '\0']), ('\u{2c1a}', ['\u{2c4a}', '\0', '\0']), ('\u{2c1b}',
+        ['\u{2c4b}', '\0', '\0']), ('\u{2c1c}', ['\u{2c4c}', '\0', '\0']), ('\u{2c1d}', ['\u{2c4d}',
+        '\0', '\0']), ('\u{2c1e}', ['\u{2c4e}', '\0', '\0']), ('\u{2c1f}', ['\u{2c4f}', '\0',
+        '\0']), ('\u{2c20}', ['\u{2c50}', '\0', '\0']), ('\u{2c21}', ['\u{2c51}', '\0', '\0']),
+        ('\u{2c22}', ['\u{2c52}', '\0', '\0']), ('\u{2c23}', ['\u{2c53}', '\0', '\0']), ('\u{2c24}',
+        ['\u{2c54}', '\0', '\0']), ('\u{2c25}', ['\u{2c55}', '\0', '\0']), ('\u{2c26}', ['\u{2c56}',
+        '\0', '\0']), ('\u{2c27}', ['\u{2c57}', '\0', '\0']), ('\u{2c28}', ['\u{2c58}', '\0',
+        '\0']), ('\u{2c29}', ['\u{2c59}', '\0', '\0']), ('\u{2c2a}', ['\u{2c5a}', '\0', '\0']),
+        ('\u{2c2b}', ['\u{2c5b}', '\0', '\0']), ('\u{2c2c}', ['\u{2c5c}', '\0', '\0']), ('\u{2c2d}',
+        ['\u{2c5d}', '\0', '\0']), ('\u{2c2e}', ['\u{2c5e}', '\0', '\0']), ('\u{2c60}', ['\u{2c61}',
+        '\0', '\0']), ('\u{2c62}', ['\u{26b}', '\0', '\0']), ('\u{2c63}', ['\u{1d7d}', '\0', '\0']),
+        ('\u{2c64}', ['\u{27d}', '\0', '\0']), ('\u{2c67}', ['\u{2c68}', '\0', '\0']), ('\u{2c69}',
+        ['\u{2c6a}', '\0', '\0']), ('\u{2c6b}', ['\u{2c6c}', '\0', '\0']), ('\u{2c6d}', ['\u{251}',
+        '\0', '\0']), ('\u{2c6e}', ['\u{271}', '\0', '\0']), ('\u{2c6f}', ['\u{250}', '\0', '\0']),
+        ('\u{2c70}', ['\u{252}', '\0', '\0']), ('\u{2c72}', ['\u{2c73}', '\0', '\0']), ('\u{2c75}',
+        ['\u{2c76}', '\0', '\0']), ('\u{2c7e}', ['\u{23f}', '\0', '\0']), ('\u{2c7f}', ['\u{240}',
+        '\0', '\0']), ('\u{2c80}', ['\u{2c81}', '\0', '\0']), ('\u{2c82}', ['\u{2c83}', '\0',
+        '\0']), ('\u{2c84}', ['\u{2c85}', '\0', '\0']), ('\u{2c86}', ['\u{2c87}', '\0', '\0']),
+        ('\u{2c88}', ['\u{2c89}', '\0', '\0']), ('\u{2c8a}', ['\u{2c8b}', '\0', '\0']), ('\u{2c8c}',
+        ['\u{2c8d}', '\0', '\0']), ('\u{2c8e}', ['\u{2c8f}', '\0', '\0']), ('\u{2c90}', ['\u{2c91}',
+        '\0', '\0']), ('\u{2c92}', ['\u{2c93}', '\0', '\0']), ('\u{2c94}', ['\u{2c95}', '\0',
+        '\0']), ('\u{2c96}', ['\u{2c97}', '\0', '\0']), ('\u{2c98}', ['\u{2c99}', '\0', '\0']),
+        ('\u{2c9a}', ['\u{2c9b}', '\0', '\0']), ('\u{2c9c}', ['\u{2c9d}', '\0', '\0']), ('\u{2c9e}',
+        ['\u{2c9f}', '\0', '\0']), ('\u{2ca0}', ['\u{2ca1}', '\0', '\0']), ('\u{2ca2}', ['\u{2ca3}',
+        '\0', '\0']), ('\u{2ca4}', ['\u{2ca5}', '\0', '\0']), ('\u{2ca6}', ['\u{2ca7}', '\0',
+        '\0']), ('\u{2ca8}', ['\u{2ca9}', '\0', '\0']), ('\u{2caa}', ['\u{2cab}', '\0', '\0']),
+        ('\u{2cac}', ['\u{2cad}', '\0', '\0']), ('\u{2cae}', ['\u{2caf}', '\0', '\0']), ('\u{2cb0}',
+        ['\u{2cb1}', '\0', '\0']), ('\u{2cb2}', ['\u{2cb3}', '\0', '\0']), ('\u{2cb4}', ['\u{2cb5}',
+        '\0', '\0']), ('\u{2cb6}', ['\u{2cb7}', '\0', '\0']), ('\u{2cb8}', ['\u{2cb9}', '\0',
+        '\0']), ('\u{2cba}', ['\u{2cbb}', '\0', '\0']), ('\u{2cbc}', ['\u{2cbd}', '\0', '\0']),
+        ('\u{2cbe}', ['\u{2cbf}', '\0', '\0']), ('\u{2cc0}', ['\u{2cc1}', '\0', '\0']), ('\u{2cc2}',
+        ['\u{2cc3}', '\0', '\0']), ('\u{2cc4}', ['\u{2cc5}', '\0', '\0']), ('\u{2cc6}', ['\u{2cc7}',
+        '\0', '\0']), ('\u{2cc8}', ['\u{2cc9}', '\0', '\0']), ('\u{2cca}', ['\u{2ccb}', '\0',
+        '\0']), ('\u{2ccc}', ['\u{2ccd}', '\0', '\0']), ('\u{2cce}', ['\u{2ccf}', '\0', '\0']),
+        ('\u{2cd0}', ['\u{2cd1}', '\0', '\0']), ('\u{2cd2}', ['\u{2cd3}', '\0', '\0']), ('\u{2cd4}',
+        ['\u{2cd5}', '\0', '\0']), ('\u{2cd6}', ['\u{2cd7}', '\0', '\0']), ('\u{2cd8}', ['\u{2cd9}',
+        '\0', '\0']), ('\u{2cda}', ['\u{2cdb}', '\0', '\0']), ('\u{2cdc}', ['\u{2cdd}', '\0',
+        '\0']), ('\u{2cde}', ['\u{2cdf}', '\0', '\0']), ('\u{2ce0}', ['\u{2ce1}', '\0', '\0']),
+        ('\u{2ce2}', ['\u{2ce3}', '\0', '\0']), ('\u{2ceb}', ['\u{2cec}', '\0', '\0']), ('\u{2ced}',
+        ['\u{2cee}', '\0', '\0']), ('\u{2cf2}', ['\u{2cf3}', '\0', '\0']), ('\u{a640}', ['\u{a641}',
+        '\0', '\0']), ('\u{a642}', ['\u{a643}', '\0', '\0']), ('\u{a644}', ['\u{a645}', '\0',
+        '\0']), ('\u{a646}', ['\u{a647}', '\0', '\0']), ('\u{a648}', ['\u{a649}', '\0', '\0']),
+        ('\u{a64a}', ['\u{a64b}', '\0', '\0']), ('\u{a64c}', ['\u{a64d}', '\0', '\0']), ('\u{a64e}',
+        ['\u{a64f}', '\0', '\0']), ('\u{a650}', ['\u{a651}', '\0', '\0']), ('\u{a652}', ['\u{a653}',
+        '\0', '\0']), ('\u{a654}', ['\u{a655}', '\0', '\0']), ('\u{a656}', ['\u{a657}', '\0',
+        '\0']), ('\u{a658}', ['\u{a659}', '\0', '\0']), ('\u{a65a}', ['\u{a65b}', '\0', '\0']),
+        ('\u{a65c}', ['\u{a65d}', '\0', '\0']), ('\u{a65e}', ['\u{a65f}', '\0', '\0']), ('\u{a660}',
+        ['\u{a661}', '\0', '\0']), ('\u{a662}', ['\u{a663}', '\0', '\0']), ('\u{a664}', ['\u{a665}',
+        '\0', '\0']), ('\u{a666}', ['\u{a667}', '\0', '\0']), ('\u{a668}', ['\u{a669}', '\0',
+        '\0']), ('\u{a66a}', ['\u{a66b}', '\0', '\0']), ('\u{a66c}', ['\u{a66d}', '\0', '\0']),
+        ('\u{a680}', ['\u{a681}', '\0', '\0']), ('\u{a682}', ['\u{a683}', '\0', '\0']), ('\u{a684}',
+        ['\u{a685}', '\0', '\0']), ('\u{a686}', ['\u{a687}', '\0', '\0']), ('\u{a688}', ['\u{a689}',
+        '\0', '\0']), ('\u{a68a}', ['\u{a68b}', '\0', '\0']), ('\u{a68c}', ['\u{a68d}', '\0',
+        '\0']), ('\u{a68e}', ['\u{a68f}', '\0', '\0']), ('\u{a690}', ['\u{a691}', '\0', '\0']),
+        ('\u{a692}', ['\u{a693}', '\0', '\0']), ('\u{a694}', ['\u{a695}', '\0', '\0']), ('\u{a696}',
+        ['\u{a697}', '\0', '\0']), ('\u{a698}', ['\u{a699}', '\0', '\0']), ('\u{a69a}', ['\u{a69b}',
+        '\0', '\0']), ('\u{a722}', ['\u{a723}', '\0', '\0']), ('\u{a724}', ['\u{a725}', '\0',
+        '\0']), ('\u{a726}', ['\u{a727}', '\0', '\0']), ('\u{a728}', ['\u{a729}', '\0', '\0']),
+        ('\u{a72a}', ['\u{a72b}', '\0', '\0']), ('\u{a72c}', ['\u{a72d}', '\0', '\0']), ('\u{a72e}',
+        ['\u{a72f}', '\0', '\0']), ('\u{a732}', ['\u{a733}', '\0', '\0']), ('\u{a734}', ['\u{a735}',
+        '\0', '\0']), ('\u{a736}', ['\u{a737}', '\0', '\0']), ('\u{a738}', ['\u{a739}', '\0',
+        '\0']), ('\u{a73a}', ['\u{a73b}', '\0', '\0']), ('\u{a73c}', ['\u{a73d}', '\0', '\0']),
+        ('\u{a73e}', ['\u{a73f}', '\0', '\0']), ('\u{a740}', ['\u{a741}', '\0', '\0']), ('\u{a742}',
+        ['\u{a743}', '\0', '\0']), ('\u{a744}', ['\u{a745}', '\0', '\0']), ('\u{a746}', ['\u{a747}',
+        '\0', '\0']), ('\u{a748}', ['\u{a749}', '\0', '\0']), ('\u{a74a}', ['\u{a74b}', '\0',
+        '\0']), ('\u{a74c}', ['\u{a74d}', '\0', '\0']), ('\u{a74e}', ['\u{a74f}', '\0', '\0']),
+        ('\u{a750}', ['\u{a751}', '\0', '\0']), ('\u{a752}', ['\u{a753}', '\0', '\0']), ('\u{a754}',
+        ['\u{a755}', '\0', '\0']), ('\u{a756}', ['\u{a757}', '\0', '\0']), ('\u{a758}', ['\u{a759}',
+        '\0', '\0']), ('\u{a75a}', ['\u{a75b}', '\0', '\0']), ('\u{a75c}', ['\u{a75d}', '\0',
+        '\0']), ('\u{a75e}', ['\u{a75f}', '\0', '\0']), ('\u{a760}', ['\u{a761}', '\0', '\0']),
+        ('\u{a762}', ['\u{a763}', '\0', '\0']), ('\u{a764}', ['\u{a765}', '\0', '\0']), ('\u{a766}',
+        ['\u{a767}', '\0', '\0']), ('\u{a768}', ['\u{a769}', '\0', '\0']), ('\u{a76a}', ['\u{a76b}',
+        '\0', '\0']), ('\u{a76c}', ['\u{a76d}', '\0', '\0']), ('\u{a76e}', ['\u{a76f}', '\0',
+        '\0']), ('\u{a779}', ['\u{a77a}', '\0', '\0']), ('\u{a77b}', ['\u{a77c}', '\0', '\0']),
+        ('\u{a77d}', ['\u{1d79}', '\0', '\0']), ('\u{a77e}', ['\u{a77f}', '\0', '\0']), ('\u{a780}',
+        ['\u{a781}', '\0', '\0']), ('\u{a782}', ['\u{a783}', '\0', '\0']), ('\u{a784}', ['\u{a785}',
+        '\0', '\0']), ('\u{a786}', ['\u{a787}', '\0', '\0']), ('\u{a78b}', ['\u{a78c}', '\0',
+        '\0']), ('\u{a78d}', ['\u{265}', '\0', '\0']), ('\u{a790}', ['\u{a791}', '\0', '\0']),
+        ('\u{a792}', ['\u{a793}', '\0', '\0']), ('\u{a796}', ['\u{a797}', '\0', '\0']), ('\u{a798}',
+        ['\u{a799}', '\0', '\0']), ('\u{a79a}', ['\u{a79b}', '\0', '\0']), ('\u{a79c}', ['\u{a79d}',
+        '\0', '\0']), ('\u{a79e}', ['\u{a79f}', '\0', '\0']), ('\u{a7a0}', ['\u{a7a1}', '\0',
+        '\0']), ('\u{a7a2}', ['\u{a7a3}', '\0', '\0']), ('\u{a7a4}', ['\u{a7a5}', '\0', '\0']),
+        ('\u{a7a6}', ['\u{a7a7}', '\0', '\0']), ('\u{a7a8}', ['\u{a7a9}', '\0', '\0']), ('\u{a7aa}',
+        ['\u{266}', '\0', '\0']), ('\u{a7ab}', ['\u{25c}', '\0', '\0']), ('\u{a7ac}', ['\u{261}',
+        '\0', '\0']), ('\u{a7ad}', ['\u{26c}', '\0', '\0']), ('\u{a7b0}', ['\u{29e}', '\0', '\0']),
+        ('\u{a7b1}', ['\u{287}', '\0', '\0']), ('\u{ff21}', ['\u{ff41}', '\0', '\0']), ('\u{ff22}',
+        ['\u{ff42}', '\0', '\0']), ('\u{ff23}', ['\u{ff43}', '\0', '\0']), ('\u{ff24}', ['\u{ff44}',
+        '\0', '\0']), ('\u{ff25}', ['\u{ff45}', '\0', '\0']), ('\u{ff26}', ['\u{ff46}', '\0',
+        '\0']), ('\u{ff27}', ['\u{ff47}', '\0', '\0']), ('\u{ff28}', ['\u{ff48}', '\0', '\0']),
+        ('\u{ff29}', ['\u{ff49}', '\0', '\0']), ('\u{ff2a}', ['\u{ff4a}', '\0', '\0']), ('\u{ff2b}',
+        ['\u{ff4b}', '\0', '\0']), ('\u{ff2c}', ['\u{ff4c}', '\0', '\0']), ('\u{ff2d}', ['\u{ff4d}',
+        '\0', '\0']), ('\u{ff2e}', ['\u{ff4e}', '\0', '\0']), ('\u{ff2f}', ['\u{ff4f}', '\0',
+        '\0']), ('\u{ff30}', ['\u{ff50}', '\0', '\0']), ('\u{ff31}', ['\u{ff51}', '\0', '\0']),
+        ('\u{ff32}', ['\u{ff52}', '\0', '\0']), ('\u{ff33}', ['\u{ff53}', '\0', '\0']), ('\u{ff34}',
+        ['\u{ff54}', '\0', '\0']), ('\u{ff35}', ['\u{ff55}', '\0', '\0']), ('\u{ff36}', ['\u{ff56}',
+        '\0', '\0']), ('\u{ff37}', ['\u{ff57}', '\0', '\0']), ('\u{ff38}', ['\u{ff58}', '\0',
+        '\0']), ('\u{ff39}', ['\u{ff59}', '\0', '\0']), ('\u{ff3a}', ['\u{ff5a}', '\0', '\0']),
+        ('\u{10400}', ['\u{10428}', '\0', '\0']), ('\u{10401}', ['\u{10429}', '\0', '\0']),
+        ('\u{10402}', ['\u{1042a}', '\0', '\0']), ('\u{10403}', ['\u{1042b}', '\0', '\0']),
+        ('\u{10404}', ['\u{1042c}', '\0', '\0']), ('\u{10405}', ['\u{1042d}', '\0', '\0']),
+        ('\u{10406}', ['\u{1042e}', '\0', '\0']), ('\u{10407}', ['\u{1042f}', '\0', '\0']),
+        ('\u{10408}', ['\u{10430}', '\0', '\0']), ('\u{10409}', ['\u{10431}', '\0', '\0']),
+        ('\u{1040a}', ['\u{10432}', '\0', '\0']), ('\u{1040b}', ['\u{10433}', '\0', '\0']),
+        ('\u{1040c}', ['\u{10434}', '\0', '\0']), ('\u{1040d}', ['\u{10435}', '\0', '\0']),
+        ('\u{1040e}', ['\u{10436}', '\0', '\0']), ('\u{1040f}', ['\u{10437}', '\0', '\0']),
+        ('\u{10410}', ['\u{10438}', '\0', '\0']), ('\u{10411}', ['\u{10439}', '\0', '\0']),
+        ('\u{10412}', ['\u{1043a}', '\0', '\0']), ('\u{10413}', ['\u{1043b}', '\0', '\0']),
+        ('\u{10414}', ['\u{1043c}', '\0', '\0']), ('\u{10415}', ['\u{1043d}', '\0', '\0']),
+        ('\u{10416}', ['\u{1043e}', '\0', '\0']), ('\u{10417}', ['\u{1043f}', '\0', '\0']),
+        ('\u{10418}', ['\u{10440}', '\0', '\0']), ('\u{10419}', ['\u{10441}', '\0', '\0']),
+        ('\u{1041a}', ['\u{10442}', '\0', '\0']), ('\u{1041b}', ['\u{10443}', '\0', '\0']),
+        ('\u{1041c}', ['\u{10444}', '\0', '\0']), ('\u{1041d}', ['\u{10445}', '\0', '\0']),
+        ('\u{1041e}', ['\u{10446}', '\0', '\0']), ('\u{1041f}', ['\u{10447}', '\0', '\0']),
+        ('\u{10420}', ['\u{10448}', '\0', '\0']), ('\u{10421}', ['\u{10449}', '\0', '\0']),
+        ('\u{10422}', ['\u{1044a}', '\0', '\0']), ('\u{10423}', ['\u{1044b}', '\0', '\0']),
+        ('\u{10424}', ['\u{1044c}', '\0', '\0']), ('\u{10425}', ['\u{1044d}', '\0', '\0']),
+        ('\u{10426}', ['\u{1044e}', '\0', '\0']), ('\u{10427}', ['\u{1044f}', '\0', '\0']),
+        ('\u{118a0}', ['\u{118c0}', '\0', '\0']), ('\u{118a1}', ['\u{118c1}', '\0', '\0']),
+        ('\u{118a2}', ['\u{118c2}', '\0', '\0']), ('\u{118a3}', ['\u{118c3}', '\0', '\0']),
+        ('\u{118a4}', ['\u{118c4}', '\0', '\0']), ('\u{118a5}', ['\u{118c5}', '\0', '\0']),
+        ('\u{118a6}', ['\u{118c6}', '\0', '\0']), ('\u{118a7}', ['\u{118c7}', '\0', '\0']),
+        ('\u{118a8}', ['\u{118c8}', '\0', '\0']), ('\u{118a9}', ['\u{118c9}', '\0', '\0']),
+        ('\u{118aa}', ['\u{118ca}', '\0', '\0']), ('\u{118ab}', ['\u{118cb}', '\0', '\0']),
+        ('\u{118ac}', ['\u{118cc}', '\0', '\0']), ('\u{118ad}', ['\u{118cd}', '\0', '\0']),
+        ('\u{118ae}', ['\u{118ce}', '\0', '\0']), ('\u{118af}', ['\u{118cf}', '\0', '\0']),
+        ('\u{118b0}', ['\u{118d0}', '\0', '\0']), ('\u{118b1}', ['\u{118d1}', '\0', '\0']),
+        ('\u{118b2}', ['\u{118d2}', '\0', '\0']), ('\u{118b3}', ['\u{118d3}', '\0', '\0']),
+        ('\u{118b4}', ['\u{118d4}', '\0', '\0']), ('\u{118b5}', ['\u{118d5}', '\0', '\0']),
+        ('\u{118b6}', ['\u{118d6}', '\0', '\0']), ('\u{118b7}', ['\u{118d7}', '\0', '\0']),
+        ('\u{118b8}', ['\u{118d8}', '\0', '\0']), ('\u{118b9}', ['\u{118d9}', '\0', '\0']),
+        ('\u{118ba}', ['\u{118da}', '\0', '\0']), ('\u{118bb}', ['\u{118db}', '\0', '\0']),
+        ('\u{118bc}', ['\u{118dc}', '\0', '\0']), ('\u{118bd}', ['\u{118dd}', '\0', '\0']),
+        ('\u{118be}', ['\u{118de}', '\0', '\0']), ('\u{118bf}', ['\u{118df}', '\0', '\0'])
+    ];
+
+    const to_uppercase_table: &'static [(char, [char; 3])] = &[
+        ('\u{61}', ['\u{41}', '\0', '\0']), ('\u{62}', ['\u{42}', '\0', '\0']), ('\u{63}',
+        ['\u{43}', '\0', '\0']), ('\u{64}', ['\u{44}', '\0', '\0']), ('\u{65}', ['\u{45}', '\0',
+        '\0']), ('\u{66}', ['\u{46}', '\0', '\0']), ('\u{67}', ['\u{47}', '\0', '\0']), ('\u{68}',
+        ['\u{48}', '\0', '\0']), ('\u{69}', ['\u{49}', '\0', '\0']), ('\u{6a}', ['\u{4a}', '\0',
+        '\0']), ('\u{6b}', ['\u{4b}', '\0', '\0']), ('\u{6c}', ['\u{4c}', '\0', '\0']), ('\u{6d}',
+        ['\u{4d}', '\0', '\0']), ('\u{6e}', ['\u{4e}', '\0', '\0']), ('\u{6f}', ['\u{4f}', '\0',
+        '\0']), ('\u{70}', ['\u{50}', '\0', '\0']), ('\u{71}', ['\u{51}', '\0', '\0']), ('\u{72}',
+        ['\u{52}', '\0', '\0']), ('\u{73}', ['\u{53}', '\0', '\0']), ('\u{74}', ['\u{54}', '\0',
+        '\0']), ('\u{75}', ['\u{55}', '\0', '\0']), ('\u{76}', ['\u{56}', '\0', '\0']), ('\u{77}',
+        ['\u{57}', '\0', '\0']), ('\u{78}', ['\u{58}', '\0', '\0']), ('\u{79}', ['\u{59}', '\0',
+        '\0']), ('\u{7a}', ['\u{5a}', '\0', '\0']), ('\u{b5}', ['\u{39c}', '\0', '\0']), ('\u{df}',
+        ['\u{53}', '\u{53}', '\0']), ('\u{e0}', ['\u{c0}', '\0', '\0']), ('\u{e1}', ['\u{c1}', '\0',
+        '\0']), ('\u{e2}', ['\u{c2}', '\0', '\0']), ('\u{e3}', ['\u{c3}', '\0', '\0']), ('\u{e4}',
+        ['\u{c4}', '\0', '\0']), ('\u{e5}', ['\u{c5}', '\0', '\0']), ('\u{e6}', ['\u{c6}', '\0',
+        '\0']), ('\u{e7}', ['\u{c7}', '\0', '\0']), ('\u{e8}', ['\u{c8}', '\0', '\0']), ('\u{e9}',
+        ['\u{c9}', '\0', '\0']), ('\u{ea}', ['\u{ca}', '\0', '\0']), ('\u{eb}', ['\u{cb}', '\0',
+        '\0']), ('\u{ec}', ['\u{cc}', '\0', '\0']), ('\u{ed}', ['\u{cd}', '\0', '\0']), ('\u{ee}',
+        ['\u{ce}', '\0', '\0']), ('\u{ef}', ['\u{cf}', '\0', '\0']), ('\u{f0}', ['\u{d0}', '\0',
+        '\0']), ('\u{f1}', ['\u{d1}', '\0', '\0']), ('\u{f2}', ['\u{d2}', '\0', '\0']), ('\u{f3}',
+        ['\u{d3}', '\0', '\0']), ('\u{f4}', ['\u{d4}', '\0', '\0']), ('\u{f5}', ['\u{d5}', '\0',
+        '\0']), ('\u{f6}', ['\u{d6}', '\0', '\0']), ('\u{f8}', ['\u{d8}', '\0', '\0']), ('\u{f9}',
+        ['\u{d9}', '\0', '\0']), ('\u{fa}', ['\u{da}', '\0', '\0']), ('\u{fb}', ['\u{db}', '\0',
+        '\0']), ('\u{fc}', ['\u{dc}', '\0', '\0']), ('\u{fd}', ['\u{dd}', '\0', '\0']), ('\u{fe}',
+        ['\u{de}', '\0', '\0']), ('\u{ff}', ['\u{178}', '\0', '\0']), ('\u{101}', ['\u{100}', '\0',
+        '\0']), ('\u{103}', ['\u{102}', '\0', '\0']), ('\u{105}', ['\u{104}', '\0', '\0']),
+        ('\u{107}', ['\u{106}', '\0', '\0']), ('\u{109}', ['\u{108}', '\0', '\0']), ('\u{10b}',
+        ['\u{10a}', '\0', '\0']), ('\u{10d}', ['\u{10c}', '\0', '\0']), ('\u{10f}', ['\u{10e}',
+        '\0', '\0']), ('\u{111}', ['\u{110}', '\0', '\0']), ('\u{113}', ['\u{112}', '\0', '\0']),
+        ('\u{115}', ['\u{114}', '\0', '\0']), ('\u{117}', ['\u{116}', '\0', '\0']), ('\u{119}',
+        ['\u{118}', '\0', '\0']), ('\u{11b}', ['\u{11a}', '\0', '\0']), ('\u{11d}', ['\u{11c}',
+        '\0', '\0']), ('\u{11f}', ['\u{11e}', '\0', '\0']), ('\u{121}', ['\u{120}', '\0', '\0']),
+        ('\u{123}', ['\u{122}', '\0', '\0']), ('\u{125}', ['\u{124}', '\0', '\0']), ('\u{127}',
+        ['\u{126}', '\0', '\0']), ('\u{129}', ['\u{128}', '\0', '\0']), ('\u{12b}', ['\u{12a}',
+        '\0', '\0']), ('\u{12d}', ['\u{12c}', '\0', '\0']), ('\u{12f}', ['\u{12e}', '\0', '\0']),
+        ('\u{131}', ['\u{49}', '\0', '\0']), ('\u{133}', ['\u{132}', '\0', '\0']), ('\u{135}',
+        ['\u{134}', '\0', '\0']), ('\u{137}', ['\u{136}', '\0', '\0']), ('\u{13a}', ['\u{139}',
+        '\0', '\0']), ('\u{13c}', ['\u{13b}', '\0', '\0']), ('\u{13e}', ['\u{13d}', '\0', '\0']),
+        ('\u{140}', ['\u{13f}', '\0', '\0']), ('\u{142}', ['\u{141}', '\0', '\0']), ('\u{144}',
+        ['\u{143}', '\0', '\0']), ('\u{146}', ['\u{145}', '\0', '\0']), ('\u{148}', ['\u{147}',
+        '\0', '\0']), ('\u{149}', ['\u{2bc}', '\u{4e}', '\0']), ('\u{14b}', ['\u{14a}', '\0',
+        '\0']), ('\u{14d}', ['\u{14c}', '\0', '\0']), ('\u{14f}', ['\u{14e}', '\0', '\0']),
+        ('\u{151}', ['\u{150}', '\0', '\0']), ('\u{153}', ['\u{152}', '\0', '\0']), ('\u{155}',
+        ['\u{154}', '\0', '\0']), ('\u{157}', ['\u{156}', '\0', '\0']), ('\u{159}', ['\u{158}',
+        '\0', '\0']), ('\u{15b}', ['\u{15a}', '\0', '\0']), ('\u{15d}', ['\u{15c}', '\0', '\0']),
+        ('\u{15f}', ['\u{15e}', '\0', '\0']), ('\u{161}', ['\u{160}', '\0', '\0']), ('\u{163}',
+        ['\u{162}', '\0', '\0']), ('\u{165}', ['\u{164}', '\0', '\0']), ('\u{167}', ['\u{166}',
+        '\0', '\0']), ('\u{169}', ['\u{168}', '\0', '\0']), ('\u{16b}', ['\u{16a}', '\0', '\0']),
+        ('\u{16d}', ['\u{16c}', '\0', '\0']), ('\u{16f}', ['\u{16e}', '\0', '\0']), ('\u{171}',
+        ['\u{170}', '\0', '\0']), ('\u{173}', ['\u{172}', '\0', '\0']), ('\u{175}', ['\u{174}',
+        '\0', '\0']), ('\u{177}', ['\u{176}', '\0', '\0']), ('\u{17a}', ['\u{179}', '\0', '\0']),
+        ('\u{17c}', ['\u{17b}', '\0', '\0']), ('\u{17e}', ['\u{17d}', '\0', '\0']), ('\u{17f}',
+        ['\u{53}', '\0', '\0']), ('\u{180}', ['\u{243}', '\0', '\0']), ('\u{183}', ['\u{182}', '\0',
+        '\0']), ('\u{185}', ['\u{184}', '\0', '\0']), ('\u{188}', ['\u{187}', '\0', '\0']),
+        ('\u{18c}', ['\u{18b}', '\0', '\0']), ('\u{192}', ['\u{191}', '\0', '\0']), ('\u{195}',
+        ['\u{1f6}', '\0', '\0']), ('\u{199}', ['\u{198}', '\0', '\0']), ('\u{19a}', ['\u{23d}',
+        '\0', '\0']), ('\u{19e}', ['\u{220}', '\0', '\0']), ('\u{1a1}', ['\u{1a0}', '\0', '\0']),
+        ('\u{1a3}', ['\u{1a2}', '\0', '\0']), ('\u{1a5}', ['\u{1a4}', '\0', '\0']), ('\u{1a8}',
+        ['\u{1a7}', '\0', '\0']), ('\u{1ad}', ['\u{1ac}', '\0', '\0']), ('\u{1b0}', ['\u{1af}',
+        '\0', '\0']), ('\u{1b4}', ['\u{1b3}', '\0', '\0']), ('\u{1b6}', ['\u{1b5}', '\0', '\0']),
+        ('\u{1b9}', ['\u{1b8}', '\0', '\0']), ('\u{1bd}', ['\u{1bc}', '\0', '\0']), ('\u{1bf}',
+        ['\u{1f7}', '\0', '\0']), ('\u{1c5}', ['\u{1c4}', '\0', '\0']), ('\u{1c6}', ['\u{1c4}',
+        '\0', '\0']), ('\u{1c8}', ['\u{1c7}', '\0', '\0']), ('\u{1c9}', ['\u{1c7}', '\0', '\0']),
+        ('\u{1cb}', ['\u{1ca}', '\0', '\0']), ('\u{1cc}', ['\u{1ca}', '\0', '\0']), ('\u{1ce}',
+        ['\u{1cd}', '\0', '\0']), ('\u{1d0}', ['\u{1cf}', '\0', '\0']), ('\u{1d2}', ['\u{1d1}',
+        '\0', '\0']), ('\u{1d4}', ['\u{1d3}', '\0', '\0']), ('\u{1d6}', ['\u{1d5}', '\0', '\0']),
+        ('\u{1d8}', ['\u{1d7}', '\0', '\0']), ('\u{1da}', ['\u{1d9}', '\0', '\0']), ('\u{1dc}',
+        ['\u{1db}', '\0', '\0']), ('\u{1dd}', ['\u{18e}', '\0', '\0']), ('\u{1df}', ['\u{1de}',
+        '\0', '\0']), ('\u{1e1}', ['\u{1e0}', '\0', '\0']), ('\u{1e3}', ['\u{1e2}', '\0', '\0']),
+        ('\u{1e5}', ['\u{1e4}', '\0', '\0']), ('\u{1e7}', ['\u{1e6}', '\0', '\0']), ('\u{1e9}',
+        ['\u{1e8}', '\0', '\0']), ('\u{1eb}', ['\u{1ea}', '\0', '\0']), ('\u{1ed}', ['\u{1ec}',
+        '\0', '\0']), ('\u{1ef}', ['\u{1ee}', '\0', '\0']), ('\u{1f0}', ['\u{4a}', '\u{30c}',
+        '\0']), ('\u{1f2}', ['\u{1f1}', '\0', '\0']), ('\u{1f3}', ['\u{1f1}', '\0', '\0']),
+        ('\u{1f5}', ['\u{1f4}', '\0', '\0']), ('\u{1f9}', ['\u{1f8}', '\0', '\0']), ('\u{1fb}',
+        ['\u{1fa}', '\0', '\0']), ('\u{1fd}', ['\u{1fc}', '\0', '\0']), ('\u{1ff}', ['\u{1fe}',
+        '\0', '\0']), ('\u{201}', ['\u{200}', '\0', '\0']), ('\u{203}', ['\u{202}', '\0', '\0']),
+        ('\u{205}', ['\u{204}', '\0', '\0']), ('\u{207}', ['\u{206}', '\0', '\0']), ('\u{209}',
+        ['\u{208}', '\0', '\0']), ('\u{20b}', ['\u{20a}', '\0', '\0']), ('\u{20d}', ['\u{20c}',
+        '\0', '\0']), ('\u{20f}', ['\u{20e}', '\0', '\0']), ('\u{211}', ['\u{210}', '\0', '\0']),
+        ('\u{213}', ['\u{212}', '\0', '\0']), ('\u{215}', ['\u{214}', '\0', '\0']), ('\u{217}',
+        ['\u{216}', '\0', '\0']), ('\u{219}', ['\u{218}', '\0', '\0']), ('\u{21b}', ['\u{21a}',
+        '\0', '\0']), ('\u{21d}', ['\u{21c}', '\0', '\0']), ('\u{21f}', ['\u{21e}', '\0', '\0']),
+        ('\u{223}', ['\u{222}', '\0', '\0']), ('\u{225}', ['\u{224}', '\0', '\0']), ('\u{227}',
+        ['\u{226}', '\0', '\0']), ('\u{229}', ['\u{228}', '\0', '\0']), ('\u{22b}', ['\u{22a}',
+        '\0', '\0']), ('\u{22d}', ['\u{22c}', '\0', '\0']), ('\u{22f}', ['\u{22e}', '\0', '\0']),
+        ('\u{231}', ['\u{230}', '\0', '\0']), ('\u{233}', ['\u{232}', '\0', '\0']), ('\u{23c}',
+        ['\u{23b}', '\0', '\0']), ('\u{23f}', ['\u{2c7e}', '\0', '\0']), ('\u{240}', ['\u{2c7f}',
+        '\0', '\0']), ('\u{242}', ['\u{241}', '\0', '\0']), ('\u{247}', ['\u{246}', '\0', '\0']),
+        ('\u{249}', ['\u{248}', '\0', '\0']), ('\u{24b}', ['\u{24a}', '\0', '\0']), ('\u{24d}',
+        ['\u{24c}', '\0', '\0']), ('\u{24f}', ['\u{24e}', '\0', '\0']), ('\u{250}', ['\u{2c6f}',
+        '\0', '\0']), ('\u{251}', ['\u{2c6d}', '\0', '\0']), ('\u{252}', ['\u{2c70}', '\0', '\0']),
+        ('\u{253}', ['\u{181}', '\0', '\0']), ('\u{254}', ['\u{186}', '\0', '\0']), ('\u{256}',
+        ['\u{189}', '\0', '\0']), ('\u{257}', ['\u{18a}', '\0', '\0']), ('\u{259}', ['\u{18f}',
+        '\0', '\0']), ('\u{25b}', ['\u{190}', '\0', '\0']), ('\u{25c}', ['\u{a7ab}', '\0', '\0']),
+        ('\u{260}', ['\u{193}', '\0', '\0']), ('\u{261}', ['\u{a7ac}', '\0', '\0']), ('\u{263}',
+        ['\u{194}', '\0', '\0']), ('\u{265}', ['\u{a78d}', '\0', '\0']), ('\u{266}', ['\u{a7aa}',
+        '\0', '\0']), ('\u{268}', ['\u{197}', '\0', '\0']), ('\u{269}', ['\u{196}', '\0', '\0']),
+        ('\u{26b}', ['\u{2c62}', '\0', '\0']), ('\u{26c}', ['\u{a7ad}', '\0', '\0']), ('\u{26f}',
+        ['\u{19c}', '\0', '\0']), ('\u{271}', ['\u{2c6e}', '\0', '\0']), ('\u{272}', ['\u{19d}',
+        '\0', '\0']), ('\u{275}', ['\u{19f}', '\0', '\0']), ('\u{27d}', ['\u{2c64}', '\0', '\0']),
+        ('\u{280}', ['\u{1a6}', '\0', '\0']), ('\u{283}', ['\u{1a9}', '\0', '\0']), ('\u{287}',
+        ['\u{a7b1}', '\0', '\0']), ('\u{288}', ['\u{1ae}', '\0', '\0']), ('\u{289}', ['\u{244}',
+        '\0', '\0']), ('\u{28a}', ['\u{1b1}', '\0', '\0']), ('\u{28b}', ['\u{1b2}', '\0', '\0']),
+        ('\u{28c}', ['\u{245}', '\0', '\0']), ('\u{292}', ['\u{1b7}', '\0', '\0']), ('\u{29e}',
+        ['\u{a7b0}', '\0', '\0']), ('\u{345}', ['\u{399}', '\0', '\0']), ('\u{371}', ['\u{370}',
+        '\0', '\0']), ('\u{373}', ['\u{372}', '\0', '\0']), ('\u{377}', ['\u{376}', '\0', '\0']),
+        ('\u{37b}', ['\u{3fd}', '\0', '\0']), ('\u{37c}', ['\u{3fe}', '\0', '\0']), ('\u{37d}',
+        ['\u{3ff}', '\0', '\0']), ('\u{390}', ['\u{399}', '\u{308}', '\u{301}']), ('\u{3ac}',
+        ['\u{386}', '\0', '\0']), ('\u{3ad}', ['\u{388}', '\0', '\0']), ('\u{3ae}', ['\u{389}',
+        '\0', '\0']), ('\u{3af}', ['\u{38a}', '\0', '\0']), ('\u{3b0}', ['\u{3a5}', '\u{308}',
+        '\u{301}']), ('\u{3b1}', ['\u{391}', '\0', '\0']), ('\u{3b2}', ['\u{392}', '\0', '\0']),
+        ('\u{3b3}', ['\u{393}', '\0', '\0']), ('\u{3b4}', ['\u{394}', '\0', '\0']), ('\u{3b5}',
+        ['\u{395}', '\0', '\0']), ('\u{3b6}', ['\u{396}', '\0', '\0']), ('\u{3b7}', ['\u{397}',
+        '\0', '\0']), ('\u{3b8}', ['\u{398}', '\0', '\0']), ('\u{3b9}', ['\u{399}', '\0', '\0']),
+        ('\u{3ba}', ['\u{39a}', '\0', '\0']), ('\u{3bb}', ['\u{39b}', '\0', '\0']), ('\u{3bc}',
+        ['\u{39c}', '\0', '\0']), ('\u{3bd}', ['\u{39d}', '\0', '\0']), ('\u{3be}', ['\u{39e}',
+        '\0', '\0']), ('\u{3bf}', ['\u{39f}', '\0', '\0']), ('\u{3c0}', ['\u{3a0}', '\0', '\0']),
+        ('\u{3c1}', ['\u{3a1}', '\0', '\0']), ('\u{3c2}', ['\u{3a3}', '\0', '\0']), ('\u{3c3}',
+        ['\u{3a3}', '\0', '\0']), ('\u{3c4}', ['\u{3a4}', '\0', '\0']), ('\u{3c5}', ['\u{3a5}',
+        '\0', '\0']), ('\u{3c6}', ['\u{3a6}', '\0', '\0']), ('\u{3c7}', ['\u{3a7}', '\0', '\0']),
+        ('\u{3c8}', ['\u{3a8}', '\0', '\0']), ('\u{3c9}', ['\u{3a9}', '\0', '\0']), ('\u{3ca}',
+        ['\u{3aa}', '\0', '\0']), ('\u{3cb}', ['\u{3ab}', '\0', '\0']), ('\u{3cc}', ['\u{38c}',
+        '\0', '\0']), ('\u{3cd}', ['\u{38e}', '\0', '\0']), ('\u{3ce}', ['\u{38f}', '\0', '\0']),
+        ('\u{3d0}', ['\u{392}', '\0', '\0']), ('\u{3d1}', ['\u{398}', '\0', '\0']), ('\u{3d5}',
+        ['\u{3a6}', '\0', '\0']), ('\u{3d6}', ['\u{3a0}', '\0', '\0']), ('\u{3d7}', ['\u{3cf}',
+        '\0', '\0']), ('\u{3d9}', ['\u{3d8}', '\0', '\0']), ('\u{3db}', ['\u{3da}', '\0', '\0']),
+        ('\u{3dd}', ['\u{3dc}', '\0', '\0']), ('\u{3df}', ['\u{3de}', '\0', '\0']), ('\u{3e1}',
+        ['\u{3e0}', '\0', '\0']), ('\u{3e3}', ['\u{3e2}', '\0', '\0']), ('\u{3e5}', ['\u{3e4}',
+        '\0', '\0']), ('\u{3e7}', ['\u{3e6}', '\0', '\0']), ('\u{3e9}', ['\u{3e8}', '\0', '\0']),
+        ('\u{3eb}', ['\u{3ea}', '\0', '\0']), ('\u{3ed}', ['\u{3ec}', '\0', '\0']), ('\u{3ef}',
+        ['\u{3ee}', '\0', '\0']), ('\u{3f0}', ['\u{39a}', '\0', '\0']), ('\u{3f1}', ['\u{3a1}',
+        '\0', '\0']), ('\u{3f2}', ['\u{3f9}', '\0', '\0']), ('\u{3f3}', ['\u{37f}', '\0', '\0']),
+        ('\u{3f5}', ['\u{395}', '\0', '\0']), ('\u{3f8}', ['\u{3f7}', '\0', '\0']), ('\u{3fb}',
+        ['\u{3fa}', '\0', '\0']), ('\u{430}', ['\u{410}', '\0', '\0']), ('\u{431}', ['\u{411}',
+        '\0', '\0']), ('\u{432}', ['\u{412}', '\0', '\0']), ('\u{433}', ['\u{413}', '\0', '\0']),
+        ('\u{434}', ['\u{414}', '\0', '\0']), ('\u{435}', ['\u{415}', '\0', '\0']), ('\u{436}',
+        ['\u{416}', '\0', '\0']), ('\u{437}', ['\u{417}', '\0', '\0']), ('\u{438}', ['\u{418}',
+        '\0', '\0']), ('\u{439}', ['\u{419}', '\0', '\0']), ('\u{43a}', ['\u{41a}', '\0', '\0']),
+        ('\u{43b}', ['\u{41b}', '\0', '\0']), ('\u{43c}', ['\u{41c}', '\0', '\0']), ('\u{43d}',
+        ['\u{41d}', '\0', '\0']), ('\u{43e}', ['\u{41e}', '\0', '\0']), ('\u{43f}', ['\u{41f}',
+        '\0', '\0']), ('\u{440}', ['\u{420}', '\0', '\0']), ('\u{441}', ['\u{421}', '\0', '\0']),
+        ('\u{442}', ['\u{422}', '\0', '\0']), ('\u{443}', ['\u{423}', '\0', '\0']), ('\u{444}',
+        ['\u{424}', '\0', '\0']), ('\u{445}', ['\u{425}', '\0', '\0']), ('\u{446}', ['\u{426}',
+        '\0', '\0']), ('\u{447}', ['\u{427}', '\0', '\0']), ('\u{448}', ['\u{428}', '\0', '\0']),
+        ('\u{449}', ['\u{429}', '\0', '\0']), ('\u{44a}', ['\u{42a}', '\0', '\0']), ('\u{44b}',
+        ['\u{42b}', '\0', '\0']), ('\u{44c}', ['\u{42c}', '\0', '\0']), ('\u{44d}', ['\u{42d}',
+        '\0', '\0']), ('\u{44e}', ['\u{42e}', '\0', '\0']), ('\u{44f}', ['\u{42f}', '\0', '\0']),
+        ('\u{450}', ['\u{400}', '\0', '\0']), ('\u{451}', ['\u{401}', '\0', '\0']), ('\u{452}',
+        ['\u{402}', '\0', '\0']), ('\u{453}', ['\u{403}', '\0', '\0']), ('\u{454}', ['\u{404}',
+        '\0', '\0']), ('\u{455}', ['\u{405}', '\0', '\0']), ('\u{456}', ['\u{406}', '\0', '\0']),
+        ('\u{457}', ['\u{407}', '\0', '\0']), ('\u{458}', ['\u{408}', '\0', '\0']), ('\u{459}',
+        ['\u{409}', '\0', '\0']), ('\u{45a}', ['\u{40a}', '\0', '\0']), ('\u{45b}', ['\u{40b}',
+        '\0', '\0']), ('\u{45c}', ['\u{40c}', '\0', '\0']), ('\u{45d}', ['\u{40d}', '\0', '\0']),
+        ('\u{45e}', ['\u{40e}', '\0', '\0']), ('\u{45f}', ['\u{40f}', '\0', '\0']), ('\u{461}',
+        ['\u{460}', '\0', '\0']), ('\u{463}', ['\u{462}', '\0', '\0']), ('\u{465}', ['\u{464}',
+        '\0', '\0']), ('\u{467}', ['\u{466}', '\0', '\0']), ('\u{469}', ['\u{468}', '\0', '\0']),
+        ('\u{46b}', ['\u{46a}', '\0', '\0']), ('\u{46d}', ['\u{46c}', '\0', '\0']), ('\u{46f}',
+        ['\u{46e}', '\0', '\0']), ('\u{471}', ['\u{470}', '\0', '\0']), ('\u{473}', ['\u{472}',
+        '\0', '\0']), ('\u{475}', ['\u{474}', '\0', '\0']), ('\u{477}', ['\u{476}', '\0', '\0']),
+        ('\u{479}', ['\u{478}', '\0', '\0']), ('\u{47b}', ['\u{47a}', '\0', '\0']), ('\u{47d}',
+        ['\u{47c}', '\0', '\0']), ('\u{47f}', ['\u{47e}', '\0', '\0']), ('\u{481}', ['\u{480}',
+        '\0', '\0']), ('\u{48b}', ['\u{48a}', '\0', '\0']), ('\u{48d}', ['\u{48c}', '\0', '\0']),
+        ('\u{48f}', ['\u{48e}', '\0', '\0']), ('\u{491}', ['\u{490}', '\0', '\0']), ('\u{493}',
+        ['\u{492}', '\0', '\0']), ('\u{495}', ['\u{494}', '\0', '\0']), ('\u{497}', ['\u{496}',
+        '\0', '\0']), ('\u{499}', ['\u{498}', '\0', '\0']), ('\u{49b}', ['\u{49a}', '\0', '\0']),
+        ('\u{49d}', ['\u{49c}', '\0', '\0']), ('\u{49f}', ['\u{49e}', '\0', '\0']), ('\u{4a1}',
+        ['\u{4a0}', '\0', '\0']), ('\u{4a3}', ['\u{4a2}', '\0', '\0']), ('\u{4a5}', ['\u{4a4}',
+        '\0', '\0']), ('\u{4a7}', ['\u{4a6}', '\0', '\0']), ('\u{4a9}', ['\u{4a8}', '\0', '\0']),
+        ('\u{4ab}', ['\u{4aa}', '\0', '\0']), ('\u{4ad}', ['\u{4ac}', '\0', '\0']), ('\u{4af}',
+        ['\u{4ae}', '\0', '\0']), ('\u{4b1}', ['\u{4b0}', '\0', '\0']), ('\u{4b3}', ['\u{4b2}',
+        '\0', '\0']), ('\u{4b5}', ['\u{4b4}', '\0', '\0']), ('\u{4b7}', ['\u{4b6}', '\0', '\0']),
+        ('\u{4b9}', ['\u{4b8}', '\0', '\0']), ('\u{4bb}', ['\u{4ba}', '\0', '\0']), ('\u{4bd}',
+        ['\u{4bc}', '\0', '\0']), ('\u{4bf}', ['\u{4be}', '\0', '\0']), ('\u{4c2}', ['\u{4c1}',
+        '\0', '\0']), ('\u{4c4}', ['\u{4c3}', '\0', '\0']), ('\u{4c6}', ['\u{4c5}', '\0', '\0']),
+        ('\u{4c8}', ['\u{4c7}', '\0', '\0']), ('\u{4ca}', ['\u{4c9}', '\0', '\0']), ('\u{4cc}',
+        ['\u{4cb}', '\0', '\0']), ('\u{4ce}', ['\u{4cd}', '\0', '\0']), ('\u{4cf}', ['\u{4c0}',
+        '\0', '\0']), ('\u{4d1}', ['\u{4d0}', '\0', '\0']), ('\u{4d3}', ['\u{4d2}', '\0', '\0']),
+        ('\u{4d5}', ['\u{4d4}', '\0', '\0']), ('\u{4d7}', ['\u{4d6}', '\0', '\0']), ('\u{4d9}',
+        ['\u{4d8}', '\0', '\0']), ('\u{4db}', ['\u{4da}', '\0', '\0']), ('\u{4dd}', ['\u{4dc}',
+        '\0', '\0']), ('\u{4df}', ['\u{4de}', '\0', '\0']), ('\u{4e1}', ['\u{4e0}', '\0', '\0']),
+        ('\u{4e3}', ['\u{4e2}', '\0', '\0']), ('\u{4e5}', ['\u{4e4}', '\0', '\0']), ('\u{4e7}',
+        ['\u{4e6}', '\0', '\0']), ('\u{4e9}', ['\u{4e8}', '\0', '\0']), ('\u{4eb}', ['\u{4ea}',
+        '\0', '\0']), ('\u{4ed}', ['\u{4ec}', '\0', '\0']), ('\u{4ef}', ['\u{4ee}', '\0', '\0']),
+        ('\u{4f1}', ['\u{4f0}', '\0', '\0']), ('\u{4f3}', ['\u{4f2}', '\0', '\0']), ('\u{4f5}',
+        ['\u{4f4}', '\0', '\0']), ('\u{4f7}', ['\u{4f6}', '\0', '\0']), ('\u{4f9}', ['\u{4f8}',
+        '\0', '\0']), ('\u{4fb}', ['\u{4fa}', '\0', '\0']), ('\u{4fd}', ['\u{4fc}', '\0', '\0']),
+        ('\u{4ff}', ['\u{4fe}', '\0', '\0']), ('\u{501}', ['\u{500}', '\0', '\0']), ('\u{503}',
+        ['\u{502}', '\0', '\0']), ('\u{505}', ['\u{504}', '\0', '\0']), ('\u{507}', ['\u{506}',
+        '\0', '\0']), ('\u{509}', ['\u{508}', '\0', '\0']), ('\u{50b}', ['\u{50a}', '\0', '\0']),
+        ('\u{50d}', ['\u{50c}', '\0', '\0']), ('\u{50f}', ['\u{50e}', '\0', '\0']), ('\u{511}',
+        ['\u{510}', '\0', '\0']), ('\u{513}', ['\u{512}', '\0', '\0']), ('\u{515}', ['\u{514}',
+        '\0', '\0']), ('\u{517}', ['\u{516}', '\0', '\0']), ('\u{519}', ['\u{518}', '\0', '\0']),
+        ('\u{51b}', ['\u{51a}', '\0', '\0']), ('\u{51d}', ['\u{51c}', '\0', '\0']), ('\u{51f}',
+        ['\u{51e}', '\0', '\0']), ('\u{521}', ['\u{520}', '\0', '\0']), ('\u{523}', ['\u{522}',
+        '\0', '\0']), ('\u{525}', ['\u{524}', '\0', '\0']), ('\u{527}', ['\u{526}', '\0', '\0']),
+        ('\u{529}', ['\u{528}', '\0', '\0']), ('\u{52b}', ['\u{52a}', '\0', '\0']), ('\u{52d}',
+        ['\u{52c}', '\0', '\0']), ('\u{52f}', ['\u{52e}', '\0', '\0']), ('\u{561}', ['\u{531}',
+        '\0', '\0']), ('\u{562}', ['\u{532}', '\0', '\0']), ('\u{563}', ['\u{533}', '\0', '\0']),
+        ('\u{564}', ['\u{534}', '\0', '\0']), ('\u{565}', ['\u{535}', '\0', '\0']), ('\u{566}',
+        ['\u{536}', '\0', '\0']), ('\u{567}', ['\u{537}', '\0', '\0']), ('\u{568}', ['\u{538}',
+        '\0', '\0']), ('\u{569}', ['\u{539}', '\0', '\0']), ('\u{56a}', ['\u{53a}', '\0', '\0']),
+        ('\u{56b}', ['\u{53b}', '\0', '\0']), ('\u{56c}', ['\u{53c}', '\0', '\0']), ('\u{56d}',
+        ['\u{53d}', '\0', '\0']), ('\u{56e}', ['\u{53e}', '\0', '\0']), ('\u{56f}', ['\u{53f}',
+        '\0', '\0']), ('\u{570}', ['\u{540}', '\0', '\0']), ('\u{571}', ['\u{541}', '\0', '\0']),
+        ('\u{572}', ['\u{542}', '\0', '\0']), ('\u{573}', ['\u{543}', '\0', '\0']), ('\u{574}',
+        ['\u{544}', '\0', '\0']), ('\u{575}', ['\u{545}', '\0', '\0']), ('\u{576}', ['\u{546}',
+        '\0', '\0']), ('\u{577}', ['\u{547}', '\0', '\0']), ('\u{578}', ['\u{548}', '\0', '\0']),
+        ('\u{579}', ['\u{549}', '\0', '\0']), ('\u{57a}', ['\u{54a}', '\0', '\0']), ('\u{57b}',
+        ['\u{54b}', '\0', '\0']), ('\u{57c}', ['\u{54c}', '\0', '\0']), ('\u{57d}', ['\u{54d}',
+        '\0', '\0']), ('\u{57e}', ['\u{54e}', '\0', '\0']), ('\u{57f}', ['\u{54f}', '\0', '\0']),
+        ('\u{580}', ['\u{550}', '\0', '\0']), ('\u{581}', ['\u{551}', '\0', '\0']), ('\u{582}',
+        ['\u{552}', '\0', '\0']), ('\u{583}', ['\u{553}', '\0', '\0']), ('\u{584}', ['\u{554}',
+        '\0', '\0']), ('\u{585}', ['\u{555}', '\0', '\0']), ('\u{586}', ['\u{556}', '\0', '\0']),
+        ('\u{587}', ['\u{535}', '\u{552}', '\0']), ('\u{1d79}', ['\u{a77d}', '\0', '\0']),
+        ('\u{1d7d}', ['\u{2c63}', '\0', '\0']), ('\u{1e01}', ['\u{1e00}', '\0', '\0']), ('\u{1e03}',
+        ['\u{1e02}', '\0', '\0']), ('\u{1e05}', ['\u{1e04}', '\0', '\0']), ('\u{1e07}', ['\u{1e06}',
+        '\0', '\0']), ('\u{1e09}', ['\u{1e08}', '\0', '\0']), ('\u{1e0b}', ['\u{1e0a}', '\0',
+        '\0']), ('\u{1e0d}', ['\u{1e0c}', '\0', '\0']), ('\u{1e0f}', ['\u{1e0e}', '\0', '\0']),
+        ('\u{1e11}', ['\u{1e10}', '\0', '\0']), ('\u{1e13}', ['\u{1e12}', '\0', '\0']), ('\u{1e15}',
+        ['\u{1e14}', '\0', '\0']), ('\u{1e17}', ['\u{1e16}', '\0', '\0']), ('\u{1e19}', ['\u{1e18}',
+        '\0', '\0']), ('\u{1e1b}', ['\u{1e1a}', '\0', '\0']), ('\u{1e1d}', ['\u{1e1c}', '\0',
+        '\0']), ('\u{1e1f}', ['\u{1e1e}', '\0', '\0']), ('\u{1e21}', ['\u{1e20}', '\0', '\0']),
+        ('\u{1e23}', ['\u{1e22}', '\0', '\0']), ('\u{1e25}', ['\u{1e24}', '\0', '\0']), ('\u{1e27}',
+        ['\u{1e26}', '\0', '\0']), ('\u{1e29}', ['\u{1e28}', '\0', '\0']), ('\u{1e2b}', ['\u{1e2a}',
+        '\0', '\0']), ('\u{1e2d}', ['\u{1e2c}', '\0', '\0']), ('\u{1e2f}', ['\u{1e2e}', '\0',
+        '\0']), ('\u{1e31}', ['\u{1e30}', '\0', '\0']), ('\u{1e33}', ['\u{1e32}', '\0', '\0']),
+        ('\u{1e35}', ['\u{1e34}', '\0', '\0']), ('\u{1e37}', ['\u{1e36}', '\0', '\0']), ('\u{1e39}',
+        ['\u{1e38}', '\0', '\0']), ('\u{1e3b}', ['\u{1e3a}', '\0', '\0']), ('\u{1e3d}', ['\u{1e3c}',
+        '\0', '\0']), ('\u{1e3f}', ['\u{1e3e}', '\0', '\0']), ('\u{1e41}', ['\u{1e40}', '\0',
+        '\0']), ('\u{1e43}', ['\u{1e42}', '\0', '\0']), ('\u{1e45}', ['\u{1e44}', '\0', '\0']),
+        ('\u{1e47}', ['\u{1e46}', '\0', '\0']), ('\u{1e49}', ['\u{1e48}', '\0', '\0']), ('\u{1e4b}',
+        ['\u{1e4a}', '\0', '\0']), ('\u{1e4d}', ['\u{1e4c}', '\0', '\0']), ('\u{1e4f}', ['\u{1e4e}',
+        '\0', '\0']), ('\u{1e51}', ['\u{1e50}', '\0', '\0']), ('\u{1e53}', ['\u{1e52}', '\0',
+        '\0']), ('\u{1e55}', ['\u{1e54}', '\0', '\0']), ('\u{1e57}', ['\u{1e56}', '\0', '\0']),
+        ('\u{1e59}', ['\u{1e58}', '\0', '\0']), ('\u{1e5b}', ['\u{1e5a}', '\0', '\0']), ('\u{1e5d}',
+        ['\u{1e5c}', '\0', '\0']), ('\u{1e5f}', ['\u{1e5e}', '\0', '\0']), ('\u{1e61}', ['\u{1e60}',
+        '\0', '\0']), ('\u{1e63}', ['\u{1e62}', '\0', '\0']), ('\u{1e65}', ['\u{1e64}', '\0',
+        '\0']), ('\u{1e67}', ['\u{1e66}', '\0', '\0']), ('\u{1e69}', ['\u{1e68}', '\0', '\0']),
+        ('\u{1e6b}', ['\u{1e6a}', '\0', '\0']), ('\u{1e6d}', ['\u{1e6c}', '\0', '\0']), ('\u{1e6f}',
+        ['\u{1e6e}', '\0', '\0']), ('\u{1e71}', ['\u{1e70}', '\0', '\0']), ('\u{1e73}', ['\u{1e72}',
+        '\0', '\0']), ('\u{1e75}', ['\u{1e74}', '\0', '\0']), ('\u{1e77}', ['\u{1e76}', '\0',
+        '\0']), ('\u{1e79}', ['\u{1e78}', '\0', '\0']), ('\u{1e7b}', ['\u{1e7a}', '\0', '\0']),
+        ('\u{1e7d}', ['\u{1e7c}', '\0', '\0']), ('\u{1e7f}', ['\u{1e7e}', '\0', '\0']), ('\u{1e81}',
+        ['\u{1e80}', '\0', '\0']), ('\u{1e83}', ['\u{1e82}', '\0', '\0']), ('\u{1e85}', ['\u{1e84}',
+        '\0', '\0']), ('\u{1e87}', ['\u{1e86}', '\0', '\0']), ('\u{1e89}', ['\u{1e88}', '\0',
+        '\0']), ('\u{1e8b}', ['\u{1e8a}', '\0', '\0']), ('\u{1e8d}', ['\u{1e8c}', '\0', '\0']),
+        ('\u{1e8f}', ['\u{1e8e}', '\0', '\0']), ('\u{1e91}', ['\u{1e90}', '\0', '\0']), ('\u{1e93}',
+        ['\u{1e92}', '\0', '\0']), ('\u{1e95}', ['\u{1e94}', '\0', '\0']), ('\u{1e96}', ['\u{48}',
+        '\u{331}', '\0']), ('\u{1e97}', ['\u{54}', '\u{308}', '\0']), ('\u{1e98}', ['\u{57}',
+        '\u{30a}', '\0']), ('\u{1e99}', ['\u{59}', '\u{30a}', '\0']), ('\u{1e9a}', ['\u{41}',
+        '\u{2be}', '\0']), ('\u{1e9b}', ['\u{1e60}', '\0', '\0']), ('\u{1ea1}', ['\u{1ea0}', '\0',
+        '\0']), ('\u{1ea3}', ['\u{1ea2}', '\0', '\0']), ('\u{1ea5}', ['\u{1ea4}', '\0', '\0']),
+        ('\u{1ea7}', ['\u{1ea6}', '\0', '\0']), ('\u{1ea9}', ['\u{1ea8}', '\0', '\0']), ('\u{1eab}',
+        ['\u{1eaa}', '\0', '\0']), ('\u{1ead}', ['\u{1eac}', '\0', '\0']), ('\u{1eaf}', ['\u{1eae}',
+        '\0', '\0']), ('\u{1eb1}', ['\u{1eb0}', '\0', '\0']), ('\u{1eb3}', ['\u{1eb2}', '\0',
+        '\0']), ('\u{1eb5}', ['\u{1eb4}', '\0', '\0']), ('\u{1eb7}', ['\u{1eb6}', '\0', '\0']),
+        ('\u{1eb9}', ['\u{1eb8}', '\0', '\0']), ('\u{1ebb}', ['\u{1eba}', '\0', '\0']), ('\u{1ebd}',
+        ['\u{1ebc}', '\0', '\0']), ('\u{1ebf}', ['\u{1ebe}', '\0', '\0']), ('\u{1ec1}', ['\u{1ec0}',
+        '\0', '\0']), ('\u{1ec3}', ['\u{1ec2}', '\0', '\0']), ('\u{1ec5}', ['\u{1ec4}', '\0',
+        '\0']), ('\u{1ec7}', ['\u{1ec6}', '\0', '\0']), ('\u{1ec9}', ['\u{1ec8}', '\0', '\0']),
+        ('\u{1ecb}', ['\u{1eca}', '\0', '\0']), ('\u{1ecd}', ['\u{1ecc}', '\0', '\0']), ('\u{1ecf}',
+        ['\u{1ece}', '\0', '\0']), ('\u{1ed1}', ['\u{1ed0}', '\0', '\0']), ('\u{1ed3}', ['\u{1ed2}',
+        '\0', '\0']), ('\u{1ed5}', ['\u{1ed4}', '\0', '\0']), ('\u{1ed7}', ['\u{1ed6}', '\0',
+        '\0']), ('\u{1ed9}', ['\u{1ed8}', '\0', '\0']), ('\u{1edb}', ['\u{1eda}', '\0', '\0']),
+        ('\u{1edd}', ['\u{1edc}', '\0', '\0']), ('\u{1edf}', ['\u{1ede}', '\0', '\0']), ('\u{1ee1}',
+        ['\u{1ee0}', '\0', '\0']), ('\u{1ee3}', ['\u{1ee2}', '\0', '\0']), ('\u{1ee5}', ['\u{1ee4}',
+        '\0', '\0']), ('\u{1ee7}', ['\u{1ee6}', '\0', '\0']), ('\u{1ee9}', ['\u{1ee8}', '\0',
+        '\0']), ('\u{1eeb}', ['\u{1eea}', '\0', '\0']), ('\u{1eed}', ['\u{1eec}', '\0', '\0']),
+        ('\u{1eef}', ['\u{1eee}', '\0', '\0']), ('\u{1ef1}', ['\u{1ef0}', '\0', '\0']), ('\u{1ef3}',
+        ['\u{1ef2}', '\0', '\0']), ('\u{1ef5}', ['\u{1ef4}', '\0', '\0']), ('\u{1ef7}', ['\u{1ef6}',
+        '\0', '\0']), ('\u{1ef9}', ['\u{1ef8}', '\0', '\0']), ('\u{1efb}', ['\u{1efa}', '\0',
+        '\0']), ('\u{1efd}', ['\u{1efc}', '\0', '\0']), ('\u{1eff}', ['\u{1efe}', '\0', '\0']),
+        ('\u{1f00}', ['\u{1f08}', '\0', '\0']), ('\u{1f01}', ['\u{1f09}', '\0', '\0']), ('\u{1f02}',
+        ['\u{1f0a}', '\0', '\0']), ('\u{1f03}', ['\u{1f0b}', '\0', '\0']), ('\u{1f04}', ['\u{1f0c}',
+        '\0', '\0']), ('\u{1f05}', ['\u{1f0d}', '\0', '\0']), ('\u{1f06}', ['\u{1f0e}', '\0',
+        '\0']), ('\u{1f07}', ['\u{1f0f}', '\0', '\0']), ('\u{1f10}', ['\u{1f18}', '\0', '\0']),
+        ('\u{1f11}', ['\u{1f19}', '\0', '\0']), ('\u{1f12}', ['\u{1f1a}', '\0', '\0']), ('\u{1f13}',
+        ['\u{1f1b}', '\0', '\0']), ('\u{1f14}', ['\u{1f1c}', '\0', '\0']), ('\u{1f15}', ['\u{1f1d}',
+        '\0', '\0']), ('\u{1f20}', ['\u{1f28}', '\0', '\0']), ('\u{1f21}', ['\u{1f29}', '\0',
+        '\0']), ('\u{1f22}', ['\u{1f2a}', '\0', '\0']), ('\u{1f23}', ['\u{1f2b}', '\0', '\0']),
+        ('\u{1f24}', ['\u{1f2c}', '\0', '\0']), ('\u{1f25}', ['\u{1f2d}', '\0', '\0']), ('\u{1f26}',
+        ['\u{1f2e}', '\0', '\0']), ('\u{1f27}', ['\u{1f2f}', '\0', '\0']), ('\u{1f30}', ['\u{1f38}',
+        '\0', '\0']), ('\u{1f31}', ['\u{1f39}', '\0', '\0']), ('\u{1f32}', ['\u{1f3a}', '\0',
+        '\0']), ('\u{1f33}', ['\u{1f3b}', '\0', '\0']), ('\u{1f34}', ['\u{1f3c}', '\0', '\0']),
+        ('\u{1f35}', ['\u{1f3d}', '\0', '\0']), ('\u{1f36}', ['\u{1f3e}', '\0', '\0']), ('\u{1f37}',
+        ['\u{1f3f}', '\0', '\0']), ('\u{1f40}', ['\u{1f48}', '\0', '\0']), ('\u{1f41}', ['\u{1f49}',
+        '\0', '\0']), ('\u{1f42}', ['\u{1f4a}', '\0', '\0']), ('\u{1f43}', ['\u{1f4b}', '\0',
+        '\0']), ('\u{1f44}', ['\u{1f4c}', '\0', '\0']), ('\u{1f45}', ['\u{1f4d}', '\0', '\0']),
+        ('\u{1f50}', ['\u{3a5}', '\u{313}', '\0']), ('\u{1f51}', ['\u{1f59}', '\0', '\0']),
+        ('\u{1f52}', ['\u{3a5}', '\u{313}', '\u{300}']), ('\u{1f53}', ['\u{1f5b}', '\0', '\0']),
+        ('\u{1f54}', ['\u{3a5}', '\u{313}', '\u{301}']), ('\u{1f55}', ['\u{1f5d}', '\0', '\0']),
+        ('\u{1f56}', ['\u{3a5}', '\u{313}', '\u{342}']), ('\u{1f57}', ['\u{1f5f}', '\0', '\0']),
+        ('\u{1f60}', ['\u{1f68}', '\0', '\0']), ('\u{1f61}', ['\u{1f69}', '\0', '\0']), ('\u{1f62}',
+        ['\u{1f6a}', '\0', '\0']), ('\u{1f63}', ['\u{1f6b}', '\0', '\0']), ('\u{1f64}', ['\u{1f6c}',
+        '\0', '\0']), ('\u{1f65}', ['\u{1f6d}', '\0', '\0']), ('\u{1f66}', ['\u{1f6e}', '\0',
+        '\0']), ('\u{1f67}', ['\u{1f6f}', '\0', '\0']), ('\u{1f70}', ['\u{1fba}', '\0', '\0']),
+        ('\u{1f71}', ['\u{1fbb}', '\0', '\0']), ('\u{1f72}', ['\u{1fc8}', '\0', '\0']), ('\u{1f73}',
+        ['\u{1fc9}', '\0', '\0']), ('\u{1f74}', ['\u{1fca}', '\0', '\0']), ('\u{1f75}', ['\u{1fcb}',
+        '\0', '\0']), ('\u{1f76}', ['\u{1fda}', '\0', '\0']), ('\u{1f77}', ['\u{1fdb}', '\0',
+        '\0']), ('\u{1f78}', ['\u{1ff8}', '\0', '\0']), ('\u{1f79}', ['\u{1ff9}', '\0', '\0']),
+        ('\u{1f7a}', ['\u{1fea}', '\0', '\0']), ('\u{1f7b}', ['\u{1feb}', '\0', '\0']), ('\u{1f7c}',
+        ['\u{1ffa}', '\0', '\0']), ('\u{1f7d}', ['\u{1ffb}', '\0', '\0']), ('\u{1f80}', ['\u{1f08}',
+        '\u{399}', '\0']), ('\u{1f81}', ['\u{1f09}', '\u{399}', '\0']), ('\u{1f82}', ['\u{1f0a}',
+        '\u{399}', '\0']), ('\u{1f83}', ['\u{1f0b}', '\u{399}', '\0']), ('\u{1f84}', ['\u{1f0c}',
+        '\u{399}', '\0']), ('\u{1f85}', ['\u{1f0d}', '\u{399}', '\0']), ('\u{1f86}', ['\u{1f0e}',
+        '\u{399}', '\0']), ('\u{1f87}', ['\u{1f0f}', '\u{399}', '\0']), ('\u{1f88}', ['\u{1f08}',
+        '\u{399}', '\0']), ('\u{1f89}', ['\u{1f09}', '\u{399}', '\0']), ('\u{1f8a}', ['\u{1f0a}',
+        '\u{399}', '\0']), ('\u{1f8b}', ['\u{1f0b}', '\u{399}', '\0']), ('\u{1f8c}', ['\u{1f0c}',
+        '\u{399}', '\0']), ('\u{1f8d}', ['\u{1f0d}', '\u{399}', '\0']), ('\u{1f8e}', ['\u{1f0e}',
+        '\u{399}', '\0']), ('\u{1f8f}', ['\u{1f0f}', '\u{399}', '\0']), ('\u{1f90}', ['\u{1f28}',
+        '\u{399}', '\0']), ('\u{1f91}', ['\u{1f29}', '\u{399}', '\0']), ('\u{1f92}', ['\u{1f2a}',
+        '\u{399}', '\0']), ('\u{1f93}', ['\u{1f2b}', '\u{399}', '\0']), ('\u{1f94}', ['\u{1f2c}',
+        '\u{399}', '\0']), ('\u{1f95}', ['\u{1f2d}', '\u{399}', '\0']), ('\u{1f96}', ['\u{1f2e}',
+        '\u{399}', '\0']), ('\u{1f97}', ['\u{1f2f}', '\u{399}', '\0']), ('\u{1f98}', ['\u{1f28}',
+        '\u{399}', '\0']), ('\u{1f99}', ['\u{1f29}', '\u{399}', '\0']), ('\u{1f9a}', ['\u{1f2a}',
+        '\u{399}', '\0']), ('\u{1f9b}', ['\u{1f2b}', '\u{399}', '\0']), ('\u{1f9c}', ['\u{1f2c}',
+        '\u{399}', '\0']), ('\u{1f9d}', ['\u{1f2d}', '\u{399}', '\0']), ('\u{1f9e}', ['\u{1f2e}',
+        '\u{399}', '\0']), ('\u{1f9f}', ['\u{1f2f}', '\u{399}', '\0']), ('\u{1fa0}', ['\u{1f68}',
+        '\u{399}', '\0']), ('\u{1fa1}', ['\u{1f69}', '\u{399}', '\0']), ('\u{1fa2}', ['\u{1f6a}',
+        '\u{399}', '\0']), ('\u{1fa3}', ['\u{1f6b}', '\u{399}', '\0']), ('\u{1fa4}', ['\u{1f6c}',
+        '\u{399}', '\0']), ('\u{1fa5}', ['\u{1f6d}', '\u{399}', '\0']), ('\u{1fa6}', ['\u{1f6e}',
+        '\u{399}', '\0']), ('\u{1fa7}', ['\u{1f6f}', '\u{399}', '\0']), ('\u{1fa8}', ['\u{1f68}',
+        '\u{399}', '\0']), ('\u{1fa9}', ['\u{1f69}', '\u{399}', '\0']), ('\u{1faa}', ['\u{1f6a}',
+        '\u{399}', '\0']), ('\u{1fab}', ['\u{1f6b}', '\u{399}', '\0']), ('\u{1fac}', ['\u{1f6c}',
+        '\u{399}', '\0']), ('\u{1fad}', ['\u{1f6d}', '\u{399}', '\0']), ('\u{1fae}', ['\u{1f6e}',
+        '\u{399}', '\0']), ('\u{1faf}', ['\u{1f6f}', '\u{399}', '\0']), ('\u{1fb0}', ['\u{1fb8}',
+        '\0', '\0']), ('\u{1fb1}', ['\u{1fb9}', '\0', '\0']), ('\u{1fb2}', ['\u{1fba}', '\u{399}',
+        '\0']), ('\u{1fb3}', ['\u{391}', '\u{399}', '\0']), ('\u{1fb4}', ['\u{386}', '\u{399}',
+        '\0']), ('\u{1fb6}', ['\u{391}', '\u{342}', '\0']), ('\u{1fb7}', ['\u{391}', '\u{342}',
+        '\u{399}']), ('\u{1fbc}', ['\u{391}', '\u{399}', '\0']), ('\u{1fbe}', ['\u{399}', '\0',
+        '\0']), ('\u{1fc2}', ['\u{1fca}', '\u{399}', '\0']), ('\u{1fc3}', ['\u{397}', '\u{399}',
+        '\0']), ('\u{1fc4}', ['\u{389}', '\u{399}', '\0']), ('\u{1fc6}', ['\u{397}', '\u{342}',
+        '\0']), ('\u{1fc7}', ['\u{397}', '\u{342}', '\u{399}']), ('\u{1fcc}', ['\u{397}', '\u{399}',
+        '\0']), ('\u{1fd0}', ['\u{1fd8}', '\0', '\0']), ('\u{1fd1}', ['\u{1fd9}', '\0', '\0']),
+        ('\u{1fd2}', ['\u{399}', '\u{308}', '\u{300}']), ('\u{1fd3}', ['\u{399}', '\u{308}',
+        '\u{301}']), ('\u{1fd6}', ['\u{399}', '\u{342}', '\0']), ('\u{1fd7}', ['\u{399}', '\u{308}',
+        '\u{342}']), ('\u{1fe0}', ['\u{1fe8}', '\0', '\0']), ('\u{1fe1}', ['\u{1fe9}', '\0', '\0']),
+        ('\u{1fe2}', ['\u{3a5}', '\u{308}', '\u{300}']), ('\u{1fe3}', ['\u{3a5}', '\u{308}',
+        '\u{301}']), ('\u{1fe4}', ['\u{3a1}', '\u{313}', '\0']), ('\u{1fe5}', ['\u{1fec}', '\0',
+        '\0']), ('\u{1fe6}', ['\u{3a5}', '\u{342}', '\0']), ('\u{1fe7}', ['\u{3a5}', '\u{308}',
+        '\u{342}']), ('\u{1ff2}', ['\u{1ffa}', '\u{399}', '\0']), ('\u{1ff3}', ['\u{3a9}',
+        '\u{399}', '\0']), ('\u{1ff4}', ['\u{38f}', '\u{399}', '\0']), ('\u{1ff6}', ['\u{3a9}',
+        '\u{342}', '\0']), ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{399}']), ('\u{1ffc}', ['\u{3a9}',
+        '\u{399}', '\0']), ('\u{214e}', ['\u{2132}', '\0', '\0']), ('\u{2170}', ['\u{2160}', '\0',
+        '\0']), ('\u{2171}', ['\u{2161}', '\0', '\0']), ('\u{2172}', ['\u{2162}', '\0', '\0']),
+        ('\u{2173}', ['\u{2163}', '\0', '\0']), ('\u{2174}', ['\u{2164}', '\0', '\0']), ('\u{2175}',
+        ['\u{2165}', '\0', '\0']), ('\u{2176}', ['\u{2166}', '\0', '\0']), ('\u{2177}', ['\u{2167}',
+        '\0', '\0']), ('\u{2178}', ['\u{2168}', '\0', '\0']), ('\u{2179}', ['\u{2169}', '\0',
+        '\0']), ('\u{217a}', ['\u{216a}', '\0', '\0']), ('\u{217b}', ['\u{216b}', '\0', '\0']),
+        ('\u{217c}', ['\u{216c}', '\0', '\0']), ('\u{217d}', ['\u{216d}', '\0', '\0']), ('\u{217e}',
+        ['\u{216e}', '\0', '\0']), ('\u{217f}', ['\u{216f}', '\0', '\0']), ('\u{2184}', ['\u{2183}',
+        '\0', '\0']), ('\u{24d0}', ['\u{24b6}', '\0', '\0']), ('\u{24d1}', ['\u{24b7}', '\0',
+        '\0']), ('\u{24d2}', ['\u{24b8}', '\0', '\0']), ('\u{24d3}', ['\u{24b9}', '\0', '\0']),
+        ('\u{24d4}', ['\u{24ba}', '\0', '\0']), ('\u{24d5}', ['\u{24bb}', '\0', '\0']), ('\u{24d6}',
+        ['\u{24bc}', '\0', '\0']), ('\u{24d7}', ['\u{24bd}', '\0', '\0']), ('\u{24d8}', ['\u{24be}',
+        '\0', '\0']), ('\u{24d9}', ['\u{24bf}', '\0', '\0']), ('\u{24da}', ['\u{24c0}', '\0',
+        '\0']), ('\u{24db}', ['\u{24c1}', '\0', '\0']), ('\u{24dc}', ['\u{24c2}', '\0', '\0']),
+        ('\u{24dd}', ['\u{24c3}', '\0', '\0']), ('\u{24de}', ['\u{24c4}', '\0', '\0']), ('\u{24df}',
+        ['\u{24c5}', '\0', '\0']), ('\u{24e0}', ['\u{24c6}', '\0', '\0']), ('\u{24e1}', ['\u{24c7}',
+        '\0', '\0']), ('\u{24e2}', ['\u{24c8}', '\0', '\0']), ('\u{24e3}', ['\u{24c9}', '\0',
+        '\0']), ('\u{24e4}', ['\u{24ca}', '\0', '\0']), ('\u{24e5}', ['\u{24cb}', '\0', '\0']),
+        ('\u{24e6}', ['\u{24cc}', '\0', '\0']), ('\u{24e7}', ['\u{24cd}', '\0', '\0']), ('\u{24e8}',
+        ['\u{24ce}', '\0', '\0']), ('\u{24e9}', ['\u{24cf}', '\0', '\0']), ('\u{2c30}', ['\u{2c00}',
+        '\0', '\0']), ('\u{2c31}', ['\u{2c01}', '\0', '\0']), ('\u{2c32}', ['\u{2c02}', '\0',
+        '\0']), ('\u{2c33}', ['\u{2c03}', '\0', '\0']), ('\u{2c34}', ['\u{2c04}', '\0', '\0']),
+        ('\u{2c35}', ['\u{2c05}', '\0', '\0']), ('\u{2c36}', ['\u{2c06}', '\0', '\0']), ('\u{2c37}',
+        ['\u{2c07}', '\0', '\0']), ('\u{2c38}', ['\u{2c08}', '\0', '\0']), ('\u{2c39}', ['\u{2c09}',
+        '\0', '\0']), ('\u{2c3a}', ['\u{2c0a}', '\0', '\0']), ('\u{2c3b}', ['\u{2c0b}', '\0',
+        '\0']), ('\u{2c3c}', ['\u{2c0c}', '\0', '\0']), ('\u{2c3d}', ['\u{2c0d}', '\0', '\0']),
+        ('\u{2c3e}', ['\u{2c0e}', '\0', '\0']), ('\u{2c3f}', ['\u{2c0f}', '\0', '\0']), ('\u{2c40}',
+        ['\u{2c10}', '\0', '\0']), ('\u{2c41}', ['\u{2c11}', '\0', '\0']), ('\u{2c42}', ['\u{2c12}',
+        '\0', '\0']), ('\u{2c43}', ['\u{2c13}', '\0', '\0']), ('\u{2c44}', ['\u{2c14}', '\0',
+        '\0']), ('\u{2c45}', ['\u{2c15}', '\0', '\0']), ('\u{2c46}', ['\u{2c16}', '\0', '\0']),
+        ('\u{2c47}', ['\u{2c17}', '\0', '\0']), ('\u{2c48}', ['\u{2c18}', '\0', '\0']), ('\u{2c49}',
+        ['\u{2c19}', '\0', '\0']), ('\u{2c4a}', ['\u{2c1a}', '\0', '\0']), ('\u{2c4b}', ['\u{2c1b}',
+        '\0', '\0']), ('\u{2c4c}', ['\u{2c1c}', '\0', '\0']), ('\u{2c4d}', ['\u{2c1d}', '\0',
+        '\0']), ('\u{2c4e}', ['\u{2c1e}', '\0', '\0']), ('\u{2c4f}', ['\u{2c1f}', '\0', '\0']),
+        ('\u{2c50}', ['\u{2c20}', '\0', '\0']), ('\u{2c51}', ['\u{2c21}', '\0', '\0']), ('\u{2c52}',
+        ['\u{2c22}', '\0', '\0']), ('\u{2c53}', ['\u{2c23}', '\0', '\0']), ('\u{2c54}', ['\u{2c24}',
+        '\0', '\0']), ('\u{2c55}', ['\u{2c25}', '\0', '\0']), ('\u{2c56}', ['\u{2c26}', '\0',
+        '\0']), ('\u{2c57}', ['\u{2c27}', '\0', '\0']), ('\u{2c58}', ['\u{2c28}', '\0', '\0']),
+        ('\u{2c59}', ['\u{2c29}', '\0', '\0']), ('\u{2c5a}', ['\u{2c2a}', '\0', '\0']), ('\u{2c5b}',
+        ['\u{2c2b}', '\0', '\0']), ('\u{2c5c}', ['\u{2c2c}', '\0', '\0']), ('\u{2c5d}', ['\u{2c2d}',
+        '\0', '\0']), ('\u{2c5e}', ['\u{2c2e}', '\0', '\0']), ('\u{2c61}', ['\u{2c60}', '\0',
+        '\0']), ('\u{2c65}', ['\u{23a}', '\0', '\0']), ('\u{2c66}', ['\u{23e}', '\0', '\0']),
+        ('\u{2c68}', ['\u{2c67}', '\0', '\0']), ('\u{2c6a}', ['\u{2c69}', '\0', '\0']), ('\u{2c6c}',
+        ['\u{2c6b}', '\0', '\0']), ('\u{2c73}', ['\u{2c72}', '\0', '\0']), ('\u{2c76}', ['\u{2c75}',
+        '\0', '\0']), ('\u{2c81}', ['\u{2c80}', '\0', '\0']), ('\u{2c83}', ['\u{2c82}', '\0',
+        '\0']), ('\u{2c85}', ['\u{2c84}', '\0', '\0']), ('\u{2c87}', ['\u{2c86}', '\0', '\0']),
+        ('\u{2c89}', ['\u{2c88}', '\0', '\0']), ('\u{2c8b}', ['\u{2c8a}', '\0', '\0']), ('\u{2c8d}',
+        ['\u{2c8c}', '\0', '\0']), ('\u{2c8f}', ['\u{2c8e}', '\0', '\0']), ('\u{2c91}', ['\u{2c90}',
+        '\0', '\0']), ('\u{2c93}', ['\u{2c92}', '\0', '\0']), ('\u{2c95}', ['\u{2c94}', '\0',
+        '\0']), ('\u{2c97}', ['\u{2c96}', '\0', '\0']), ('\u{2c99}', ['\u{2c98}', '\0', '\0']),
+        ('\u{2c9b}', ['\u{2c9a}', '\0', '\0']), ('\u{2c9d}', ['\u{2c9c}', '\0', '\0']), ('\u{2c9f}',
+        ['\u{2c9e}', '\0', '\0']), ('\u{2ca1}', ['\u{2ca0}', '\0', '\0']), ('\u{2ca3}', ['\u{2ca2}',
+        '\0', '\0']), ('\u{2ca5}', ['\u{2ca4}', '\0', '\0']), ('\u{2ca7}', ['\u{2ca6}', '\0',
+        '\0']), ('\u{2ca9}', ['\u{2ca8}', '\0', '\0']), ('\u{2cab}', ['\u{2caa}', '\0', '\0']),
+        ('\u{2cad}', ['\u{2cac}', '\0', '\0']), ('\u{2caf}', ['\u{2cae}', '\0', '\0']), ('\u{2cb1}',
+        ['\u{2cb0}', '\0', '\0']), ('\u{2cb3}', ['\u{2cb2}', '\0', '\0']), ('\u{2cb5}', ['\u{2cb4}',
+        '\0', '\0']), ('\u{2cb7}', ['\u{2cb6}', '\0', '\0']), ('\u{2cb9}', ['\u{2cb8}', '\0',
+        '\0']), ('\u{2cbb}', ['\u{2cba}', '\0', '\0']), ('\u{2cbd}', ['\u{2cbc}', '\0', '\0']),
+        ('\u{2cbf}', ['\u{2cbe}', '\0', '\0']), ('\u{2cc1}', ['\u{2cc0}', '\0', '\0']), ('\u{2cc3}',
+        ['\u{2cc2}', '\0', '\0']), ('\u{2cc5}', ['\u{2cc4}', '\0', '\0']), ('\u{2cc7}', ['\u{2cc6}',
+        '\0', '\0']), ('\u{2cc9}', ['\u{2cc8}', '\0', '\0']), ('\u{2ccb}', ['\u{2cca}', '\0',
+        '\0']), ('\u{2ccd}', ['\u{2ccc}', '\0', '\0']), ('\u{2ccf}', ['\u{2cce}', '\0', '\0']),
+        ('\u{2cd1}', ['\u{2cd0}', '\0', '\0']), ('\u{2cd3}', ['\u{2cd2}', '\0', '\0']), ('\u{2cd5}',
+        ['\u{2cd4}', '\0', '\0']), ('\u{2cd7}', ['\u{2cd6}', '\0', '\0']), ('\u{2cd9}', ['\u{2cd8}',
+        '\0', '\0']), ('\u{2cdb}', ['\u{2cda}', '\0', '\0']), ('\u{2cdd}', ['\u{2cdc}', '\0',
+        '\0']), ('\u{2cdf}', ['\u{2cde}', '\0', '\0']), ('\u{2ce1}', ['\u{2ce0}', '\0', '\0']),
+        ('\u{2ce3}', ['\u{2ce2}', '\0', '\0']), ('\u{2cec}', ['\u{2ceb}', '\0', '\0']), ('\u{2cee}',
+        ['\u{2ced}', '\0', '\0']), ('\u{2cf3}', ['\u{2cf2}', '\0', '\0']), ('\u{2d00}', ['\u{10a0}',
+        '\0', '\0']), ('\u{2d01}', ['\u{10a1}', '\0', '\0']), ('\u{2d02}', ['\u{10a2}', '\0',
+        '\0']), ('\u{2d03}', ['\u{10a3}', '\0', '\0']), ('\u{2d04}', ['\u{10a4}', '\0', '\0']),
+        ('\u{2d05}', ['\u{10a5}', '\0', '\0']), ('\u{2d06}', ['\u{10a6}', '\0', '\0']), ('\u{2d07}',
+        ['\u{10a7}', '\0', '\0']), ('\u{2d08}', ['\u{10a8}', '\0', '\0']), ('\u{2d09}', ['\u{10a9}',
+        '\0', '\0']), ('\u{2d0a}', ['\u{10aa}', '\0', '\0']), ('\u{2d0b}', ['\u{10ab}', '\0',
+        '\0']), ('\u{2d0c}', ['\u{10ac}', '\0', '\0']), ('\u{2d0d}', ['\u{10ad}', '\0', '\0']),
+        ('\u{2d0e}', ['\u{10ae}', '\0', '\0']), ('\u{2d0f}', ['\u{10af}', '\0', '\0']), ('\u{2d10}',
+        ['\u{10b0}', '\0', '\0']), ('\u{2d11}', ['\u{10b1}', '\0', '\0']), ('\u{2d12}', ['\u{10b2}',
+        '\0', '\0']), ('\u{2d13}', ['\u{10b3}', '\0', '\0']), ('\u{2d14}', ['\u{10b4}', '\0',
+        '\0']), ('\u{2d15}', ['\u{10b5}', '\0', '\0']), ('\u{2d16}', ['\u{10b6}', '\0', '\0']),
+        ('\u{2d17}', ['\u{10b7}', '\0', '\0']), ('\u{2d18}', ['\u{10b8}', '\0', '\0']), ('\u{2d19}',
+        ['\u{10b9}', '\0', '\0']), ('\u{2d1a}', ['\u{10ba}', '\0', '\0']), ('\u{2d1b}', ['\u{10bb}',
+        '\0', '\0']), ('\u{2d1c}', ['\u{10bc}', '\0', '\0']), ('\u{2d1d}', ['\u{10bd}', '\0',
+        '\0']), ('\u{2d1e}', ['\u{10be}', '\0', '\0']), ('\u{2d1f}', ['\u{10bf}', '\0', '\0']),
+        ('\u{2d20}', ['\u{10c0}', '\0', '\0']), ('\u{2d21}', ['\u{10c1}', '\0', '\0']), ('\u{2d22}',
+        ['\u{10c2}', '\0', '\0']), ('\u{2d23}', ['\u{10c3}', '\0', '\0']), ('\u{2d24}', ['\u{10c4}',
+        '\0', '\0']), ('\u{2d25}', ['\u{10c5}', '\0', '\0']), ('\u{2d27}', ['\u{10c7}', '\0',
+        '\0']), ('\u{2d2d}', ['\u{10cd}', '\0', '\0']), ('\u{a641}', ['\u{a640}', '\0', '\0']),
+        ('\u{a643}', ['\u{a642}', '\0', '\0']), ('\u{a645}', ['\u{a644}', '\0', '\0']), ('\u{a647}',
+        ['\u{a646}', '\0', '\0']), ('\u{a649}', ['\u{a648}', '\0', '\0']), ('\u{a64b}', ['\u{a64a}',
+        '\0', '\0']), ('\u{a64d}', ['\u{a64c}', '\0', '\0']), ('\u{a64f}', ['\u{a64e}', '\0',
+        '\0']), ('\u{a651}', ['\u{a650}', '\0', '\0']), ('\u{a653}', ['\u{a652}', '\0', '\0']),
+        ('\u{a655}', ['\u{a654}', '\0', '\0']), ('\u{a657}', ['\u{a656}', '\0', '\0']), ('\u{a659}',
+        ['\u{a658}', '\0', '\0']), ('\u{a65b}', ['\u{a65a}', '\0', '\0']), ('\u{a65d}', ['\u{a65c}',
+        '\0', '\0']), ('\u{a65f}', ['\u{a65e}', '\0', '\0']), ('\u{a661}', ['\u{a660}', '\0',
+        '\0']), ('\u{a663}', ['\u{a662}', '\0', '\0']), ('\u{a665}', ['\u{a664}', '\0', '\0']),
+        ('\u{a667}', ['\u{a666}', '\0', '\0']), ('\u{a669}', ['\u{a668}', '\0', '\0']), ('\u{a66b}',
+        ['\u{a66a}', '\0', '\0']), ('\u{a66d}', ['\u{a66c}', '\0', '\0']), ('\u{a681}', ['\u{a680}',
+        '\0', '\0']), ('\u{a683}', ['\u{a682}', '\0', '\0']), ('\u{a685}', ['\u{a684}', '\0',
+        '\0']), ('\u{a687}', ['\u{a686}', '\0', '\0']), ('\u{a689}', ['\u{a688}', '\0', '\0']),
+        ('\u{a68b}', ['\u{a68a}', '\0', '\0']), ('\u{a68d}', ['\u{a68c}', '\0', '\0']), ('\u{a68f}',
+        ['\u{a68e}', '\0', '\0']), ('\u{a691}', ['\u{a690}', '\0', '\0']), ('\u{a693}', ['\u{a692}',
+        '\0', '\0']), ('\u{a695}', ['\u{a694}', '\0', '\0']), ('\u{a697}', ['\u{a696}', '\0',
+        '\0']), ('\u{a699}', ['\u{a698}', '\0', '\0']), ('\u{a69b}', ['\u{a69a}', '\0', '\0']),
+        ('\u{a723}', ['\u{a722}', '\0', '\0']), ('\u{a725}', ['\u{a724}', '\0', '\0']), ('\u{a727}',
+        ['\u{a726}', '\0', '\0']), ('\u{a729}', ['\u{a728}', '\0', '\0']), ('\u{a72b}', ['\u{a72a}',
+        '\0', '\0']), ('\u{a72d}', ['\u{a72c}', '\0', '\0']), ('\u{a72f}', ['\u{a72e}', '\0',
+        '\0']), ('\u{a733}', ['\u{a732}', '\0', '\0']), ('\u{a735}', ['\u{a734}', '\0', '\0']),
+        ('\u{a737}', ['\u{a736}', '\0', '\0']), ('\u{a739}', ['\u{a738}', '\0', '\0']), ('\u{a73b}',
+        ['\u{a73a}', '\0', '\0']), ('\u{a73d}', ['\u{a73c}', '\0', '\0']), ('\u{a73f}', ['\u{a73e}',
+        '\0', '\0']), ('\u{a741}', ['\u{a740}', '\0', '\0']), ('\u{a743}', ['\u{a742}', '\0',
+        '\0']), ('\u{a745}', ['\u{a744}', '\0', '\0']), ('\u{a747}', ['\u{a746}', '\0', '\0']),
+        ('\u{a749}', ['\u{a748}', '\0', '\0']), ('\u{a74b}', ['\u{a74a}', '\0', '\0']), ('\u{a74d}',
+        ['\u{a74c}', '\0', '\0']), ('\u{a74f}', ['\u{a74e}', '\0', '\0']), ('\u{a751}', ['\u{a750}',
+        '\0', '\0']), ('\u{a753}', ['\u{a752}', '\0', '\0']), ('\u{a755}', ['\u{a754}', '\0',
+        '\0']), ('\u{a757}', ['\u{a756}', '\0', '\0']), ('\u{a759}', ['\u{a758}', '\0', '\0']),
+        ('\u{a75b}', ['\u{a75a}', '\0', '\0']), ('\u{a75d}', ['\u{a75c}', '\0', '\0']), ('\u{a75f}',
+        ['\u{a75e}', '\0', '\0']), ('\u{a761}', ['\u{a760}', '\0', '\0']), ('\u{a763}', ['\u{a762}',
+        '\0', '\0']), ('\u{a765}', ['\u{a764}', '\0', '\0']), ('\u{a767}', ['\u{a766}', '\0',
+        '\0']), ('\u{a769}', ['\u{a768}', '\0', '\0']), ('\u{a76b}', ['\u{a76a}', '\0', '\0']),
+        ('\u{a76d}', ['\u{a76c}', '\0', '\0']), ('\u{a76f}', ['\u{a76e}', '\0', '\0']), ('\u{a77a}',
+        ['\u{a779}', '\0', '\0']), ('\u{a77c}', ['\u{a77b}', '\0', '\0']), ('\u{a77f}', ['\u{a77e}',
+        '\0', '\0']), ('\u{a781}', ['\u{a780}', '\0', '\0']), ('\u{a783}', ['\u{a782}', '\0',
+        '\0']), ('\u{a785}', ['\u{a784}', '\0', '\0']), ('\u{a787}', ['\u{a786}', '\0', '\0']),
+        ('\u{a78c}', ['\u{a78b}', '\0', '\0']), ('\u{a791}', ['\u{a790}', '\0', '\0']), ('\u{a793}',
+        ['\u{a792}', '\0', '\0']), ('\u{a797}', ['\u{a796}', '\0', '\0']), ('\u{a799}', ['\u{a798}',
+        '\0', '\0']), ('\u{a79b}', ['\u{a79a}', '\0', '\0']), ('\u{a79d}', ['\u{a79c}', '\0',
+        '\0']), ('\u{a79f}', ['\u{a79e}', '\0', '\0']), ('\u{a7a1}', ['\u{a7a0}', '\0', '\0']),
+        ('\u{a7a3}', ['\u{a7a2}', '\0', '\0']), ('\u{a7a5}', ['\u{a7a4}', '\0', '\0']), ('\u{a7a7}',
+        ['\u{a7a6}', '\0', '\0']), ('\u{a7a9}', ['\u{a7a8}', '\0', '\0']), ('\u{fb00}', ['\u{46}',
+        '\u{46}', '\0']), ('\u{fb01}', ['\u{46}', '\u{49}', '\0']), ('\u{fb02}', ['\u{46}',
+        '\u{4c}', '\0']), ('\u{fb03}', ['\u{46}', '\u{46}', '\u{49}']), ('\u{fb04}', ['\u{46}',
+        '\u{46}', '\u{4c}']), ('\u{fb05}', ['\u{53}', '\u{54}', '\0']), ('\u{fb06}', ['\u{53}',
+        '\u{54}', '\0']), ('\u{fb13}', ['\u{544}', '\u{546}', '\0']), ('\u{fb14}', ['\u{544}',
+        '\u{535}', '\0']), ('\u{fb15}', ['\u{544}', '\u{53b}', '\0']), ('\u{fb16}', ['\u{54e}',
+        '\u{546}', '\0']), ('\u{fb17}', ['\u{544}', '\u{53d}', '\0']), ('\u{ff41}', ['\u{ff21}',
+        '\0', '\0']), ('\u{ff42}', ['\u{ff22}', '\0', '\0']), ('\u{ff43}', ['\u{ff23}', '\0',
+        '\0']), ('\u{ff44}', ['\u{ff24}', '\0', '\0']), ('\u{ff45}', ['\u{ff25}', '\0', '\0']),
+        ('\u{ff46}', ['\u{ff26}', '\0', '\0']), ('\u{ff47}', ['\u{ff27}', '\0', '\0']), ('\u{ff48}',
+        ['\u{ff28}', '\0', '\0']), ('\u{ff49}', ['\u{ff29}', '\0', '\0']), ('\u{ff4a}', ['\u{ff2a}',
+        '\0', '\0']), ('\u{ff4b}', ['\u{ff2b}', '\0', '\0']), ('\u{ff4c}', ['\u{ff2c}', '\0',
+        '\0']), ('\u{ff4d}', ['\u{ff2d}', '\0', '\0']), ('\u{ff4e}', ['\u{ff2e}', '\0', '\0']),
+        ('\u{ff4f}', ['\u{ff2f}', '\0', '\0']), ('\u{ff50}', ['\u{ff30}', '\0', '\0']), ('\u{ff51}',
+        ['\u{ff31}', '\0', '\0']), ('\u{ff52}', ['\u{ff32}', '\0', '\0']), ('\u{ff53}', ['\u{ff33}',
+        '\0', '\0']), ('\u{ff54}', ['\u{ff34}', '\0', '\0']), ('\u{ff55}', ['\u{ff35}', '\0',
+        '\0']), ('\u{ff56}', ['\u{ff36}', '\0', '\0']), ('\u{ff57}', ['\u{ff37}', '\0', '\0']),
+        ('\u{ff58}', ['\u{ff38}', '\0', '\0']), ('\u{ff59}', ['\u{ff39}', '\0', '\0']), ('\u{ff5a}',
+        ['\u{ff3a}', '\0', '\0']), ('\u{10428}', ['\u{10400}', '\0', '\0']), ('\u{10429}',
+        ['\u{10401}', '\0', '\0']), ('\u{1042a}', ['\u{10402}', '\0', '\0']), ('\u{1042b}',
+        ['\u{10403}', '\0', '\0']), ('\u{1042c}', ['\u{10404}', '\0', '\0']), ('\u{1042d}',
+        ['\u{10405}', '\0', '\0']), ('\u{1042e}', ['\u{10406}', '\0', '\0']), ('\u{1042f}',
+        ['\u{10407}', '\0', '\0']), ('\u{10430}', ['\u{10408}', '\0', '\0']), ('\u{10431}',
+        ['\u{10409}', '\0', '\0']), ('\u{10432}', ['\u{1040a}', '\0', '\0']), ('\u{10433}',
+        ['\u{1040b}', '\0', '\0']), ('\u{10434}', ['\u{1040c}', '\0', '\0']), ('\u{10435}',
+        ['\u{1040d}', '\0', '\0']), ('\u{10436}', ['\u{1040e}', '\0', '\0']), ('\u{10437}',
+        ['\u{1040f}', '\0', '\0']), ('\u{10438}', ['\u{10410}', '\0', '\0']), ('\u{10439}',
+        ['\u{10411}', '\0', '\0']), ('\u{1043a}', ['\u{10412}', '\0', '\0']), ('\u{1043b}',
+        ['\u{10413}', '\0', '\0']), ('\u{1043c}', ['\u{10414}', '\0', '\0']), ('\u{1043d}',
+        ['\u{10415}', '\0', '\0']), ('\u{1043e}', ['\u{10416}', '\0', '\0']), ('\u{1043f}',
+        ['\u{10417}', '\0', '\0']), ('\u{10440}', ['\u{10418}', '\0', '\0']), ('\u{10441}',
+        ['\u{10419}', '\0', '\0']), ('\u{10442}', ['\u{1041a}', '\0', '\0']), ('\u{10443}',
+        ['\u{1041b}', '\0', '\0']), ('\u{10444}', ['\u{1041c}', '\0', '\0']), ('\u{10445}',
+        ['\u{1041d}', '\0', '\0']), ('\u{10446}', ['\u{1041e}', '\0', '\0']), ('\u{10447}',
+        ['\u{1041f}', '\0', '\0']), ('\u{10448}', ['\u{10420}', '\0', '\0']), ('\u{10449}',
+        ['\u{10421}', '\0', '\0']), ('\u{1044a}', ['\u{10422}', '\0', '\0']), ('\u{1044b}',
+        ['\u{10423}', '\0', '\0']), ('\u{1044c}', ['\u{10424}', '\0', '\0']), ('\u{1044d}',
+        ['\u{10425}', '\0', '\0']), ('\u{1044e}', ['\u{10426}', '\0', '\0']), ('\u{1044f}',
+        ['\u{10427}', '\0', '\0']), ('\u{118c0}', ['\u{118a0}', '\0', '\0']), ('\u{118c1}',
+        ['\u{118a1}', '\0', '\0']), ('\u{118c2}', ['\u{118a2}', '\0', '\0']), ('\u{118c3}',
+        ['\u{118a3}', '\0', '\0']), ('\u{118c4}', ['\u{118a4}', '\0', '\0']), ('\u{118c5}',
+        ['\u{118a5}', '\0', '\0']), ('\u{118c6}', ['\u{118a6}', '\0', '\0']), ('\u{118c7}',
+        ['\u{118a7}', '\0', '\0']), ('\u{118c8}', ['\u{118a8}', '\0', '\0']), ('\u{118c9}',
+        ['\u{118a9}', '\0', '\0']), ('\u{118ca}', ['\u{118aa}', '\0', '\0']), ('\u{118cb}',
+        ['\u{118ab}', '\0', '\0']), ('\u{118cc}', ['\u{118ac}', '\0', '\0']), ('\u{118cd}',
+        ['\u{118ad}', '\0', '\0']), ('\u{118ce}', ['\u{118ae}', '\0', '\0']), ('\u{118cf}',
+        ['\u{118af}', '\0', '\0']), ('\u{118d0}', ['\u{118b0}', '\0', '\0']), ('\u{118d1}',
+        ['\u{118b1}', '\0', '\0']), ('\u{118d2}', ['\u{118b2}', '\0', '\0']), ('\u{118d3}',
+        ['\u{118b3}', '\0', '\0']), ('\u{118d4}', ['\u{118b4}', '\0', '\0']), ('\u{118d5}',
+        ['\u{118b5}', '\0', '\0']), ('\u{118d6}', ['\u{118b6}', '\0', '\0']), ('\u{118d7}',
+        ['\u{118b7}', '\0', '\0']), ('\u{118d8}', ['\u{118b8}', '\0', '\0']), ('\u{118d9}',
+        ['\u{118b9}', '\0', '\0']), ('\u{118da}', ['\u{118ba}', '\0', '\0']), ('\u{118db}',
+        ['\u{118bb}', '\0', '\0']), ('\u{118dc}', ['\u{118bc}', '\0', '\0']), ('\u{118dd}',
+        ['\u{118bd}', '\0', '\0']), ('\u{118de}', ['\u{118be}', '\0', '\0']), ('\u{118df}',
+        ['\u{118bf}', '\0', '\0'])
     ];
 
-    const LlLu_table: &'static [(char, char)] = &[
-        ('\u{61}', '\u{41}'), ('\u{62}', '\u{42}'), ('\u{63}', '\u{43}'), ('\u{64}', '\u{44}'),
-        ('\u{65}', '\u{45}'), ('\u{66}', '\u{46}'), ('\u{67}', '\u{47}'), ('\u{68}', '\u{48}'),
-        ('\u{69}', '\u{49}'), ('\u{6a}', '\u{4a}'), ('\u{6b}', '\u{4b}'), ('\u{6c}', '\u{4c}'),
-        ('\u{6d}', '\u{4d}'), ('\u{6e}', '\u{4e}'), ('\u{6f}', '\u{4f}'), ('\u{70}', '\u{50}'),
-        ('\u{71}', '\u{51}'), ('\u{72}', '\u{52}'), ('\u{73}', '\u{53}'), ('\u{74}', '\u{54}'),
-        ('\u{75}', '\u{55}'), ('\u{76}', '\u{56}'), ('\u{77}', '\u{57}'), ('\u{78}', '\u{58}'),
-        ('\u{79}', '\u{59}'), ('\u{7a}', '\u{5a}'), ('\u{b5}', '\u{39c}'), ('\u{e0}', '\u{c0}'),
-        ('\u{e1}', '\u{c1}'), ('\u{e2}', '\u{c2}'), ('\u{e3}', '\u{c3}'), ('\u{e4}', '\u{c4}'),
-        ('\u{e5}', '\u{c5}'), ('\u{e6}', '\u{c6}'), ('\u{e7}', '\u{c7}'), ('\u{e8}', '\u{c8}'),
-        ('\u{e9}', '\u{c9}'), ('\u{ea}', '\u{ca}'), ('\u{eb}', '\u{cb}'), ('\u{ec}', '\u{cc}'),
-        ('\u{ed}', '\u{cd}'), ('\u{ee}', '\u{ce}'), ('\u{ef}', '\u{cf}'), ('\u{f0}', '\u{d0}'),
-        ('\u{f1}', '\u{d1}'), ('\u{f2}', '\u{d2}'), ('\u{f3}', '\u{d3}'), ('\u{f4}', '\u{d4}'),
-        ('\u{f5}', '\u{d5}'), ('\u{f6}', '\u{d6}'), ('\u{f8}', '\u{d8}'), ('\u{f9}', '\u{d9}'),
-        ('\u{fa}', '\u{da}'), ('\u{fb}', '\u{db}'), ('\u{fc}', '\u{dc}'), ('\u{fd}', '\u{dd}'),
-        ('\u{fe}', '\u{de}'), ('\u{ff}', '\u{178}'), ('\u{101}', '\u{100}'), ('\u{103}', '\u{102}'),
-        ('\u{105}', '\u{104}'), ('\u{107}', '\u{106}'), ('\u{109}', '\u{108}'), ('\u{10b}',
-        '\u{10a}'), ('\u{10d}', '\u{10c}'), ('\u{10f}', '\u{10e}'), ('\u{111}', '\u{110}'),
-        ('\u{113}', '\u{112}'), ('\u{115}', '\u{114}'), ('\u{117}', '\u{116}'), ('\u{119}',
-        '\u{118}'), ('\u{11b}', '\u{11a}'), ('\u{11d}', '\u{11c}'), ('\u{11f}', '\u{11e}'),
-        ('\u{121}', '\u{120}'), ('\u{123}', '\u{122}'), ('\u{125}', '\u{124}'), ('\u{127}',
-        '\u{126}'), ('\u{129}', '\u{128}'), ('\u{12b}', '\u{12a}'), ('\u{12d}', '\u{12c}'),
-        ('\u{12f}', '\u{12e}'), ('\u{131}', '\u{49}'), ('\u{133}', '\u{132}'), ('\u{135}',
-        '\u{134}'), ('\u{137}', '\u{136}'), ('\u{13a}', '\u{139}'), ('\u{13c}', '\u{13b}'),
-        ('\u{13e}', '\u{13d}'), ('\u{140}', '\u{13f}'), ('\u{142}', '\u{141}'), ('\u{144}',
-        '\u{143}'), ('\u{146}', '\u{145}'), ('\u{148}', '\u{147}'), ('\u{14b}', '\u{14a}'),
-        ('\u{14d}', '\u{14c}'), ('\u{14f}', '\u{14e}'), ('\u{151}', '\u{150}'), ('\u{153}',
-        '\u{152}'), ('\u{155}', '\u{154}'), ('\u{157}', '\u{156}'), ('\u{159}', '\u{158}'),
-        ('\u{15b}', '\u{15a}'), ('\u{15d}', '\u{15c}'), ('\u{15f}', '\u{15e}'), ('\u{161}',
-        '\u{160}'), ('\u{163}', '\u{162}'), ('\u{165}', '\u{164}'), ('\u{167}', '\u{166}'),
-        ('\u{169}', '\u{168}'), ('\u{16b}', '\u{16a}'), ('\u{16d}', '\u{16c}'), ('\u{16f}',
-        '\u{16e}'), ('\u{171}', '\u{170}'), ('\u{173}', '\u{172}'), ('\u{175}', '\u{174}'),
-        ('\u{177}', '\u{176}'), ('\u{17a}', '\u{179}'), ('\u{17c}', '\u{17b}'), ('\u{17e}',
-        '\u{17d}'), ('\u{17f}', '\u{53}'), ('\u{180}', '\u{243}'), ('\u{183}', '\u{182}'),
-        ('\u{185}', '\u{184}'), ('\u{188}', '\u{187}'), ('\u{18c}', '\u{18b}'), ('\u{192}',
-        '\u{191}'), ('\u{195}', '\u{1f6}'), ('\u{199}', '\u{198}'), ('\u{19a}', '\u{23d}'),
-        ('\u{19e}', '\u{220}'), ('\u{1a1}', '\u{1a0}'), ('\u{1a3}', '\u{1a2}'), ('\u{1a5}',
-        '\u{1a4}'), ('\u{1a8}', '\u{1a7}'), ('\u{1ad}', '\u{1ac}'), ('\u{1b0}', '\u{1af}'),
-        ('\u{1b4}', '\u{1b3}'), ('\u{1b6}', '\u{1b5}'), ('\u{1b9}', '\u{1b8}'), ('\u{1bd}',
-        '\u{1bc}'), ('\u{1bf}', '\u{1f7}'), ('\u{1c6}', '\u{1c4}'), ('\u{1c9}', '\u{1c7}'),
-        ('\u{1cc}', '\u{1ca}'), ('\u{1ce}', '\u{1cd}'), ('\u{1d0}', '\u{1cf}'), ('\u{1d2}',
-        '\u{1d1}'), ('\u{1d4}', '\u{1d3}'), ('\u{1d6}', '\u{1d5}'), ('\u{1d8}', '\u{1d7}'),
-        ('\u{1da}', '\u{1d9}'), ('\u{1dc}', '\u{1db}'), ('\u{1dd}', '\u{18e}'), ('\u{1df}',
-        '\u{1de}'), ('\u{1e1}', '\u{1e0}'), ('\u{1e3}', '\u{1e2}'), ('\u{1e5}', '\u{1e4}'),
-        ('\u{1e7}', '\u{1e6}'), ('\u{1e9}', '\u{1e8}'), ('\u{1eb}', '\u{1ea}'), ('\u{1ed}',
-        '\u{1ec}'), ('\u{1ef}', '\u{1ee}'), ('\u{1f3}', '\u{1f1}'), ('\u{1f5}', '\u{1f4}'),
-        ('\u{1f9}', '\u{1f8}'), ('\u{1fb}', '\u{1fa}'), ('\u{1fd}', '\u{1fc}'), ('\u{1ff}',
-        '\u{1fe}'), ('\u{201}', '\u{200}'), ('\u{203}', '\u{202}'), ('\u{205}', '\u{204}'),
-        ('\u{207}', '\u{206}'), ('\u{209}', '\u{208}'), ('\u{20b}', '\u{20a}'), ('\u{20d}',
-        '\u{20c}'), ('\u{20f}', '\u{20e}'), ('\u{211}', '\u{210}'), ('\u{213}', '\u{212}'),
-        ('\u{215}', '\u{214}'), ('\u{217}', '\u{216}'), ('\u{219}', '\u{218}'), ('\u{21b}',
-        '\u{21a}'), ('\u{21d}', '\u{21c}'), ('\u{21f}', '\u{21e}'), ('\u{223}', '\u{222}'),
-        ('\u{225}', '\u{224}'), ('\u{227}', '\u{226}'), ('\u{229}', '\u{228}'), ('\u{22b}',
-        '\u{22a}'), ('\u{22d}', '\u{22c}'), ('\u{22f}', '\u{22e}'), ('\u{231}', '\u{230}'),
-        ('\u{233}', '\u{232}'), ('\u{23c}', '\u{23b}'), ('\u{23f}', '\u{2c7e}'), ('\u{240}',
-        '\u{2c7f}'), ('\u{242}', '\u{241}'), ('\u{247}', '\u{246}'), ('\u{249}', '\u{248}'),
-        ('\u{24b}', '\u{24a}'), ('\u{24d}', '\u{24c}'), ('\u{24f}', '\u{24e}'), ('\u{250}',
-        '\u{2c6f}'), ('\u{251}', '\u{2c6d}'), ('\u{252}', '\u{2c70}'), ('\u{253}', '\u{181}'),
-        ('\u{254}', '\u{186}'), ('\u{256}', '\u{189}'), ('\u{257}', '\u{18a}'), ('\u{259}',
-        '\u{18f}'), ('\u{25b}', '\u{190}'), ('\u{25c}', '\u{a7ab}'), ('\u{260}', '\u{193}'),
-        ('\u{261}', '\u{a7ac}'), ('\u{263}', '\u{194}'), ('\u{265}', '\u{a78d}'), ('\u{266}',
-        '\u{a7aa}'), ('\u{268}', '\u{197}'), ('\u{269}', '\u{196}'), ('\u{26b}', '\u{2c62}'),
-        ('\u{26c}', '\u{a7ad}'), ('\u{26f}', '\u{19c}'), ('\u{271}', '\u{2c6e}'), ('\u{272}',
-        '\u{19d}'), ('\u{275}', '\u{19f}'), ('\u{27d}', '\u{2c64}'), ('\u{280}', '\u{1a6}'),
-        ('\u{283}', '\u{1a9}'), ('\u{287}', '\u{a7b1}'), ('\u{288}', '\u{1ae}'), ('\u{289}',
-        '\u{244}'), ('\u{28a}', '\u{1b1}'), ('\u{28b}', '\u{1b2}'), ('\u{28c}', '\u{245}'),
-        ('\u{292}', '\u{1b7}'), ('\u{29e}', '\u{a7b0}'), ('\u{371}', '\u{370}'), ('\u{373}',
-        '\u{372}'), ('\u{377}', '\u{376}'), ('\u{37b}', '\u{3fd}'), ('\u{37c}', '\u{3fe}'),
-        ('\u{37d}', '\u{3ff}'), ('\u{3ac}', '\u{386}'), ('\u{3ad}', '\u{388}'), ('\u{3ae}',
-        '\u{389}'), ('\u{3af}', '\u{38a}'), ('\u{3b1}', '\u{391}'), ('\u{3b2}', '\u{392}'),
-        ('\u{3b3}', '\u{393}'), ('\u{3b4}', '\u{394}'), ('\u{3b5}', '\u{395}'), ('\u{3b6}',
-        '\u{396}'), ('\u{3b7}', '\u{397}'), ('\u{3b8}', '\u{398}'), ('\u{3b9}', '\u{399}'),
-        ('\u{3ba}', '\u{39a}'), ('\u{3bb}', '\u{39b}'), ('\u{3bc}', '\u{39c}'), ('\u{3bd}',
-        '\u{39d}'), ('\u{3be}', '\u{39e}'), ('\u{3bf}', '\u{39f}'), ('\u{3c0}', '\u{3a0}'),
-        ('\u{3c1}', '\u{3a1}'), ('\u{3c2}', '\u{3a3}'), ('\u{3c3}', '\u{3a3}'), ('\u{3c4}',
-        '\u{3a4}'), ('\u{3c5}', '\u{3a5}'), ('\u{3c6}', '\u{3a6}'), ('\u{3c7}', '\u{3a7}'),
-        ('\u{3c8}', '\u{3a8}'), ('\u{3c9}', '\u{3a9}'), ('\u{3ca}', '\u{3aa}'), ('\u{3cb}',
-        '\u{3ab}'), ('\u{3cc}', '\u{38c}'), ('\u{3cd}', '\u{38e}'), ('\u{3ce}', '\u{38f}'),
-        ('\u{3d0}', '\u{392}'), ('\u{3d1}', '\u{398}'), ('\u{3d5}', '\u{3a6}'), ('\u{3d6}',
-        '\u{3a0}'), ('\u{3d7}', '\u{3cf}'), ('\u{3d9}', '\u{3d8}'), ('\u{3db}', '\u{3da}'),
-        ('\u{3dd}', '\u{3dc}'), ('\u{3df}', '\u{3de}'), ('\u{3e1}', '\u{3e0}'), ('\u{3e3}',
-        '\u{3e2}'), ('\u{3e5}', '\u{3e4}'), ('\u{3e7}', '\u{3e6}'), ('\u{3e9}', '\u{3e8}'),
-        ('\u{3eb}', '\u{3ea}'), ('\u{3ed}', '\u{3ec}'), ('\u{3ef}', '\u{3ee}'), ('\u{3f0}',
-        '\u{39a}'), ('\u{3f1}', '\u{3a1}'), ('\u{3f2}', '\u{3f9}'), ('\u{3f3}', '\u{37f}'),
-        ('\u{3f5}', '\u{395}'), ('\u{3f8}', '\u{3f7}'), ('\u{3fb}', '\u{3fa}'), ('\u{430}',
-        '\u{410}'), ('\u{431}', '\u{411}'), ('\u{432}', '\u{412}'), ('\u{433}', '\u{413}'),
-        ('\u{434}', '\u{414}'), ('\u{435}', '\u{415}'), ('\u{436}', '\u{416}'), ('\u{437}',
-        '\u{417}'), ('\u{438}', '\u{418}'), ('\u{439}', '\u{419}'), ('\u{43a}', '\u{41a}'),
-        ('\u{43b}', '\u{41b}'), ('\u{43c}', '\u{41c}'), ('\u{43d}', '\u{41d}'), ('\u{43e}',
-        '\u{41e}'), ('\u{43f}', '\u{41f}'), ('\u{440}', '\u{420}'), ('\u{441}', '\u{421}'),
-        ('\u{442}', '\u{422}'), ('\u{443}', '\u{423}'), ('\u{444}', '\u{424}'), ('\u{445}',
-        '\u{425}'), ('\u{446}', '\u{426}'), ('\u{447}', '\u{427}'), ('\u{448}', '\u{428}'),
-        ('\u{449}', '\u{429}'), ('\u{44a}', '\u{42a}'), ('\u{44b}', '\u{42b}'), ('\u{44c}',
-        '\u{42c}'), ('\u{44d}', '\u{42d}'), ('\u{44e}', '\u{42e}'), ('\u{44f}', '\u{42f}'),
-        ('\u{450}', '\u{400}'), ('\u{451}', '\u{401}'), ('\u{452}', '\u{402}'), ('\u{453}',
-        '\u{403}'), ('\u{454}', '\u{404}'), ('\u{455}', '\u{405}'), ('\u{456}', '\u{406}'),
-        ('\u{457}', '\u{407}'), ('\u{458}', '\u{408}'), ('\u{459}', '\u{409}'), ('\u{45a}',
-        '\u{40a}'), ('\u{45b}', '\u{40b}'), ('\u{45c}', '\u{40c}'), ('\u{45d}', '\u{40d}'),
-        ('\u{45e}', '\u{40e}'), ('\u{45f}', '\u{40f}'), ('\u{461}', '\u{460}'), ('\u{463}',
-        '\u{462}'), ('\u{465}', '\u{464}'), ('\u{467}', '\u{466}'), ('\u{469}', '\u{468}'),
-        ('\u{46b}', '\u{46a}'), ('\u{46d}', '\u{46c}'), ('\u{46f}', '\u{46e}'), ('\u{471}',
-        '\u{470}'), ('\u{473}', '\u{472}'), ('\u{475}', '\u{474}'), ('\u{477}', '\u{476}'),
-        ('\u{479}', '\u{478}'), ('\u{47b}', '\u{47a}'), ('\u{47d}', '\u{47c}'), ('\u{47f}',
-        '\u{47e}'), ('\u{481}', '\u{480}'), ('\u{48b}', '\u{48a}'), ('\u{48d}', '\u{48c}'),
-        ('\u{48f}', '\u{48e}'), ('\u{491}', '\u{490}'), ('\u{493}', '\u{492}'), ('\u{495}',
-        '\u{494}'), ('\u{497}', '\u{496}'), ('\u{499}', '\u{498}'), ('\u{49b}', '\u{49a}'),
-        ('\u{49d}', '\u{49c}'), ('\u{49f}', '\u{49e}'), ('\u{4a1}', '\u{4a0}'), ('\u{4a3}',
-        '\u{4a2}'), ('\u{4a5}', '\u{4a4}'), ('\u{4a7}', '\u{4a6}'), ('\u{4a9}', '\u{4a8}'),
-        ('\u{4ab}', '\u{4aa}'), ('\u{4ad}', '\u{4ac}'), ('\u{4af}', '\u{4ae}'), ('\u{4b1}',
-        '\u{4b0}'), ('\u{4b3}', '\u{4b2}'), ('\u{4b5}', '\u{4b4}'), ('\u{4b7}', '\u{4b6}'),
-        ('\u{4b9}', '\u{4b8}'), ('\u{4bb}', '\u{4ba}'), ('\u{4bd}', '\u{4bc}'), ('\u{4bf}',
-        '\u{4be}'), ('\u{4c2}', '\u{4c1}'), ('\u{4c4}', '\u{4c3}'), ('\u{4c6}', '\u{4c5}'),
-        ('\u{4c8}', '\u{4c7}'), ('\u{4ca}', '\u{4c9}'), ('\u{4cc}', '\u{4cb}'), ('\u{4ce}',
-        '\u{4cd}'), ('\u{4cf}', '\u{4c0}'), ('\u{4d1}', '\u{4d0}'), ('\u{4d3}', '\u{4d2}'),
-        ('\u{4d5}', '\u{4d4}'), ('\u{4d7}', '\u{4d6}'), ('\u{4d9}', '\u{4d8}'), ('\u{4db}',
-        '\u{4da}'), ('\u{4dd}', '\u{4dc}'), ('\u{4df}', '\u{4de}'), ('\u{4e1}', '\u{4e0}'),
-        ('\u{4e3}', '\u{4e2}'), ('\u{4e5}', '\u{4e4}'), ('\u{4e7}', '\u{4e6}'), ('\u{4e9}',
-        '\u{4e8}'), ('\u{4eb}', '\u{4ea}'), ('\u{4ed}', '\u{4ec}'), ('\u{4ef}', '\u{4ee}'),
-        ('\u{4f1}', '\u{4f0}'), ('\u{4f3}', '\u{4f2}'), ('\u{4f5}', '\u{4f4}'), ('\u{4f7}',
-        '\u{4f6}'), ('\u{4f9}', '\u{4f8}'), ('\u{4fb}', '\u{4fa}'), ('\u{4fd}', '\u{4fc}'),
-        ('\u{4ff}', '\u{4fe}'), ('\u{501}', '\u{500}'), ('\u{503}', '\u{502}'), ('\u{505}',
-        '\u{504}'), ('\u{507}', '\u{506}'), ('\u{509}', '\u{508}'), ('\u{50b}', '\u{50a}'),
-        ('\u{50d}', '\u{50c}'), ('\u{50f}', '\u{50e}'), ('\u{511}', '\u{510}'), ('\u{513}',
-        '\u{512}'), ('\u{515}', '\u{514}'), ('\u{517}', '\u{516}'), ('\u{519}', '\u{518}'),
-        ('\u{51b}', '\u{51a}'), ('\u{51d}', '\u{51c}'), ('\u{51f}', '\u{51e}'), ('\u{521}',
-        '\u{520}'), ('\u{523}', '\u{522}'), ('\u{525}', '\u{524}'), ('\u{527}', '\u{526}'),
-        ('\u{529}', '\u{528}'), ('\u{52b}', '\u{52a}'), ('\u{52d}', '\u{52c}'), ('\u{52f}',
-        '\u{52e}'), ('\u{561}', '\u{531}'), ('\u{562}', '\u{532}'), ('\u{563}', '\u{533}'),
-        ('\u{564}', '\u{534}'), ('\u{565}', '\u{535}'), ('\u{566}', '\u{536}'), ('\u{567}',
-        '\u{537}'), ('\u{568}', '\u{538}'), ('\u{569}', '\u{539}'), ('\u{56a}', '\u{53a}'),
-        ('\u{56b}', '\u{53b}'), ('\u{56c}', '\u{53c}'), ('\u{56d}', '\u{53d}'), ('\u{56e}',
-        '\u{53e}'), ('\u{56f}', '\u{53f}'), ('\u{570}', '\u{540}'), ('\u{571}', '\u{541}'),
-        ('\u{572}', '\u{542}'), ('\u{573}', '\u{543}'), ('\u{574}', '\u{544}'), ('\u{575}',
-        '\u{545}'), ('\u{576}', '\u{546}'), ('\u{577}', '\u{547}'), ('\u{578}', '\u{548}'),
-        ('\u{579}', '\u{549}'), ('\u{57a}', '\u{54a}'), ('\u{57b}', '\u{54b}'), ('\u{57c}',
-        '\u{54c}'), ('\u{57d}', '\u{54d}'), ('\u{57e}', '\u{54e}'), ('\u{57f}', '\u{54f}'),
-        ('\u{580}', '\u{550}'), ('\u{581}', '\u{551}'), ('\u{582}', '\u{552}'), ('\u{583}',
-        '\u{553}'), ('\u{584}', '\u{554}'), ('\u{585}', '\u{555}'), ('\u{586}', '\u{556}'),
-        ('\u{1d79}', '\u{a77d}'), ('\u{1d7d}', '\u{2c63}'), ('\u{1e01}', '\u{1e00}'), ('\u{1e03}',
-        '\u{1e02}'), ('\u{1e05}', '\u{1e04}'), ('\u{1e07}', '\u{1e06}'), ('\u{1e09}', '\u{1e08}'),
-        ('\u{1e0b}', '\u{1e0a}'), ('\u{1e0d}', '\u{1e0c}'), ('\u{1e0f}', '\u{1e0e}'), ('\u{1e11}',
-        '\u{1e10}'), ('\u{1e13}', '\u{1e12}'), ('\u{1e15}', '\u{1e14}'), ('\u{1e17}', '\u{1e16}'),
-        ('\u{1e19}', '\u{1e18}'), ('\u{1e1b}', '\u{1e1a}'), ('\u{1e1d}', '\u{1e1c}'), ('\u{1e1f}',
-        '\u{1e1e}'), ('\u{1e21}', '\u{1e20}'), ('\u{1e23}', '\u{1e22}'), ('\u{1e25}', '\u{1e24}'),
-        ('\u{1e27}', '\u{1e26}'), ('\u{1e29}', '\u{1e28}'), ('\u{1e2b}', '\u{1e2a}'), ('\u{1e2d}',
-        '\u{1e2c}'), ('\u{1e2f}', '\u{1e2e}'), ('\u{1e31}', '\u{1e30}'), ('\u{1e33}', '\u{1e32}'),
-        ('\u{1e35}', '\u{1e34}'), ('\u{1e37}', '\u{1e36}'), ('\u{1e39}', '\u{1e38}'), ('\u{1e3b}',
-        '\u{1e3a}'), ('\u{1e3d}', '\u{1e3c}'), ('\u{1e3f}', '\u{1e3e}'), ('\u{1e41}', '\u{1e40}'),
-        ('\u{1e43}', '\u{1e42}'), ('\u{1e45}', '\u{1e44}'), ('\u{1e47}', '\u{1e46}'), ('\u{1e49}',
-        '\u{1e48}'), ('\u{1e4b}', '\u{1e4a}'), ('\u{1e4d}', '\u{1e4c}'), ('\u{1e4f}', '\u{1e4e}'),
-        ('\u{1e51}', '\u{1e50}'), ('\u{1e53}', '\u{1e52}'), ('\u{1e55}', '\u{1e54}'), ('\u{1e57}',
-        '\u{1e56}'), ('\u{1e59}', '\u{1e58}'), ('\u{1e5b}', '\u{1e5a}'), ('\u{1e5d}', '\u{1e5c}'),
-        ('\u{1e5f}', '\u{1e5e}'), ('\u{1e61}', '\u{1e60}'), ('\u{1e63}', '\u{1e62}'), ('\u{1e65}',
-        '\u{1e64}'), ('\u{1e67}', '\u{1e66}'), ('\u{1e69}', '\u{1e68}'), ('\u{1e6b}', '\u{1e6a}'),
-        ('\u{1e6d}', '\u{1e6c}'), ('\u{1e6f}', '\u{1e6e}'), ('\u{1e71}', '\u{1e70}'), ('\u{1e73}',
-        '\u{1e72}'), ('\u{1e75}', '\u{1e74}'), ('\u{1e77}', '\u{1e76}'), ('\u{1e79}', '\u{1e78}'),
-        ('\u{1e7b}', '\u{1e7a}'), ('\u{1e7d}', '\u{1e7c}'), ('\u{1e7f}', '\u{1e7e}'), ('\u{1e81}',
-        '\u{1e80}'), ('\u{1e83}', '\u{1e82}'), ('\u{1e85}', '\u{1e84}'), ('\u{1e87}', '\u{1e86}'),
-        ('\u{1e89}', '\u{1e88}'), ('\u{1e8b}', '\u{1e8a}'), ('\u{1e8d}', '\u{1e8c}'), ('\u{1e8f}',
-        '\u{1e8e}'), ('\u{1e91}', '\u{1e90}'), ('\u{1e93}', '\u{1e92}'), ('\u{1e95}', '\u{1e94}'),
-        ('\u{1e9b}', '\u{1e60}'), ('\u{1ea1}', '\u{1ea0}'), ('\u{1ea3}', '\u{1ea2}'), ('\u{1ea5}',
-        '\u{1ea4}'), ('\u{1ea7}', '\u{1ea6}'), ('\u{1ea9}', '\u{1ea8}'), ('\u{1eab}', '\u{1eaa}'),
-        ('\u{1ead}', '\u{1eac}'), ('\u{1eaf}', '\u{1eae}'), ('\u{1eb1}', '\u{1eb0}'), ('\u{1eb3}',
-        '\u{1eb2}'), ('\u{1eb5}', '\u{1eb4}'), ('\u{1eb7}', '\u{1eb6}'), ('\u{1eb9}', '\u{1eb8}'),
-        ('\u{1ebb}', '\u{1eba}'), ('\u{1ebd}', '\u{1ebc}'), ('\u{1ebf}', '\u{1ebe}'), ('\u{1ec1}',
-        '\u{1ec0}'), ('\u{1ec3}', '\u{1ec2}'), ('\u{1ec5}', '\u{1ec4}'), ('\u{1ec7}', '\u{1ec6}'),
-        ('\u{1ec9}', '\u{1ec8}'), ('\u{1ecb}', '\u{1eca}'), ('\u{1ecd}', '\u{1ecc}'), ('\u{1ecf}',
-        '\u{1ece}'), ('\u{1ed1}', '\u{1ed0}'), ('\u{1ed3}', '\u{1ed2}'), ('\u{1ed5}', '\u{1ed4}'),
-        ('\u{1ed7}', '\u{1ed6}'), ('\u{1ed9}', '\u{1ed8}'), ('\u{1edb}', '\u{1eda}'), ('\u{1edd}',
-        '\u{1edc}'), ('\u{1edf}', '\u{1ede}'), ('\u{1ee1}', '\u{1ee0}'), ('\u{1ee3}', '\u{1ee2}'),
-        ('\u{1ee5}', '\u{1ee4}'), ('\u{1ee7}', '\u{1ee6}'), ('\u{1ee9}', '\u{1ee8}'), ('\u{1eeb}',
-        '\u{1eea}'), ('\u{1eed}', '\u{1eec}'), ('\u{1eef}', '\u{1eee}'), ('\u{1ef1}', '\u{1ef0}'),
-        ('\u{1ef3}', '\u{1ef2}'), ('\u{1ef5}', '\u{1ef4}'), ('\u{1ef7}', '\u{1ef6}'), ('\u{1ef9}',
-        '\u{1ef8}'), ('\u{1efb}', '\u{1efa}'), ('\u{1efd}', '\u{1efc}'), ('\u{1eff}', '\u{1efe}'),
-        ('\u{1f00}', '\u{1f08}'), ('\u{1f01}', '\u{1f09}'), ('\u{1f02}', '\u{1f0a}'), ('\u{1f03}',
-        '\u{1f0b}'), ('\u{1f04}', '\u{1f0c}'), ('\u{1f05}', '\u{1f0d}'), ('\u{1f06}', '\u{1f0e}'),
-        ('\u{1f07}', '\u{1f0f}'), ('\u{1f10}', '\u{1f18}'), ('\u{1f11}', '\u{1f19}'), ('\u{1f12}',
-        '\u{1f1a}'), ('\u{1f13}', '\u{1f1b}'), ('\u{1f14}', '\u{1f1c}'), ('\u{1f15}', '\u{1f1d}'),
-        ('\u{1f20}', '\u{1f28}'), ('\u{1f21}', '\u{1f29}'), ('\u{1f22}', '\u{1f2a}'), ('\u{1f23}',
-        '\u{1f2b}'), ('\u{1f24}', '\u{1f2c}'), ('\u{1f25}', '\u{1f2d}'), ('\u{1f26}', '\u{1f2e}'),
-        ('\u{1f27}', '\u{1f2f}'), ('\u{1f30}', '\u{1f38}'), ('\u{1f31}', '\u{1f39}'), ('\u{1f32}',
-        '\u{1f3a}'), ('\u{1f33}', '\u{1f3b}'), ('\u{1f34}', '\u{1f3c}'), ('\u{1f35}', '\u{1f3d}'),
-        ('\u{1f36}', '\u{1f3e}'), ('\u{1f37}', '\u{1f3f}'), ('\u{1f40}', '\u{1f48}'), ('\u{1f41}',
-        '\u{1f49}'), ('\u{1f42}', '\u{1f4a}'), ('\u{1f43}', '\u{1f4b}'), ('\u{1f44}', '\u{1f4c}'),
-        ('\u{1f45}', '\u{1f4d}'), ('\u{1f51}', '\u{1f59}'), ('\u{1f53}', '\u{1f5b}'), ('\u{1f55}',
-        '\u{1f5d}'), ('\u{1f57}', '\u{1f5f}'), ('\u{1f60}', '\u{1f68}'), ('\u{1f61}', '\u{1f69}'),
-        ('\u{1f62}', '\u{1f6a}'), ('\u{1f63}', '\u{1f6b}'), ('\u{1f64}', '\u{1f6c}'), ('\u{1f65}',
-        '\u{1f6d}'), ('\u{1f66}', '\u{1f6e}'), ('\u{1f67}', '\u{1f6f}'), ('\u{1f70}', '\u{1fba}'),
-        ('\u{1f71}', '\u{1fbb}'), ('\u{1f72}', '\u{1fc8}'), ('\u{1f73}', '\u{1fc9}'), ('\u{1f74}',
-        '\u{1fca}'), ('\u{1f75}', '\u{1fcb}'), ('\u{1f76}', '\u{1fda}'), ('\u{1f77}', '\u{1fdb}'),
-        ('\u{1f78}', '\u{1ff8}'), ('\u{1f79}', '\u{1ff9}'), ('\u{1f7a}', '\u{1fea}'), ('\u{1f7b}',
-        '\u{1feb}'), ('\u{1f7c}', '\u{1ffa}'), ('\u{1f7d}', '\u{1ffb}'), ('\u{1f80}', '\u{1f88}'),
-        ('\u{1f81}', '\u{1f89}'), ('\u{1f82}', '\u{1f8a}'), ('\u{1f83}', '\u{1f8b}'), ('\u{1f84}',
-        '\u{1f8c}'), ('\u{1f85}', '\u{1f8d}'), ('\u{1f86}', '\u{1f8e}'), ('\u{1f87}', '\u{1f8f}'),
-        ('\u{1f90}', '\u{1f98}'), ('\u{1f91}', '\u{1f99}'), ('\u{1f92}', '\u{1f9a}'), ('\u{1f93}',
-        '\u{1f9b}'), ('\u{1f94}', '\u{1f9c}'), ('\u{1f95}', '\u{1f9d}'), ('\u{1f96}', '\u{1f9e}'),
-        ('\u{1f97}', '\u{1f9f}'), ('\u{1fa0}', '\u{1fa8}'), ('\u{1fa1}', '\u{1fa9}'), ('\u{1fa2}',
-        '\u{1faa}'), ('\u{1fa3}', '\u{1fab}'), ('\u{1fa4}', '\u{1fac}'), ('\u{1fa5}', '\u{1fad}'),
-        ('\u{1fa6}', '\u{1fae}'), ('\u{1fa7}', '\u{1faf}'), ('\u{1fb0}', '\u{1fb8}'), ('\u{1fb1}',
-        '\u{1fb9}'), ('\u{1fb3}', '\u{1fbc}'), ('\u{1fbe}', '\u{399}'), ('\u{1fc3}', '\u{1fcc}'),
-        ('\u{1fd0}', '\u{1fd8}'), ('\u{1fd1}', '\u{1fd9}'), ('\u{1fe0}', '\u{1fe8}'), ('\u{1fe1}',
-        '\u{1fe9}'), ('\u{1fe5}', '\u{1fec}'), ('\u{1ff3}', '\u{1ffc}'), ('\u{214e}', '\u{2132}'),
-        ('\u{2184}', '\u{2183}'), ('\u{2c30}', '\u{2c00}'), ('\u{2c31}', '\u{2c01}'), ('\u{2c32}',
-        '\u{2c02}'), ('\u{2c33}', '\u{2c03}'), ('\u{2c34}', '\u{2c04}'), ('\u{2c35}', '\u{2c05}'),
-        ('\u{2c36}', '\u{2c06}'), ('\u{2c37}', '\u{2c07}'), ('\u{2c38}', '\u{2c08}'), ('\u{2c39}',
-        '\u{2c09}'), ('\u{2c3a}', '\u{2c0a}'), ('\u{2c3b}', '\u{2c0b}'), ('\u{2c3c}', '\u{2c0c}'),
-        ('\u{2c3d}', '\u{2c0d}'), ('\u{2c3e}', '\u{2c0e}'), ('\u{2c3f}', '\u{2c0f}'), ('\u{2c40}',
-        '\u{2c10}'), ('\u{2c41}', '\u{2c11}'), ('\u{2c42}', '\u{2c12}'), ('\u{2c43}', '\u{2c13}'),
-        ('\u{2c44}', '\u{2c14}'), ('\u{2c45}', '\u{2c15}'), ('\u{2c46}', '\u{2c16}'), ('\u{2c47}',
-        '\u{2c17}'), ('\u{2c48}', '\u{2c18}'), ('\u{2c49}', '\u{2c19}'), ('\u{2c4a}', '\u{2c1a}'),
-        ('\u{2c4b}', '\u{2c1b}'), ('\u{2c4c}', '\u{2c1c}'), ('\u{2c4d}', '\u{2c1d}'), ('\u{2c4e}',
-        '\u{2c1e}'), ('\u{2c4f}', '\u{2c1f}'), ('\u{2c50}', '\u{2c20}'), ('\u{2c51}', '\u{2c21}'),
-        ('\u{2c52}', '\u{2c22}'), ('\u{2c53}', '\u{2c23}'), ('\u{2c54}', '\u{2c24}'), ('\u{2c55}',
-        '\u{2c25}'), ('\u{2c56}', '\u{2c26}'), ('\u{2c57}', '\u{2c27}'), ('\u{2c58}', '\u{2c28}'),
-        ('\u{2c59}', '\u{2c29}'), ('\u{2c5a}', '\u{2c2a}'), ('\u{2c5b}', '\u{2c2b}'), ('\u{2c5c}',
-        '\u{2c2c}'), ('\u{2c5d}', '\u{2c2d}'), ('\u{2c5e}', '\u{2c2e}'), ('\u{2c61}', '\u{2c60}'),
-        ('\u{2c65}', '\u{23a}'), ('\u{2c66}', '\u{23e}'), ('\u{2c68}', '\u{2c67}'), ('\u{2c6a}',
-        '\u{2c69}'), ('\u{2c6c}', '\u{2c6b}'), ('\u{2c73}', '\u{2c72}'), ('\u{2c76}', '\u{2c75}'),
-        ('\u{2c81}', '\u{2c80}'), ('\u{2c83}', '\u{2c82}'), ('\u{2c85}', '\u{2c84}'), ('\u{2c87}',
-        '\u{2c86}'), ('\u{2c89}', '\u{2c88}'), ('\u{2c8b}', '\u{2c8a}'), ('\u{2c8d}', '\u{2c8c}'),
-        ('\u{2c8f}', '\u{2c8e}'), ('\u{2c91}', '\u{2c90}'), ('\u{2c93}', '\u{2c92}'), ('\u{2c95}',
-        '\u{2c94}'), ('\u{2c97}', '\u{2c96}'), ('\u{2c99}', '\u{2c98}'), ('\u{2c9b}', '\u{2c9a}'),
-        ('\u{2c9d}', '\u{2c9c}'), ('\u{2c9f}', '\u{2c9e}'), ('\u{2ca1}', '\u{2ca0}'), ('\u{2ca3}',
-        '\u{2ca2}'), ('\u{2ca5}', '\u{2ca4}'), ('\u{2ca7}', '\u{2ca6}'), ('\u{2ca9}', '\u{2ca8}'),
-        ('\u{2cab}', '\u{2caa}'), ('\u{2cad}', '\u{2cac}'), ('\u{2caf}', '\u{2cae}'), ('\u{2cb1}',
-        '\u{2cb0}'), ('\u{2cb3}', '\u{2cb2}'), ('\u{2cb5}', '\u{2cb4}'), ('\u{2cb7}', '\u{2cb6}'),
-        ('\u{2cb9}', '\u{2cb8}'), ('\u{2cbb}', '\u{2cba}'), ('\u{2cbd}', '\u{2cbc}'), ('\u{2cbf}',
-        '\u{2cbe}'), ('\u{2cc1}', '\u{2cc0}'), ('\u{2cc3}', '\u{2cc2}'), ('\u{2cc5}', '\u{2cc4}'),
-        ('\u{2cc7}', '\u{2cc6}'), ('\u{2cc9}', '\u{2cc8}'), ('\u{2ccb}', '\u{2cca}'), ('\u{2ccd}',
-        '\u{2ccc}'), ('\u{2ccf}', '\u{2cce}'), ('\u{2cd1}', '\u{2cd0}'), ('\u{2cd3}', '\u{2cd2}'),
-        ('\u{2cd5}', '\u{2cd4}'), ('\u{2cd7}', '\u{2cd6}'), ('\u{2cd9}', '\u{2cd8}'), ('\u{2cdb}',
-        '\u{2cda}'), ('\u{2cdd}', '\u{2cdc}'), ('\u{2cdf}', '\u{2cde}'), ('\u{2ce1}', '\u{2ce0}'),
-        ('\u{2ce3}', '\u{2ce2}'), ('\u{2cec}', '\u{2ceb}'), ('\u{2cee}', '\u{2ced}'), ('\u{2cf3}',
-        '\u{2cf2}'), ('\u{2d00}', '\u{10a0}'), ('\u{2d01}', '\u{10a1}'), ('\u{2d02}', '\u{10a2}'),
-        ('\u{2d03}', '\u{10a3}'), ('\u{2d04}', '\u{10a4}'), ('\u{2d05}', '\u{10a5}'), ('\u{2d06}',
-        '\u{10a6}'), ('\u{2d07}', '\u{10a7}'), ('\u{2d08}', '\u{10a8}'), ('\u{2d09}', '\u{10a9}'),
-        ('\u{2d0a}', '\u{10aa}'), ('\u{2d0b}', '\u{10ab}'), ('\u{2d0c}', '\u{10ac}'), ('\u{2d0d}',
-        '\u{10ad}'), ('\u{2d0e}', '\u{10ae}'), ('\u{2d0f}', '\u{10af}'), ('\u{2d10}', '\u{10b0}'),
-        ('\u{2d11}', '\u{10b1}'), ('\u{2d12}', '\u{10b2}'), ('\u{2d13}', '\u{10b3}'), ('\u{2d14}',
-        '\u{10b4}'), ('\u{2d15}', '\u{10b5}'), ('\u{2d16}', '\u{10b6}'), ('\u{2d17}', '\u{10b7}'),
-        ('\u{2d18}', '\u{10b8}'), ('\u{2d19}', '\u{10b9}'), ('\u{2d1a}', '\u{10ba}'), ('\u{2d1b}',
-        '\u{10bb}'), ('\u{2d1c}', '\u{10bc}'), ('\u{2d1d}', '\u{10bd}'), ('\u{2d1e}', '\u{10be}'),
-        ('\u{2d1f}', '\u{10bf}'), ('\u{2d20}', '\u{10c0}'), ('\u{2d21}', '\u{10c1}'), ('\u{2d22}',
-        '\u{10c2}'), ('\u{2d23}', '\u{10c3}'), ('\u{2d24}', '\u{10c4}'), ('\u{2d25}', '\u{10c5}'),
-        ('\u{2d27}', '\u{10c7}'), ('\u{2d2d}', '\u{10cd}'), ('\u{a641}', '\u{a640}'), ('\u{a643}',
-        '\u{a642}'), ('\u{a645}', '\u{a644}'), ('\u{a647}', '\u{a646}'), ('\u{a649}', '\u{a648}'),
-        ('\u{a64b}', '\u{a64a}'), ('\u{a64d}', '\u{a64c}'), ('\u{a64f}', '\u{a64e}'), ('\u{a651}',
-        '\u{a650}'), ('\u{a653}', '\u{a652}'), ('\u{a655}', '\u{a654}'), ('\u{a657}', '\u{a656}'),
-        ('\u{a659}', '\u{a658}'), ('\u{a65b}', '\u{a65a}'), ('\u{a65d}', '\u{a65c}'), ('\u{a65f}',
-        '\u{a65e}'), ('\u{a661}', '\u{a660}'), ('\u{a663}', '\u{a662}'), ('\u{a665}', '\u{a664}'),
-        ('\u{a667}', '\u{a666}'), ('\u{a669}', '\u{a668}'), ('\u{a66b}', '\u{a66a}'), ('\u{a66d}',
-        '\u{a66c}'), ('\u{a681}', '\u{a680}'), ('\u{a683}', '\u{a682}'), ('\u{a685}', '\u{a684}'),
-        ('\u{a687}', '\u{a686}'), ('\u{a689}', '\u{a688}'), ('\u{a68b}', '\u{a68a}'), ('\u{a68d}',
-        '\u{a68c}'), ('\u{a68f}', '\u{a68e}'), ('\u{a691}', '\u{a690}'), ('\u{a693}', '\u{a692}'),
-        ('\u{a695}', '\u{a694}'), ('\u{a697}', '\u{a696}'), ('\u{a699}', '\u{a698}'), ('\u{a69b}',
-        '\u{a69a}'), ('\u{a723}', '\u{a722}'), ('\u{a725}', '\u{a724}'), ('\u{a727}', '\u{a726}'),
-        ('\u{a729}', '\u{a728}'), ('\u{a72b}', '\u{a72a}'), ('\u{a72d}', '\u{a72c}'), ('\u{a72f}',
-        '\u{a72e}'), ('\u{a733}', '\u{a732}'), ('\u{a735}', '\u{a734}'), ('\u{a737}', '\u{a736}'),
-        ('\u{a739}', '\u{a738}'), ('\u{a73b}', '\u{a73a}'), ('\u{a73d}', '\u{a73c}'), ('\u{a73f}',
-        '\u{a73e}'), ('\u{a741}', '\u{a740}'), ('\u{a743}', '\u{a742}'), ('\u{a745}', '\u{a744}'),
-        ('\u{a747}', '\u{a746}'), ('\u{a749}', '\u{a748}'), ('\u{a74b}', '\u{a74a}'), ('\u{a74d}',
-        '\u{a74c}'), ('\u{a74f}', '\u{a74e}'), ('\u{a751}', '\u{a750}'), ('\u{a753}', '\u{a752}'),
-        ('\u{a755}', '\u{a754}'), ('\u{a757}', '\u{a756}'), ('\u{a759}', '\u{a758}'), ('\u{a75b}',
-        '\u{a75a}'), ('\u{a75d}', '\u{a75c}'), ('\u{a75f}', '\u{a75e}'), ('\u{a761}', '\u{a760}'),
-        ('\u{a763}', '\u{a762}'), ('\u{a765}', '\u{a764}'), ('\u{a767}', '\u{a766}'), ('\u{a769}',
-        '\u{a768}'), ('\u{a76b}', '\u{a76a}'), ('\u{a76d}', '\u{a76c}'), ('\u{a76f}', '\u{a76e}'),
-        ('\u{a77a}', '\u{a779}'), ('\u{a77c}', '\u{a77b}'), ('\u{a77f}', '\u{a77e}'), ('\u{a781}',
-        '\u{a780}'), ('\u{a783}', '\u{a782}'), ('\u{a785}', '\u{a784}'), ('\u{a787}', '\u{a786}'),
-        ('\u{a78c}', '\u{a78b}'), ('\u{a791}', '\u{a790}'), ('\u{a793}', '\u{a792}'), ('\u{a797}',
-        '\u{a796}'), ('\u{a799}', '\u{a798}'), ('\u{a79b}', '\u{a79a}'), ('\u{a79d}', '\u{a79c}'),
-        ('\u{a79f}', '\u{a79e}'), ('\u{a7a1}', '\u{a7a0}'), ('\u{a7a3}', '\u{a7a2}'), ('\u{a7a5}',
-        '\u{a7a4}'), ('\u{a7a7}', '\u{a7a6}'), ('\u{a7a9}', '\u{a7a8}'), ('\u{ff41}', '\u{ff21}'),
-        ('\u{ff42}', '\u{ff22}'), ('\u{ff43}', '\u{ff23}'), ('\u{ff44}', '\u{ff24}'), ('\u{ff45}',
-        '\u{ff25}'), ('\u{ff46}', '\u{ff26}'), ('\u{ff47}', '\u{ff27}'), ('\u{ff48}', '\u{ff28}'),
-        ('\u{ff49}', '\u{ff29}'), ('\u{ff4a}', '\u{ff2a}'), ('\u{ff4b}', '\u{ff2b}'), ('\u{ff4c}',
-        '\u{ff2c}'), ('\u{ff4d}', '\u{ff2d}'), ('\u{ff4e}', '\u{ff2e}'), ('\u{ff4f}', '\u{ff2f}'),
-        ('\u{ff50}', '\u{ff30}'), ('\u{ff51}', '\u{ff31}'), ('\u{ff52}', '\u{ff32}'), ('\u{ff53}',
-        '\u{ff33}'), ('\u{ff54}', '\u{ff34}'), ('\u{ff55}', '\u{ff35}'), ('\u{ff56}', '\u{ff36}'),
-        ('\u{ff57}', '\u{ff37}'), ('\u{ff58}', '\u{ff38}'), ('\u{ff59}', '\u{ff39}'), ('\u{ff5a}',
-        '\u{ff3a}'), ('\u{10428}', '\u{10400}'), ('\u{10429}', '\u{10401}'), ('\u{1042a}',
-        '\u{10402}'), ('\u{1042b}', '\u{10403}'), ('\u{1042c}', '\u{10404}'), ('\u{1042d}',
-        '\u{10405}'), ('\u{1042e}', '\u{10406}'), ('\u{1042f}', '\u{10407}'), ('\u{10430}',
-        '\u{10408}'), ('\u{10431}', '\u{10409}'), ('\u{10432}', '\u{1040a}'), ('\u{10433}',
-        '\u{1040b}'), ('\u{10434}', '\u{1040c}'), ('\u{10435}', '\u{1040d}'), ('\u{10436}',
-        '\u{1040e}'), ('\u{10437}', '\u{1040f}'), ('\u{10438}', '\u{10410}'), ('\u{10439}',
-        '\u{10411}'), ('\u{1043a}', '\u{10412}'), ('\u{1043b}', '\u{10413}'), ('\u{1043c}',
-        '\u{10414}'), ('\u{1043d}', '\u{10415}'), ('\u{1043e}', '\u{10416}'), ('\u{1043f}',
-        '\u{10417}'), ('\u{10440}', '\u{10418}'), ('\u{10441}', '\u{10419}'), ('\u{10442}',
-        '\u{1041a}'), ('\u{10443}', '\u{1041b}'), ('\u{10444}', '\u{1041c}'), ('\u{10445}',
-        '\u{1041d}'), ('\u{10446}', '\u{1041e}'), ('\u{10447}', '\u{1041f}'), ('\u{10448}',
-        '\u{10420}'), ('\u{10449}', '\u{10421}'), ('\u{1044a}', '\u{10422}'), ('\u{1044b}',
-        '\u{10423}'), ('\u{1044c}', '\u{10424}'), ('\u{1044d}', '\u{10425}'), ('\u{1044e}',
-        '\u{10426}'), ('\u{1044f}', '\u{10427}'), ('\u{118c0}', '\u{118a0}'), ('\u{118c1}',
-        '\u{118a1}'), ('\u{118c2}', '\u{118a2}'), ('\u{118c3}', '\u{118a3}'), ('\u{118c4}',
-        '\u{118a4}'), ('\u{118c5}', '\u{118a5}'), ('\u{118c6}', '\u{118a6}'), ('\u{118c7}',
-        '\u{118a7}'), ('\u{118c8}', '\u{118a8}'), ('\u{118c9}', '\u{118a9}'), ('\u{118ca}',
-        '\u{118aa}'), ('\u{118cb}', '\u{118ab}'), ('\u{118cc}', '\u{118ac}'), ('\u{118cd}',
-        '\u{118ad}'), ('\u{118ce}', '\u{118ae}'), ('\u{118cf}', '\u{118af}'), ('\u{118d0}',
-        '\u{118b0}'), ('\u{118d1}', '\u{118b1}'), ('\u{118d2}', '\u{118b2}'), ('\u{118d3}',
-        '\u{118b3}'), ('\u{118d4}', '\u{118b4}'), ('\u{118d5}', '\u{118b5}'), ('\u{118d6}',
-        '\u{118b6}'), ('\u{118d7}', '\u{118b7}'), ('\u{118d8}', '\u{118b8}'), ('\u{118d9}',
-        '\u{118b9}'), ('\u{118da}', '\u{118ba}'), ('\u{118db}', '\u{118bb}'), ('\u{118dc}',
-        '\u{118bc}'), ('\u{118dd}', '\u{118bd}'), ('\u{118de}', '\u{118be}'), ('\u{118df}',
-        '\u{118bf}')
+    const to_titlecase_table: &'static [(char, [char; 3])] = &[
+        ('\u{61}', ['\u{41}', '\0', '\0']), ('\u{62}', ['\u{42}', '\0', '\0']), ('\u{63}',
+        ['\u{43}', '\0', '\0']), ('\u{64}', ['\u{44}', '\0', '\0']), ('\u{65}', ['\u{45}', '\0',
+        '\0']), ('\u{66}', ['\u{46}', '\0', '\0']), ('\u{67}', ['\u{47}', '\0', '\0']), ('\u{68}',
+        ['\u{48}', '\0', '\0']), ('\u{69}', ['\u{49}', '\0', '\0']), ('\u{6a}', ['\u{4a}', '\0',
+        '\0']), ('\u{6b}', ['\u{4b}', '\0', '\0']), ('\u{6c}', ['\u{4c}', '\0', '\0']), ('\u{6d}',
+        ['\u{4d}', '\0', '\0']), ('\u{6e}', ['\u{4e}', '\0', '\0']), ('\u{6f}', ['\u{4f}', '\0',
+        '\0']), ('\u{70}', ['\u{50}', '\0', '\0']), ('\u{71}', ['\u{51}', '\0', '\0']), ('\u{72}',
+        ['\u{52}', '\0', '\0']), ('\u{73}', ['\u{53}', '\0', '\0']), ('\u{74}', ['\u{54}', '\0',
+        '\0']), ('\u{75}', ['\u{55}', '\0', '\0']), ('\u{76}', ['\u{56}', '\0', '\0']), ('\u{77}',
+        ['\u{57}', '\0', '\0']), ('\u{78}', ['\u{58}', '\0', '\0']), ('\u{79}', ['\u{59}', '\0',
+        '\0']), ('\u{7a}', ['\u{5a}', '\0', '\0']), ('\u{b5}', ['\u{39c}', '\0', '\0']), ('\u{df}',
+        ['\u{53}', '\u{73}', '\0']), ('\u{e0}', ['\u{c0}', '\0', '\0']), ('\u{e1}', ['\u{c1}', '\0',
+        '\0']), ('\u{e2}', ['\u{c2}', '\0', '\0']), ('\u{e3}', ['\u{c3}', '\0', '\0']), ('\u{e4}',
+        ['\u{c4}', '\0', '\0']), ('\u{e5}', ['\u{c5}', '\0', '\0']), ('\u{e6}', ['\u{c6}', '\0',
+        '\0']), ('\u{e7}', ['\u{c7}', '\0', '\0']), ('\u{e8}', ['\u{c8}', '\0', '\0']), ('\u{e9}',
+        ['\u{c9}', '\0', '\0']), ('\u{ea}', ['\u{ca}', '\0', '\0']), ('\u{eb}', ['\u{cb}', '\0',
+        '\0']), ('\u{ec}', ['\u{cc}', '\0', '\0']), ('\u{ed}', ['\u{cd}', '\0', '\0']), ('\u{ee}',
+        ['\u{ce}', '\0', '\0']), ('\u{ef}', ['\u{cf}', '\0', '\0']), ('\u{f0}', ['\u{d0}', '\0',
+        '\0']), ('\u{f1}', ['\u{d1}', '\0', '\0']), ('\u{f2}', ['\u{d2}', '\0', '\0']), ('\u{f3}',
+        ['\u{d3}', '\0', '\0']), ('\u{f4}', ['\u{d4}', '\0', '\0']), ('\u{f5}', ['\u{d5}', '\0',
+        '\0']), ('\u{f6}', ['\u{d6}', '\0', '\0']), ('\u{f8}', ['\u{d8}', '\0', '\0']), ('\u{f9}',
+        ['\u{d9}', '\0', '\0']), ('\u{fa}', ['\u{da}', '\0', '\0']), ('\u{fb}', ['\u{db}', '\0',
+        '\0']), ('\u{fc}', ['\u{dc}', '\0', '\0']), ('\u{fd}', ['\u{dd}', '\0', '\0']), ('\u{fe}',
+        ['\u{de}', '\0', '\0']), ('\u{ff}', ['\u{178}', '\0', '\0']), ('\u{101}', ['\u{100}', '\0',
+        '\0']), ('\u{103}', ['\u{102}', '\0', '\0']), ('\u{105}', ['\u{104}', '\0', '\0']),
+        ('\u{107}', ['\u{106}', '\0', '\0']), ('\u{109}', ['\u{108}', '\0', '\0']), ('\u{10b}',
+        ['\u{10a}', '\0', '\0']), ('\u{10d}', ['\u{10c}', '\0', '\0']), ('\u{10f}', ['\u{10e}',
+        '\0', '\0']), ('\u{111}', ['\u{110}', '\0', '\0']), ('\u{113}', ['\u{112}', '\0', '\0']),
+        ('\u{115}', ['\u{114}', '\0', '\0']), ('\u{117}', ['\u{116}', '\0', '\0']), ('\u{119}',
+        ['\u{118}', '\0', '\0']), ('\u{11b}', ['\u{11a}', '\0', '\0']), ('\u{11d}', ['\u{11c}',
+        '\0', '\0']), ('\u{11f}', ['\u{11e}', '\0', '\0']), ('\u{121}', ['\u{120}', '\0', '\0']),
+        ('\u{123}', ['\u{122}', '\0', '\0']), ('\u{125}', ['\u{124}', '\0', '\0']), ('\u{127}',
+        ['\u{126}', '\0', '\0']), ('\u{129}', ['\u{128}', '\0', '\0']), ('\u{12b}', ['\u{12a}',
+        '\0', '\0']), ('\u{12d}', ['\u{12c}', '\0', '\0']), ('\u{12f}', ['\u{12e}', '\0', '\0']),
+        ('\u{131}', ['\u{49}', '\0', '\0']), ('\u{133}', ['\u{132}', '\0', '\0']), ('\u{135}',
+        ['\u{134}', '\0', '\0']), ('\u{137}', ['\u{136}', '\0', '\0']), ('\u{13a}', ['\u{139}',
+        '\0', '\0']), ('\u{13c}', ['\u{13b}', '\0', '\0']), ('\u{13e}', ['\u{13d}', '\0', '\0']),
+        ('\u{140}', ['\u{13f}', '\0', '\0']), ('\u{142}', ['\u{141}', '\0', '\0']), ('\u{144}',
+        ['\u{143}', '\0', '\0']), ('\u{146}', ['\u{145}', '\0', '\0']), ('\u{148}', ['\u{147}',
+        '\0', '\0']), ('\u{149}', ['\u{2bc}', '\u{4e}', '\0']), ('\u{14b}', ['\u{14a}', '\0',
+        '\0']), ('\u{14d}', ['\u{14c}', '\0', '\0']), ('\u{14f}', ['\u{14e}', '\0', '\0']),
+        ('\u{151}', ['\u{150}', '\0', '\0']), ('\u{153}', ['\u{152}', '\0', '\0']), ('\u{155}',
+        ['\u{154}', '\0', '\0']), ('\u{157}', ['\u{156}', '\0', '\0']), ('\u{159}', ['\u{158}',
+        '\0', '\0']), ('\u{15b}', ['\u{15a}', '\0', '\0']), ('\u{15d}', ['\u{15c}', '\0', '\0']),
+        ('\u{15f}', ['\u{15e}', '\0', '\0']), ('\u{161}', ['\u{160}', '\0', '\0']), ('\u{163}',
+        ['\u{162}', '\0', '\0']), ('\u{165}', ['\u{164}', '\0', '\0']), ('\u{167}', ['\u{166}',
+        '\0', '\0']), ('\u{169}', ['\u{168}', '\0', '\0']), ('\u{16b}', ['\u{16a}', '\0', '\0']),
+        ('\u{16d}', ['\u{16c}', '\0', '\0']), ('\u{16f}', ['\u{16e}', '\0', '\0']), ('\u{171}',
+        ['\u{170}', '\0', '\0']), ('\u{173}', ['\u{172}', '\0', '\0']), ('\u{175}', ['\u{174}',
+        '\0', '\0']), ('\u{177}', ['\u{176}', '\0', '\0']), ('\u{17a}', ['\u{179}', '\0', '\0']),
+        ('\u{17c}', ['\u{17b}', '\0', '\0']), ('\u{17e}', ['\u{17d}', '\0', '\0']), ('\u{17f}',
+        ['\u{53}', '\0', '\0']), ('\u{180}', ['\u{243}', '\0', '\0']), ('\u{183}', ['\u{182}', '\0',
+        '\0']), ('\u{185}', ['\u{184}', '\0', '\0']), ('\u{188}', ['\u{187}', '\0', '\0']),
+        ('\u{18c}', ['\u{18b}', '\0', '\0']), ('\u{192}', ['\u{191}', '\0', '\0']), ('\u{195}',
+        ['\u{1f6}', '\0', '\0']), ('\u{199}', ['\u{198}', '\0', '\0']), ('\u{19a}', ['\u{23d}',
+        '\0', '\0']), ('\u{19e}', ['\u{220}', '\0', '\0']), ('\u{1a1}', ['\u{1a0}', '\0', '\0']),
+        ('\u{1a3}', ['\u{1a2}', '\0', '\0']), ('\u{1a5}', ['\u{1a4}', '\0', '\0']), ('\u{1a8}',
+        ['\u{1a7}', '\0', '\0']), ('\u{1ad}', ['\u{1ac}', '\0', '\0']), ('\u{1b0}', ['\u{1af}',
+        '\0', '\0']), ('\u{1b4}', ['\u{1b3}', '\0', '\0']), ('\u{1b6}', ['\u{1b5}', '\0', '\0']),
+        ('\u{1b9}', ['\u{1b8}', '\0', '\0']), ('\u{1bd}', ['\u{1bc}', '\0', '\0']), ('\u{1bf}',
+        ['\u{1f7}', '\0', '\0']), ('\u{1c4}', ['\u{1c5}', '\0', '\0']), ('\u{1c5}', ['\u{1c5}',
+        '\0', '\0']), ('\u{1c6}', ['\u{1c5}', '\0', '\0']), ('\u{1c7}', ['\u{1c8}', '\0', '\0']),
+        ('\u{1c8}', ['\u{1c8}', '\0', '\0']), ('\u{1c9}', ['\u{1c8}', '\0', '\0']), ('\u{1ca}',
+        ['\u{1cb}', '\0', '\0']), ('\u{1cb}', ['\u{1cb}', '\0', '\0']), ('\u{1cc}', ['\u{1cb}',
+        '\0', '\0']), ('\u{1ce}', ['\u{1cd}', '\0', '\0']), ('\u{1d0}', ['\u{1cf}', '\0', '\0']),
+        ('\u{1d2}', ['\u{1d1}', '\0', '\0']), ('\u{1d4}', ['\u{1d3}', '\0', '\0']), ('\u{1d6}',
+        ['\u{1d5}', '\0', '\0']), ('\u{1d8}', ['\u{1d7}', '\0', '\0']), ('\u{1da}', ['\u{1d9}',
+        '\0', '\0']), ('\u{1dc}', ['\u{1db}', '\0', '\0']), ('\u{1dd}', ['\u{18e}', '\0', '\0']),
+        ('\u{1df}', ['\u{1de}', '\0', '\0']), ('\u{1e1}', ['\u{1e0}', '\0', '\0']), ('\u{1e3}',
+        ['\u{1e2}', '\0', '\0']), ('\u{1e5}', ['\u{1e4}', '\0', '\0']), ('\u{1e7}', ['\u{1e6}',
+        '\0', '\0']), ('\u{1e9}', ['\u{1e8}', '\0', '\0']), ('\u{1eb}', ['\u{1ea}', '\0', '\0']),
+        ('\u{1ed}', ['\u{1ec}', '\0', '\0']), ('\u{1ef}', ['\u{1ee}', '\0', '\0']), ('\u{1f0}',
+        ['\u{4a}', '\u{30c}', '\0']), ('\u{1f1}', ['\u{1f2}', '\0', '\0']), ('\u{1f2}', ['\u{1f2}',
+        '\0', '\0']), ('\u{1f3}', ['\u{1f2}', '\0', '\0']), ('\u{1f5}', ['\u{1f4}', '\0', '\0']),
+        ('\u{1f9}', ['\u{1f8}', '\0', '\0']), ('\u{1fb}', ['\u{1fa}', '\0', '\0']), ('\u{1fd}',
+        ['\u{1fc}', '\0', '\0']), ('\u{1ff}', ['\u{1fe}', '\0', '\0']), ('\u{201}', ['\u{200}',
+        '\0', '\0']), ('\u{203}', ['\u{202}', '\0', '\0']), ('\u{205}', ['\u{204}', '\0', '\0']),
+        ('\u{207}', ['\u{206}', '\0', '\0']), ('\u{209}', ['\u{208}', '\0', '\0']), ('\u{20b}',
+        ['\u{20a}', '\0', '\0']), ('\u{20d}', ['\u{20c}', '\0', '\0']), ('\u{20f}', ['\u{20e}',
+        '\0', '\0']), ('\u{211}', ['\u{210}', '\0', '\0']), ('\u{213}', ['\u{212}', '\0', '\0']),
+        ('\u{215}', ['\u{214}', '\0', '\0']), ('\u{217}', ['\u{216}', '\0', '\0']), ('\u{219}',
+        ['\u{218}', '\0', '\0']), ('\u{21b}', ['\u{21a}', '\0', '\0']), ('\u{21d}', ['\u{21c}',
+        '\0', '\0']), ('\u{21f}', ['\u{21e}', '\0', '\0']), ('\u{223}', ['\u{222}', '\0', '\0']),
+        ('\u{225}', ['\u{224}', '\0', '\0']), ('\u{227}', ['\u{226}', '\0', '\0']), ('\u{229}',
+        ['\u{228}', '\0', '\0']), ('\u{22b}', ['\u{22a}', '\0', '\0']), ('\u{22d}', ['\u{22c}',
+        '\0', '\0']), ('\u{22f}', ['\u{22e}', '\0', '\0']), ('\u{231}', ['\u{230}', '\0', '\0']),
+        ('\u{233}', ['\u{232}', '\0', '\0']), ('\u{23c}', ['\u{23b}', '\0', '\0']), ('\u{23f}',
+        ['\u{2c7e}', '\0', '\0']), ('\u{240}', ['\u{2c7f}', '\0', '\0']), ('\u{242}', ['\u{241}',
+        '\0', '\0']), ('\u{247}', ['\u{246}', '\0', '\0']), ('\u{249}', ['\u{248}', '\0', '\0']),
+        ('\u{24b}', ['\u{24a}', '\0', '\0']), ('\u{24d}', ['\u{24c}', '\0', '\0']), ('\u{24f}',
+        ['\u{24e}', '\0', '\0']), ('\u{250}', ['\u{2c6f}', '\0', '\0']), ('\u{251}', ['\u{2c6d}',
+        '\0', '\0']), ('\u{252}', ['\u{2c70}', '\0', '\0']), ('\u{253}', ['\u{181}', '\0', '\0']),
+        ('\u{254}', ['\u{186}', '\0', '\0']), ('\u{256}', ['\u{189}', '\0', '\0']), ('\u{257}',
+        ['\u{18a}', '\0', '\0']), ('\u{259}', ['\u{18f}', '\0', '\0']), ('\u{25b}', ['\u{190}',
+        '\0', '\0']), ('\u{25c}', ['\u{a7ab}', '\0', '\0']), ('\u{260}', ['\u{193}', '\0', '\0']),
+        ('\u{261}', ['\u{a7ac}', '\0', '\0']), ('\u{263}', ['\u{194}', '\0', '\0']), ('\u{265}',
+        ['\u{a78d}', '\0', '\0']), ('\u{266}', ['\u{a7aa}', '\0', '\0']), ('\u{268}', ['\u{197}',
+        '\0', '\0']), ('\u{269}', ['\u{196}', '\0', '\0']), ('\u{26b}', ['\u{2c62}', '\0', '\0']),
+        ('\u{26c}', ['\u{a7ad}', '\0', '\0']), ('\u{26f}', ['\u{19c}', '\0', '\0']), ('\u{271}',
+        ['\u{2c6e}', '\0', '\0']), ('\u{272}', ['\u{19d}', '\0', '\0']), ('\u{275}', ['\u{19f}',
+        '\0', '\0']), ('\u{27d}', ['\u{2c64}', '\0', '\0']), ('\u{280}', ['\u{1a6}', '\0', '\0']),
+        ('\u{283}', ['\u{1a9}', '\0', '\0']), ('\u{287}', ['\u{a7b1}', '\0', '\0']), ('\u{288}',
+        ['\u{1ae}', '\0', '\0']), ('\u{289}', ['\u{244}', '\0', '\0']), ('\u{28a}', ['\u{1b1}',
+        '\0', '\0']), ('\u{28b}', ['\u{1b2}', '\0', '\0']), ('\u{28c}', ['\u{245}', '\0', '\0']),
+        ('\u{292}', ['\u{1b7}', '\0', '\0']), ('\u{29e}', ['\u{a7b0}', '\0', '\0']), ('\u{345}',
+        ['\u{399}', '\0', '\0']), ('\u{371}', ['\u{370}', '\0', '\0']), ('\u{373}', ['\u{372}',
+        '\0', '\0']), ('\u{377}', ['\u{376}', '\0', '\0']), ('\u{37b}', ['\u{3fd}', '\0', '\0']),
+        ('\u{37c}', ['\u{3fe}', '\0', '\0']), ('\u{37d}', ['\u{3ff}', '\0', '\0']), ('\u{390}',
+        ['\u{399}', '\u{308}', '\u{301}']), ('\u{3ac}', ['\u{386}', '\0', '\0']), ('\u{3ad}',
+        ['\u{388}', '\0', '\0']), ('\u{3ae}', ['\u{389}', '\0', '\0']), ('\u{3af}', ['\u{38a}',
+        '\0', '\0']), ('\u{3b0}', ['\u{3a5}', '\u{308}', '\u{301}']), ('\u{3b1}', ['\u{391}', '\0',
+        '\0']), ('\u{3b2}', ['\u{392}', '\0', '\0']), ('\u{3b3}', ['\u{393}', '\0', '\0']),
+        ('\u{3b4}', ['\u{394}', '\0', '\0']), ('\u{3b5}', ['\u{395}', '\0', '\0']), ('\u{3b6}',
+        ['\u{396}', '\0', '\0']), ('\u{3b7}', ['\u{397}', '\0', '\0']), ('\u{3b8}', ['\u{398}',
+        '\0', '\0']), ('\u{3b9}', ['\u{399}', '\0', '\0']), ('\u{3ba}', ['\u{39a}', '\0', '\0']),
+        ('\u{3bb}', ['\u{39b}', '\0', '\0']), ('\u{3bc}', ['\u{39c}', '\0', '\0']), ('\u{3bd}',
+        ['\u{39d}', '\0', '\0']), ('\u{3be}', ['\u{39e}', '\0', '\0']), ('\u{3bf}', ['\u{39f}',
+        '\0', '\0']), ('\u{3c0}', ['\u{3a0}', '\0', '\0']), ('\u{3c1}', ['\u{3a1}', '\0', '\0']),
+        ('\u{3c2}', ['\u{3a3}', '\0', '\0']), ('\u{3c3}', ['\u{3a3}', '\0', '\0']), ('\u{3c4}',
+        ['\u{3a4}', '\0', '\0']), ('\u{3c5}', ['\u{3a5}', '\0', '\0']), ('\u{3c6}', ['\u{3a6}',
+        '\0', '\0']), ('\u{3c7}', ['\u{3a7}', '\0', '\0']), ('\u{3c8}', ['\u{3a8}', '\0', '\0']),
+        ('\u{3c9}', ['\u{3a9}', '\0', '\0']), ('\u{3ca}', ['\u{3aa}', '\0', '\0']), ('\u{3cb}',
+        ['\u{3ab}', '\0', '\0']), ('\u{3cc}', ['\u{38c}', '\0', '\0']), ('\u{3cd}', ['\u{38e}',
+        '\0', '\0']), ('\u{3ce}', ['\u{38f}', '\0', '\0']), ('\u{3d0}', ['\u{392}', '\0', '\0']),
+        ('\u{3d1}', ['\u{398}', '\0', '\0']), ('\u{3d5}', ['\u{3a6}', '\0', '\0']), ('\u{3d6}',
+        ['\u{3a0}', '\0', '\0']), ('\u{3d7}', ['\u{3cf}', '\0', '\0']), ('\u{3d9}', ['\u{3d8}',
+        '\0', '\0']), ('\u{3db}', ['\u{3da}', '\0', '\0']), ('\u{3dd}', ['\u{3dc}', '\0', '\0']),
+        ('\u{3df}', ['\u{3de}', '\0', '\0']), ('\u{3e1}', ['\u{3e0}', '\0', '\0']), ('\u{3e3}',
+        ['\u{3e2}', '\0', '\0']), ('\u{3e5}', ['\u{3e4}', '\0', '\0']), ('\u{3e7}', ['\u{3e6}',
+        '\0', '\0']), ('\u{3e9}', ['\u{3e8}', '\0', '\0']), ('\u{3eb}', ['\u{3ea}', '\0', '\0']),
+        ('\u{3ed}', ['\u{3ec}', '\0', '\0']), ('\u{3ef}', ['\u{3ee}', '\0', '\0']), ('\u{3f0}',
+        ['\u{39a}', '\0', '\0']), ('\u{3f1}', ['\u{3a1}', '\0', '\0']), ('\u{3f2}', ['\u{3f9}',
+        '\0', '\0']), ('\u{3f3}', ['\u{37f}', '\0', '\0']), ('\u{3f5}', ['\u{395}', '\0', '\0']),
+        ('\u{3f8}', ['\u{3f7}', '\0', '\0']), ('\u{3fb}', ['\u{3fa}', '\0', '\0']), ('\u{430}',
+        ['\u{410}', '\0', '\0']), ('\u{431}', ['\u{411}', '\0', '\0']), ('\u{432}', ['\u{412}',
+        '\0', '\0']), ('\u{433}', ['\u{413}', '\0', '\0']), ('\u{434}', ['\u{414}', '\0', '\0']),
+        ('\u{435}', ['\u{415}', '\0', '\0']), ('\u{436}', ['\u{416}', '\0', '\0']), ('\u{437}',
+        ['\u{417}', '\0', '\0']), ('\u{438}', ['\u{418}', '\0', '\0']), ('\u{439}', ['\u{419}',
+        '\0', '\0']), ('\u{43a}', ['\u{41a}', '\0', '\0']), ('\u{43b}', ['\u{41b}', '\0', '\0']),
+        ('\u{43c}', ['\u{41c}', '\0', '\0']), ('\u{43d}', ['\u{41d}', '\0', '\0']), ('\u{43e}',
+        ['\u{41e}', '\0', '\0']), ('\u{43f}', ['\u{41f}', '\0', '\0']), ('\u{440}', ['\u{420}',
+        '\0', '\0']), ('\u{441}', ['\u{421}', '\0', '\0']), ('\u{442}', ['\u{422}', '\0', '\0']),
+        ('\u{443}', ['\u{423}', '\0', '\0']), ('\u{444}', ['\u{424}', '\0', '\0']), ('\u{445}',
+        ['\u{425}', '\0', '\0']), ('\u{446}', ['\u{426}', '\0', '\0']), ('\u{447}', ['\u{427}',
+        '\0', '\0']), ('\u{448}', ['\u{428}', '\0', '\0']), ('\u{449}', ['\u{429}', '\0', '\0']),
+        ('\u{44a}', ['\u{42a}', '\0', '\0']), ('\u{44b}', ['\u{42b}', '\0', '\0']), ('\u{44c}',
+        ['\u{42c}', '\0', '\0']), ('\u{44d}', ['\u{42d}', '\0', '\0']), ('\u{44e}', ['\u{42e}',
+        '\0', '\0']), ('\u{44f}', ['\u{42f}', '\0', '\0']), ('\u{450}', ['\u{400}', '\0', '\0']),
+        ('\u{451}', ['\u{401}', '\0', '\0']), ('\u{452}', ['\u{402}', '\0', '\0']), ('\u{453}',
+        ['\u{403}', '\0', '\0']), ('\u{454}', ['\u{404}', '\0', '\0']), ('\u{455}', ['\u{405}',
+        '\0', '\0']), ('\u{456}', ['\u{406}', '\0', '\0']), ('\u{457}', ['\u{407}', '\0', '\0']),
+        ('\u{458}', ['\u{408}', '\0', '\0']), ('\u{459}', ['\u{409}', '\0', '\0']), ('\u{45a}',
+        ['\u{40a}', '\0', '\0']), ('\u{45b}', ['\u{40b}', '\0', '\0']), ('\u{45c}', ['\u{40c}',
+        '\0', '\0']), ('\u{45d}', ['\u{40d}', '\0', '\0']), ('\u{45e}', ['\u{40e}', '\0', '\0']),
+        ('\u{45f}', ['\u{40f}', '\0', '\0']), ('\u{461}', ['\u{460}', '\0', '\0']), ('\u{463}',
+        ['\u{462}', '\0', '\0']), ('\u{465}', ['\u{464}', '\0', '\0']), ('\u{467}', ['\u{466}',
+        '\0', '\0']), ('\u{469}', ['\u{468}', '\0', '\0']), ('\u{46b}', ['\u{46a}', '\0', '\0']),
+        ('\u{46d}', ['\u{46c}', '\0', '\0']), ('\u{46f}', ['\u{46e}', '\0', '\0']), ('\u{471}',
+        ['\u{470}', '\0', '\0']), ('\u{473}', ['\u{472}', '\0', '\0']), ('\u{475}', ['\u{474}',
+        '\0', '\0']), ('\u{477}', ['\u{476}', '\0', '\0']), ('\u{479}', ['\u{478}', '\0', '\0']),
+        ('\u{47b}', ['\u{47a}', '\0', '\0']), ('\u{47d}', ['\u{47c}', '\0', '\0']), ('\u{47f}',
+        ['\u{47e}', '\0', '\0']), ('\u{481}', ['\u{480}', '\0', '\0']), ('\u{48b}', ['\u{48a}',
+        '\0', '\0']), ('\u{48d}', ['\u{48c}', '\0', '\0']), ('\u{48f}', ['\u{48e}', '\0', '\0']),
+        ('\u{491}', ['\u{490}', '\0', '\0']), ('\u{493}', ['\u{492}', '\0', '\0']), ('\u{495}',
+        ['\u{494}', '\0', '\0']), ('\u{497}', ['\u{496}', '\0', '\0']), ('\u{499}', ['\u{498}',
+        '\0', '\0']), ('\u{49b}', ['\u{49a}', '\0', '\0']), ('\u{49d}', ['\u{49c}', '\0', '\0']),
+        ('\u{49f}', ['\u{49e}', '\0', '\0']), ('\u{4a1}', ['\u{4a0}', '\0', '\0']), ('\u{4a3}',
+        ['\u{4a2}', '\0', '\0']), ('\u{4a5}', ['\u{4a4}', '\0', '\0']), ('\u{4a7}', ['\u{4a6}',
+        '\0', '\0']), ('\u{4a9}', ['\u{4a8}', '\0', '\0']), ('\u{4ab}', ['\u{4aa}', '\0', '\0']),
+        ('\u{4ad}', ['\u{4ac}', '\0', '\0']), ('\u{4af}', ['\u{4ae}', '\0', '\0']), ('\u{4b1}',
+        ['\u{4b0}', '\0', '\0']), ('\u{4b3}', ['\u{4b2}', '\0', '\0']), ('\u{4b5}', ['\u{4b4}',
+        '\0', '\0']), ('\u{4b7}', ['\u{4b6}', '\0', '\0']), ('\u{4b9}', ['\u{4b8}', '\0', '\0']),
+        ('\u{4bb}', ['\u{4ba}', '\0', '\0']), ('\u{4bd}', ['\u{4bc}', '\0', '\0']), ('\u{4bf}',
+        ['\u{4be}', '\0', '\0']), ('\u{4c2}', ['\u{4c1}', '\0', '\0']), ('\u{4c4}', ['\u{4c3}',
+        '\0', '\0']), ('\u{4c6}', ['\u{4c5}', '\0', '\0']), ('\u{4c8}', ['\u{4c7}', '\0', '\0']),
+        ('\u{4ca}', ['\u{4c9}', '\0', '\0']), ('\u{4cc}', ['\u{4cb}', '\0', '\0']), ('\u{4ce}',
+        ['\u{4cd}', '\0', '\0']), ('\u{4cf}', ['\u{4c0}', '\0', '\0']), ('\u{4d1}', ['\u{4d0}',
+        '\0', '\0']), ('\u{4d3}', ['\u{4d2}', '\0', '\0']), ('\u{4d5}', ['\u{4d4}', '\0', '\0']),
+        ('\u{4d7}', ['\u{4d6}', '\0', '\0']), ('\u{4d9}', ['\u{4d8}', '\0', '\0']), ('\u{4db}',
+        ['\u{4da}', '\0', '\0']), ('\u{4dd}', ['\u{4dc}', '\0', '\0']), ('\u{4df}', ['\u{4de}',
+        '\0', '\0']), ('\u{4e1}', ['\u{4e0}', '\0', '\0']), ('\u{4e3}', ['\u{4e2}', '\0', '\0']),
+        ('\u{4e5}', ['\u{4e4}', '\0', '\0']), ('\u{4e7}', ['\u{4e6}', '\0', '\0']), ('\u{4e9}',
+        ['\u{4e8}', '\0', '\0']), ('\u{4eb}', ['\u{4ea}', '\0', '\0']), ('\u{4ed}', ['\u{4ec}',
+        '\0', '\0']), ('\u{4ef}', ['\u{4ee}', '\0', '\0']), ('\u{4f1}', ['\u{4f0}', '\0', '\0']),
+        ('\u{4f3}', ['\u{4f2}', '\0', '\0']), ('\u{4f5}', ['\u{4f4}', '\0', '\0']), ('\u{4f7}',
+        ['\u{4f6}', '\0', '\0']), ('\u{4f9}', ['\u{4f8}', '\0', '\0']), ('\u{4fb}', ['\u{4fa}',
+        '\0', '\0']), ('\u{4fd}', ['\u{4fc}', '\0', '\0']), ('\u{4ff}', ['\u{4fe}', '\0', '\0']),
+        ('\u{501}', ['\u{500}', '\0', '\0']), ('\u{503}', ['\u{502}', '\0', '\0']), ('\u{505}',
+        ['\u{504}', '\0', '\0']), ('\u{507}', ['\u{506}', '\0', '\0']), ('\u{509}', ['\u{508}',
+        '\0', '\0']), ('\u{50b}', ['\u{50a}', '\0', '\0']), ('\u{50d}', ['\u{50c}', '\0', '\0']),
+        ('\u{50f}', ['\u{50e}', '\0', '\0']), ('\u{511}', ['\u{510}', '\0', '\0']), ('\u{513}',
+        ['\u{512}', '\0', '\0']), ('\u{515}', ['\u{514}', '\0', '\0']), ('\u{517}', ['\u{516}',
+        '\0', '\0']), ('\u{519}', ['\u{518}', '\0', '\0']), ('\u{51b}', ['\u{51a}', '\0', '\0']),
+        ('\u{51d}', ['\u{51c}', '\0', '\0']), ('\u{51f}', ['\u{51e}', '\0', '\0']), ('\u{521}',
+        ['\u{520}', '\0', '\0']), ('\u{523}', ['\u{522}', '\0', '\0']), ('\u{525}', ['\u{524}',
+        '\0', '\0']), ('\u{527}', ['\u{526}', '\0', '\0']), ('\u{529}', ['\u{528}', '\0', '\0']),
+        ('\u{52b}', ['\u{52a}', '\0', '\0']), ('\u{52d}', ['\u{52c}', '\0', '\0']), ('\u{52f}',
+        ['\u{52e}', '\0', '\0']), ('\u{561}', ['\u{531}', '\0', '\0']), ('\u{562}', ['\u{532}',
+        '\0', '\0']), ('\u{563}', ['\u{533}', '\0', '\0']), ('\u{564}', ['\u{534}', '\0', '\0']),
+        ('\u{565}', ['\u{535}', '\0', '\0']), ('\u{566}', ['\u{536}', '\0', '\0']), ('\u{567}',
+        ['\u{537}', '\0', '\0']), ('\u{568}', ['\u{538}', '\0', '\0']), ('\u{569}', ['\u{539}',
+        '\0', '\0']), ('\u{56a}', ['\u{53a}', '\0', '\0']), ('\u{56b}', ['\u{53b}', '\0', '\0']),
+        ('\u{56c}', ['\u{53c}', '\0', '\0']), ('\u{56d}', ['\u{53d}', '\0', '\0']), ('\u{56e}',
+        ['\u{53e}', '\0', '\0']), ('\u{56f}', ['\u{53f}', '\0', '\0']), ('\u{570}', ['\u{540}',
+        '\0', '\0']), ('\u{571}', ['\u{541}', '\0', '\0']), ('\u{572}', ['\u{542}', '\0', '\0']),
+        ('\u{573}', ['\u{543}', '\0', '\0']), ('\u{574}', ['\u{544}', '\0', '\0']), ('\u{575}',
+        ['\u{545}', '\0', '\0']), ('\u{576}', ['\u{546}', '\0', '\0']), ('\u{577}', ['\u{547}',
+        '\0', '\0']), ('\u{578}', ['\u{548}', '\0', '\0']), ('\u{579}', ['\u{549}', '\0', '\0']),
+        ('\u{57a}', ['\u{54a}', '\0', '\0']), ('\u{57b}', ['\u{54b}', '\0', '\0']), ('\u{57c}',
+        ['\u{54c}', '\0', '\0']), ('\u{57d}', ['\u{54d}', '\0', '\0']), ('\u{57e}', ['\u{54e}',
+        '\0', '\0']), ('\u{57f}', ['\u{54f}', '\0', '\0']), ('\u{580}', ['\u{550}', '\0', '\0']),
+        ('\u{581}', ['\u{551}', '\0', '\0']), ('\u{582}', ['\u{552}', '\0', '\0']), ('\u{583}',
+        ['\u{553}', '\0', '\0']), ('\u{584}', ['\u{554}', '\0', '\0']), ('\u{585}', ['\u{555}',
+        '\0', '\0']), ('\u{586}', ['\u{556}', '\0', '\0']), ('\u{587}', ['\u{535}', '\u{582}',
+        '\0']), ('\u{1d79}', ['\u{a77d}', '\0', '\0']), ('\u{1d7d}', ['\u{2c63}', '\0', '\0']),
+        ('\u{1e01}', ['\u{1e00}', '\0', '\0']), ('\u{1e03}', ['\u{1e02}', '\0', '\0']), ('\u{1e05}',
+        ['\u{1e04}', '\0', '\0']), ('\u{1e07}', ['\u{1e06}', '\0', '\0']), ('\u{1e09}', ['\u{1e08}',
+        '\0', '\0']), ('\u{1e0b}', ['\u{1e0a}', '\0', '\0']), ('\u{1e0d}', ['\u{1e0c}', '\0',
+        '\0']), ('\u{1e0f}', ['\u{1e0e}', '\0', '\0']), ('\u{1e11}', ['\u{1e10}', '\0', '\0']),
+        ('\u{1e13}', ['\u{1e12}', '\0', '\0']), ('\u{1e15}', ['\u{1e14}', '\0', '\0']), ('\u{1e17}',
+        ['\u{1e16}', '\0', '\0']), ('\u{1e19}', ['\u{1e18}', '\0', '\0']), ('\u{1e1b}', ['\u{1e1a}',
+        '\0', '\0']), ('\u{1e1d}', ['\u{1e1c}', '\0', '\0']), ('\u{1e1f}', ['\u{1e1e}', '\0',
+        '\0']), ('\u{1e21}', ['\u{1e20}', '\0', '\0']), ('\u{1e23}', ['\u{1e22}', '\0', '\0']),
+        ('\u{1e25}', ['\u{1e24}', '\0', '\0']), ('\u{1e27}', ['\u{1e26}', '\0', '\0']), ('\u{1e29}',
+        ['\u{1e28}', '\0', '\0']), ('\u{1e2b}', ['\u{1e2a}', '\0', '\0']), ('\u{1e2d}', ['\u{1e2c}',
+        '\0', '\0']), ('\u{1e2f}', ['\u{1e2e}', '\0', '\0']), ('\u{1e31}', ['\u{1e30}', '\0',
+        '\0']), ('\u{1e33}', ['\u{1e32}', '\0', '\0']), ('\u{1e35}', ['\u{1e34}', '\0', '\0']),
+        ('\u{1e37}', ['\u{1e36}', '\0', '\0']), ('\u{1e39}', ['\u{1e38}', '\0', '\0']), ('\u{1e3b}',
+        ['\u{1e3a}', '\0', '\0']), ('\u{1e3d}', ['\u{1e3c}', '\0', '\0']), ('\u{1e3f}', ['\u{1e3e}',
+        '\0', '\0']), ('\u{1e41}', ['\u{1e40}', '\0', '\0']), ('\u{1e43}', ['\u{1e42}', '\0',
+        '\0']), ('\u{1e45}', ['\u{1e44}', '\0', '\0']), ('\u{1e47}', ['\u{1e46}', '\0', '\0']),
+        ('\u{1e49}', ['\u{1e48}', '\0', '\0']), ('\u{1e4b}', ['\u{1e4a}', '\0', '\0']), ('\u{1e4d}',
+        ['\u{1e4c}', '\0', '\0']), ('\u{1e4f}', ['\u{1e4e}', '\0', '\0']), ('\u{1e51}', ['\u{1e50}',
+        '\0', '\0']), ('\u{1e53}', ['\u{1e52}', '\0', '\0']), ('\u{1e55}', ['\u{1e54}', '\0',
+        '\0']), ('\u{1e57}', ['\u{1e56}', '\0', '\0']), ('\u{1e59}', ['\u{1e58}', '\0', '\0']),
+        ('\u{1e5b}', ['\u{1e5a}', '\0', '\0']), ('\u{1e5d}', ['\u{1e5c}', '\0', '\0']), ('\u{1e5f}',
+        ['\u{1e5e}', '\0', '\0']), ('\u{1e61}', ['\u{1e60}', '\0', '\0']), ('\u{1e63}', ['\u{1e62}',
+        '\0', '\0']), ('\u{1e65}', ['\u{1e64}', '\0', '\0']), ('\u{1e67}', ['\u{1e66}', '\0',
+        '\0']), ('\u{1e69}', ['\u{1e68}', '\0', '\0']), ('\u{1e6b}', ['\u{1e6a}', '\0', '\0']),
+        ('\u{1e6d}', ['\u{1e6c}', '\0', '\0']), ('\u{1e6f}', ['\u{1e6e}', '\0', '\0']), ('\u{1e71}',
+        ['\u{1e70}', '\0', '\0']), ('\u{1e73}', ['\u{1e72}', '\0', '\0']), ('\u{1e75}', ['\u{1e74}',
+        '\0', '\0']), ('\u{1e77}', ['\u{1e76}', '\0', '\0']), ('\u{1e79}', ['\u{1e78}', '\0',
+        '\0']), ('\u{1e7b}', ['\u{1e7a}', '\0', '\0']), ('\u{1e7d}', ['\u{1e7c}', '\0', '\0']),
+        ('\u{1e7f}', ['\u{1e7e}', '\0', '\0']), ('\u{1e81}', ['\u{1e80}', '\0', '\0']), ('\u{1e83}',
+        ['\u{1e82}', '\0', '\0']), ('\u{1e85}', ['\u{1e84}', '\0', '\0']), ('\u{1e87}', ['\u{1e86}',
+        '\0', '\0']), ('\u{1e89}', ['\u{1e88}', '\0', '\0']), ('\u{1e8b}', ['\u{1e8a}', '\0',
+        '\0']), ('\u{1e8d}', ['\u{1e8c}', '\0', '\0']), ('\u{1e8f}', ['\u{1e8e}', '\0', '\0']),
+        ('\u{1e91}', ['\u{1e90}', '\0', '\0']), ('\u{1e93}', ['\u{1e92}', '\0', '\0']), ('\u{1e95}',
+        ['\u{1e94}', '\0', '\0']), ('\u{1e96}', ['\u{48}', '\u{331}', '\0']), ('\u{1e97}',
+        ['\u{54}', '\u{308}', '\0']), ('\u{1e98}', ['\u{57}', '\u{30a}', '\0']), ('\u{1e99}',
+        ['\u{59}', '\u{30a}', '\0']), ('\u{1e9a}', ['\u{41}', '\u{2be}', '\0']), ('\u{1e9b}',
+        ['\u{1e60}', '\0', '\0']), ('\u{1ea1}', ['\u{1ea0}', '\0', '\0']), ('\u{1ea3}', ['\u{1ea2}',
+        '\0', '\0']), ('\u{1ea5}', ['\u{1ea4}', '\0', '\0']), ('\u{1ea7}', ['\u{1ea6}', '\0',
+        '\0']), ('\u{1ea9}', ['\u{1ea8}', '\0', '\0']), ('\u{1eab}', ['\u{1eaa}', '\0', '\0']),
+        ('\u{1ead}', ['\u{1eac}', '\0', '\0']), ('\u{1eaf}', ['\u{1eae}', '\0', '\0']), ('\u{1eb1}',
+        ['\u{1eb0}', '\0', '\0']), ('\u{1eb3}', ['\u{1eb2}', '\0', '\0']), ('\u{1eb5}', ['\u{1eb4}',
+        '\0', '\0']), ('\u{1eb7}', ['\u{1eb6}', '\0', '\0']), ('\u{1eb9}', ['\u{1eb8}', '\0',
+        '\0']), ('\u{1ebb}', ['\u{1eba}', '\0', '\0']), ('\u{1ebd}', ['\u{1ebc}', '\0', '\0']),
+        ('\u{1ebf}', ['\u{1ebe}', '\0', '\0']), ('\u{1ec1}', ['\u{1ec0}', '\0', '\0']), ('\u{1ec3}',
+        ['\u{1ec2}', '\0', '\0']), ('\u{1ec5}', ['\u{1ec4}', '\0', '\0']), ('\u{1ec7}', ['\u{1ec6}',
+        '\0', '\0']), ('\u{1ec9}', ['\u{1ec8}', '\0', '\0']), ('\u{1ecb}', ['\u{1eca}', '\0',
+        '\0']), ('\u{1ecd}', ['\u{1ecc}', '\0', '\0']), ('\u{1ecf}', ['\u{1ece}', '\0', '\0']),
+        ('\u{1ed1}', ['\u{1ed0}', '\0', '\0']), ('\u{1ed3}', ['\u{1ed2}', '\0', '\0']), ('\u{1ed5}',
+        ['\u{1ed4}', '\0', '\0']), ('\u{1ed7}', ['\u{1ed6}', '\0', '\0']), ('\u{1ed9}', ['\u{1ed8}',
+        '\0', '\0']), ('\u{1edb}', ['\u{1eda}', '\0', '\0']), ('\u{1edd}', ['\u{1edc}', '\0',
+        '\0']), ('\u{1edf}', ['\u{1ede}', '\0', '\0']), ('\u{1ee1}', ['\u{1ee0}', '\0', '\0']),
+        ('\u{1ee3}', ['\u{1ee2}', '\0', '\0']), ('\u{1ee5}', ['\u{1ee4}', '\0', '\0']), ('\u{1ee7}',
+        ['\u{1ee6}', '\0', '\0']), ('\u{1ee9}', ['\u{1ee8}', '\0', '\0']), ('\u{1eeb}', ['\u{1eea}',
+        '\0', '\0']), ('\u{1eed}', ['\u{1eec}', '\0', '\0']), ('\u{1eef}', ['\u{1eee}', '\0',
+        '\0']), ('\u{1ef1}', ['\u{1ef0}', '\0', '\0']), ('\u{1ef3}', ['\u{1ef2}', '\0', '\0']),
+        ('\u{1ef5}', ['\u{1ef4}', '\0', '\0']), ('\u{1ef7}', ['\u{1ef6}', '\0', '\0']), ('\u{1ef9}',
+        ['\u{1ef8}', '\0', '\0']), ('\u{1efb}', ['\u{1efa}', '\0', '\0']), ('\u{1efd}', ['\u{1efc}',
+        '\0', '\0']), ('\u{1eff}', ['\u{1efe}', '\0', '\0']), ('\u{1f00}', ['\u{1f08}', '\0',
+        '\0']), ('\u{1f01}', ['\u{1f09}', '\0', '\0']), ('\u{1f02}', ['\u{1f0a}', '\0', '\0']),
+        ('\u{1f03}', ['\u{1f0b}', '\0', '\0']), ('\u{1f04}', ['\u{1f0c}', '\0', '\0']), ('\u{1f05}',
+        ['\u{1f0d}', '\0', '\0']), ('\u{1f06}', ['\u{1f0e}', '\0', '\0']), ('\u{1f07}', ['\u{1f0f}',
+        '\0', '\0']), ('\u{1f10}', ['\u{1f18}', '\0', '\0']), ('\u{1f11}', ['\u{1f19}', '\0',
+        '\0']), ('\u{1f12}', ['\u{1f1a}', '\0', '\0']), ('\u{1f13}', ['\u{1f1b}', '\0', '\0']),
+        ('\u{1f14}', ['\u{1f1c}', '\0', '\0']), ('\u{1f15}', ['\u{1f1d}', '\0', '\0']), ('\u{1f20}',
+        ['\u{1f28}', '\0', '\0']), ('\u{1f21}', ['\u{1f29}', '\0', '\0']), ('\u{1f22}', ['\u{1f2a}',
+        '\0', '\0']), ('\u{1f23}', ['\u{1f2b}', '\0', '\0']), ('\u{1f24}', ['\u{1f2c}', '\0',
+        '\0']), ('\u{1f25}', ['\u{1f2d}', '\0', '\0']), ('\u{1f26}', ['\u{1f2e}', '\0', '\0']),
+        ('\u{1f27}', ['\u{1f2f}', '\0', '\0']), ('\u{1f30}', ['\u{1f38}', '\0', '\0']), ('\u{1f31}',
+        ['\u{1f39}', '\0', '\0']), ('\u{1f32}', ['\u{1f3a}', '\0', '\0']), ('\u{1f33}', ['\u{1f3b}',
+        '\0', '\0']), ('\u{1f34}', ['\u{1f3c}', '\0', '\0']), ('\u{1f35}', ['\u{1f3d}', '\0',
+        '\0']), ('\u{1f36}', ['\u{1f3e}', '\0', '\0']), ('\u{1f37}', ['\u{1f3f}', '\0', '\0']),
+        ('\u{1f40}', ['\u{1f48}', '\0', '\0']), ('\u{1f41}', ['\u{1f49}', '\0', '\0']), ('\u{1f42}',
+        ['\u{1f4a}', '\0', '\0']), ('\u{1f43}', ['\u{1f4b}', '\0', '\0']), ('\u{1f44}', ['\u{1f4c}',
+        '\0', '\0']), ('\u{1f45}', ['\u{1f4d}', '\0', '\0']), ('\u{1f50}', ['\u{3a5}', '\u{313}',
+        '\0']), ('\u{1f51}', ['\u{1f59}', '\0', '\0']), ('\u{1f52}', ['\u{3a5}', '\u{313}',
+        '\u{300}']), ('\u{1f53}', ['\u{1f5b}', '\0', '\0']), ('\u{1f54}', ['\u{3a5}', '\u{313}',
+        '\u{301}']), ('\u{1f55}', ['\u{1f5d}', '\0', '\0']), ('\u{1f56}', ['\u{3a5}', '\u{313}',
+        '\u{342}']), ('\u{1f57}', ['\u{1f5f}', '\0', '\0']), ('\u{1f60}', ['\u{1f68}', '\0', '\0']),
+        ('\u{1f61}', ['\u{1f69}', '\0', '\0']), ('\u{1f62}', ['\u{1f6a}', '\0', '\0']), ('\u{1f63}',
+        ['\u{1f6b}', '\0', '\0']), ('\u{1f64}', ['\u{1f6c}', '\0', '\0']), ('\u{1f65}', ['\u{1f6d}',
+        '\0', '\0']), ('\u{1f66}', ['\u{1f6e}', '\0', '\0']), ('\u{1f67}', ['\u{1f6f}', '\0',
+        '\0']), ('\u{1f70}', ['\u{1fba}', '\0', '\0']), ('\u{1f71}', ['\u{1fbb}', '\0', '\0']),
+        ('\u{1f72}', ['\u{1fc8}', '\0', '\0']), ('\u{1f73}', ['\u{1fc9}', '\0', '\0']), ('\u{1f74}',
+        ['\u{1fca}', '\0', '\0']), ('\u{1f75}', ['\u{1fcb}', '\0', '\0']), ('\u{1f76}', ['\u{1fda}',
+        '\0', '\0']), ('\u{1f77}', ['\u{1fdb}', '\0', '\0']), ('\u{1f78}', ['\u{1ff8}', '\0',
+        '\0']), ('\u{1f79}', ['\u{1ff9}', '\0', '\0']), ('\u{1f7a}', ['\u{1fea}', '\0', '\0']),
+        ('\u{1f7b}', ['\u{1feb}', '\0', '\0']), ('\u{1f7c}', ['\u{1ffa}', '\0', '\0']), ('\u{1f7d}',
+        ['\u{1ffb}', '\0', '\0']), ('\u{1f80}', ['\u{1f88}', '\0', '\0']), ('\u{1f81}', ['\u{1f89}',
+        '\0', '\0']), ('\u{1f82}', ['\u{1f8a}', '\0', '\0']), ('\u{1f83}', ['\u{1f8b}', '\0',
+        '\0']), ('\u{1f84}', ['\u{1f8c}', '\0', '\0']), ('\u{1f85}', ['\u{1f8d}', '\0', '\0']),
+        ('\u{1f86}', ['\u{1f8e}', '\0', '\0']), ('\u{1f87}', ['\u{1f8f}', '\0', '\0']), ('\u{1f90}',
+        ['\u{1f98}', '\0', '\0']), ('\u{1f91}', ['\u{1f99}', '\0', '\0']), ('\u{1f92}', ['\u{1f9a}',
+        '\0', '\0']), ('\u{1f93}', ['\u{1f9b}', '\0', '\0']), ('\u{1f94}', ['\u{1f9c}', '\0',
+        '\0']), ('\u{1f95}', ['\u{1f9d}', '\0', '\0']), ('\u{1f96}', ['\u{1f9e}', '\0', '\0']),
+        ('\u{1f97}', ['\u{1f9f}', '\0', '\0']), ('\u{1fa0}', ['\u{1fa8}', '\0', '\0']), ('\u{1fa1}',
+        ['\u{1fa9}', '\0', '\0']), ('\u{1fa2}', ['\u{1faa}', '\0', '\0']), ('\u{1fa3}', ['\u{1fab}',
+        '\0', '\0']), ('\u{1fa4}', ['\u{1fac}', '\0', '\0']), ('\u{1fa5}', ['\u{1fad}', '\0',
+        '\0']), ('\u{1fa6}', ['\u{1fae}', '\0', '\0']), ('\u{1fa7}', ['\u{1faf}', '\0', '\0']),
+        ('\u{1fb0}', ['\u{1fb8}', '\0', '\0']), ('\u{1fb1}', ['\u{1fb9}', '\0', '\0']), ('\u{1fb2}',
+        ['\u{1fba}', '\u{345}', '\0']), ('\u{1fb3}', ['\u{1fbc}', '\0', '\0']), ('\u{1fb4}',
+        ['\u{386}', '\u{345}', '\0']), ('\u{1fb6}', ['\u{391}', '\u{342}', '\0']), ('\u{1fb7}',
+        ['\u{391}', '\u{342}', '\u{345}']), ('\u{1fbe}', ['\u{399}', '\0', '\0']), ('\u{1fc2}',
+        ['\u{1fca}', '\u{345}', '\0']), ('\u{1fc3}', ['\u{1fcc}', '\0', '\0']), ('\u{1fc4}',
+        ['\u{389}', '\u{345}', '\0']), ('\u{1fc6}', ['\u{397}', '\u{342}', '\0']), ('\u{1fc7}',
+        ['\u{397}', '\u{342}', '\u{345}']), ('\u{1fd0}', ['\u{1fd8}', '\0', '\0']), ('\u{1fd1}',
+        ['\u{1fd9}', '\0', '\0']), ('\u{1fd2}', ['\u{399}', '\u{308}', '\u{300}']), ('\u{1fd3}',
+        ['\u{399}', '\u{308}', '\u{301}']), ('\u{1fd6}', ['\u{399}', '\u{342}', '\0']), ('\u{1fd7}',
+        ['\u{399}', '\u{308}', '\u{342}']), ('\u{1fe0}', ['\u{1fe8}', '\0', '\0']), ('\u{1fe1}',
+        ['\u{1fe9}', '\0', '\0']), ('\u{1fe2}', ['\u{3a5}', '\u{308}', '\u{300}']), ('\u{1fe3}',
+        ['\u{3a5}', '\u{308}', '\u{301}']), ('\u{1fe4}', ['\u{3a1}', '\u{313}', '\0']), ('\u{1fe5}',
+        ['\u{1fec}', '\0', '\0']), ('\u{1fe6}', ['\u{3a5}', '\u{342}', '\0']), ('\u{1fe7}',
+        ['\u{3a5}', '\u{308}', '\u{342}']), ('\u{1ff2}', ['\u{1ffa}', '\u{345}', '\0']),
+        ('\u{1ff3}', ['\u{1ffc}', '\0', '\0']), ('\u{1ff4}', ['\u{38f}', '\u{345}', '\0']),
+        ('\u{1ff6}', ['\u{3a9}', '\u{342}', '\0']), ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{345}']),
+        ('\u{214e}', ['\u{2132}', '\0', '\0']), ('\u{2170}', ['\u{2160}', '\0', '\0']), ('\u{2171}',
+        ['\u{2161}', '\0', '\0']), ('\u{2172}', ['\u{2162}', '\0', '\0']), ('\u{2173}', ['\u{2163}',
+        '\0', '\0']), ('\u{2174}', ['\u{2164}', '\0', '\0']), ('\u{2175}', ['\u{2165}', '\0',
+        '\0']), ('\u{2176}', ['\u{2166}', '\0', '\0']), ('\u{2177}', ['\u{2167}', '\0', '\0']),
+        ('\u{2178}', ['\u{2168}', '\0', '\0']), ('\u{2179}', ['\u{2169}', '\0', '\0']), ('\u{217a}',
+        ['\u{216a}', '\0', '\0']), ('\u{217b}', ['\u{216b}', '\0', '\0']), ('\u{217c}', ['\u{216c}',
+        '\0', '\0']), ('\u{217d}', ['\u{216d}', '\0', '\0']), ('\u{217e}', ['\u{216e}', '\0',
+        '\0']), ('\u{217f}', ['\u{216f}', '\0', '\0']), ('\u{2184}', ['\u{2183}', '\0', '\0']),
+        ('\u{24d0}', ['\u{24b6}', '\0', '\0']), ('\u{24d1}', ['\u{24b7}', '\0', '\0']), ('\u{24d2}',
+        ['\u{24b8}', '\0', '\0']), ('\u{24d3}', ['\u{24b9}', '\0', '\0']), ('\u{24d4}', ['\u{24ba}',
+        '\0', '\0']), ('\u{24d5}', ['\u{24bb}', '\0', '\0']), ('\u{24d6}', ['\u{24bc}', '\0',
+        '\0']), ('\u{24d7}', ['\u{24bd}', '\0', '\0']), ('\u{24d8}', ['\u{24be}', '\0', '\0']),
+        ('\u{24d9}', ['\u{24bf}', '\0', '\0']), ('\u{24da}', ['\u{24c0}', '\0', '\0']), ('\u{24db}',
+        ['\u{24c1}', '\0', '\0']), ('\u{24dc}', ['\u{24c2}', '\0', '\0']), ('\u{24dd}', ['\u{24c3}',
+        '\0', '\0']), ('\u{24de}', ['\u{24c4}', '\0', '\0']), ('\u{24df}', ['\u{24c5}', '\0',
+        '\0']), ('\u{24e0}', ['\u{24c6}', '\0', '\0']), ('\u{24e1}', ['\u{24c7}', '\0', '\0']),
+        ('\u{24e2}', ['\u{24c8}', '\0', '\0']), ('\u{24e3}', ['\u{24c9}', '\0', '\0']), ('\u{24e4}',
+        ['\u{24ca}', '\0', '\0']), ('\u{24e5}', ['\u{24cb}', '\0', '\0']), ('\u{24e6}', ['\u{24cc}',
+        '\0', '\0']), ('\u{24e7}', ['\u{24cd}', '\0', '\0']), ('\u{24e8}', ['\u{24ce}', '\0',
+        '\0']), ('\u{24e9}', ['\u{24cf}', '\0', '\0']), ('\u{2c30}', ['\u{2c00}', '\0', '\0']),
+        ('\u{2c31}', ['\u{2c01}', '\0', '\0']), ('\u{2c32}', ['\u{2c02}', '\0', '\0']), ('\u{2c33}',
+        ['\u{2c03}', '\0', '\0']), ('\u{2c34}', ['\u{2c04}', '\0', '\0']), ('\u{2c35}', ['\u{2c05}',
+        '\0', '\0']), ('\u{2c36}', ['\u{2c06}', '\0', '\0']), ('\u{2c37}', ['\u{2c07}', '\0',
+        '\0']), ('\u{2c38}', ['\u{2c08}', '\0', '\0']), ('\u{2c39}', ['\u{2c09}', '\0', '\0']),
+        ('\u{2c3a}', ['\u{2c0a}', '\0', '\0']), ('\u{2c3b}', ['\u{2c0b}', '\0', '\0']), ('\u{2c3c}',
+        ['\u{2c0c}', '\0', '\0']), ('\u{2c3d}', ['\u{2c0d}', '\0', '\0']), ('\u{2c3e}', ['\u{2c0e}',
+        '\0', '\0']), ('\u{2c3f}', ['\u{2c0f}', '\0', '\0']), ('\u{2c40}', ['\u{2c10}', '\0',
+        '\0']), ('\u{2c41}', ['\u{2c11}', '\0', '\0']), ('\u{2c42}', ['\u{2c12}', '\0', '\0']),
+        ('\u{2c43}', ['\u{2c13}', '\0', '\0']), ('\u{2c44}', ['\u{2c14}', '\0', '\0']), ('\u{2c45}',
+        ['\u{2c15}', '\0', '\0']), ('\u{2c46}', ['\u{2c16}', '\0', '\0']), ('\u{2c47}', ['\u{2c17}',
+        '\0', '\0']), ('\u{2c48}', ['\u{2c18}', '\0', '\0']), ('\u{2c49}', ['\u{2c19}', '\0',
+        '\0']), ('\u{2c4a}', ['\u{2c1a}', '\0', '\0']), ('\u{2c4b}', ['\u{2c1b}', '\0', '\0']),
+        ('\u{2c4c}', ['\u{2c1c}', '\0', '\0']), ('\u{2c4d}', ['\u{2c1d}', '\0', '\0']), ('\u{2c4e}',
+        ['\u{2c1e}', '\0', '\0']), ('\u{2c4f}', ['\u{2c1f}', '\0', '\0']), ('\u{2c50}', ['\u{2c20}',
+        '\0', '\0']), ('\u{2c51}', ['\u{2c21}', '\0', '\0']), ('\u{2c52}', ['\u{2c22}', '\0',
+        '\0']), ('\u{2c53}', ['\u{2c23}', '\0', '\0']), ('\u{2c54}', ['\u{2c24}', '\0', '\0']),
+        ('\u{2c55}', ['\u{2c25}', '\0', '\0']), ('\u{2c56}', ['\u{2c26}', '\0', '\0']), ('\u{2c57}',
+        ['\u{2c27}', '\0', '\0']), ('\u{2c58}', ['\u{2c28}', '\0', '\0']), ('\u{2c59}', ['\u{2c29}',
+        '\0', '\0']), ('\u{2c5a}', ['\u{2c2a}', '\0', '\0']), ('\u{2c5b}', ['\u{2c2b}', '\0',
+        '\0']), ('\u{2c5c}', ['\u{2c2c}', '\0', '\0']), ('\u{2c5d}', ['\u{2c2d}', '\0', '\0']),
+        ('\u{2c5e}', ['\u{2c2e}', '\0', '\0']), ('\u{2c61}', ['\u{2c60}', '\0', '\0']), ('\u{2c65}',
+        ['\u{23a}', '\0', '\0']), ('\u{2c66}', ['\u{23e}', '\0', '\0']), ('\u{2c68}', ['\u{2c67}',
+        '\0', '\0']), ('\u{2c6a}', ['\u{2c69}', '\0', '\0']), ('\u{2c6c}', ['\u{2c6b}', '\0',
+        '\0']), ('\u{2c73}', ['\u{2c72}', '\0', '\0']), ('\u{2c76}', ['\u{2c75}', '\0', '\0']),
+        ('\u{2c81}', ['\u{2c80}', '\0', '\0']), ('\u{2c83}', ['\u{2c82}', '\0', '\0']), ('\u{2c85}',
+        ['\u{2c84}', '\0', '\0']), ('\u{2c87}', ['\u{2c86}', '\0', '\0']), ('\u{2c89}', ['\u{2c88}',
+        '\0', '\0']), ('\u{2c8b}', ['\u{2c8a}', '\0', '\0']), ('\u{2c8d}', ['\u{2c8c}', '\0',
+        '\0']), ('\u{2c8f}', ['\u{2c8e}', '\0', '\0']), ('\u{2c91}', ['\u{2c90}', '\0', '\0']),
+        ('\u{2c93}', ['\u{2c92}', '\0', '\0']), ('\u{2c95}', ['\u{2c94}', '\0', '\0']), ('\u{2c97}',
+        ['\u{2c96}', '\0', '\0']), ('\u{2c99}', ['\u{2c98}', '\0', '\0']), ('\u{2c9b}', ['\u{2c9a}',
+        '\0', '\0']), ('\u{2c9d}', ['\u{2c9c}', '\0', '\0']), ('\u{2c9f}', ['\u{2c9e}', '\0',
+        '\0']), ('\u{2ca1}', ['\u{2ca0}', '\0', '\0']), ('\u{2ca3}', ['\u{2ca2}', '\0', '\0']),
+        ('\u{2ca5}', ['\u{2ca4}', '\0', '\0']), ('\u{2ca7}', ['\u{2ca6}', '\0', '\0']), ('\u{2ca9}',
+        ['\u{2ca8}', '\0', '\0']), ('\u{2cab}', ['\u{2caa}', '\0', '\0']), ('\u{2cad}', ['\u{2cac}',
+        '\0', '\0']), ('\u{2caf}', ['\u{2cae}', '\0', '\0']), ('\u{2cb1}', ['\u{2cb0}', '\0',
+        '\0']), ('\u{2cb3}', ['\u{2cb2}', '\0', '\0']), ('\u{2cb5}', ['\u{2cb4}', '\0', '\0']),
+        ('\u{2cb7}', ['\u{2cb6}', '\0', '\0']), ('\u{2cb9}', ['\u{2cb8}', '\0', '\0']), ('\u{2cbb}',
+        ['\u{2cba}', '\0', '\0']), ('\u{2cbd}', ['\u{2cbc}', '\0', '\0']), ('\u{2cbf}', ['\u{2cbe}',
+        '\0', '\0']), ('\u{2cc1}', ['\u{2cc0}', '\0', '\0']), ('\u{2cc3}', ['\u{2cc2}', '\0',
+        '\0']), ('\u{2cc5}', ['\u{2cc4}', '\0', '\0']), ('\u{2cc7}', ['\u{2cc6}', '\0', '\0']),
+        ('\u{2cc9}', ['\u{2cc8}', '\0', '\0']), ('\u{2ccb}', ['\u{2cca}', '\0', '\0']), ('\u{2ccd}',
+        ['\u{2ccc}', '\0', '\0']), ('\u{2ccf}', ['\u{2cce}', '\0', '\0']), ('\u{2cd1}', ['\u{2cd0}',
+        '\0', '\0']), ('\u{2cd3}', ['\u{2cd2}', '\0', '\0']), ('\u{2cd5}', ['\u{2cd4}', '\0',
+        '\0']), ('\u{2cd7}', ['\u{2cd6}', '\0', '\0']), ('\u{2cd9}', ['\u{2cd8}', '\0', '\0']),
+        ('\u{2cdb}', ['\u{2cda}', '\0', '\0']), ('\u{2cdd}', ['\u{2cdc}', '\0', '\0']), ('\u{2cdf}',
+        ['\u{2cde}', '\0', '\0']), ('\u{2ce1}', ['\u{2ce0}', '\0', '\0']), ('\u{2ce3}', ['\u{2ce2}',
+        '\0', '\0']), ('\u{2cec}', ['\u{2ceb}', '\0', '\0']), ('\u{2cee}', ['\u{2ced}', '\0',
+        '\0']), ('\u{2cf3}', ['\u{2cf2}', '\0', '\0']), ('\u{2d00}', ['\u{10a0}', '\0', '\0']),
+        ('\u{2d01}', ['\u{10a1}', '\0', '\0']), ('\u{2d02}', ['\u{10a2}', '\0', '\0']), ('\u{2d03}',
+        ['\u{10a3}', '\0', '\0']), ('\u{2d04}', ['\u{10a4}', '\0', '\0']), ('\u{2d05}', ['\u{10a5}',
+        '\0', '\0']), ('\u{2d06}', ['\u{10a6}', '\0', '\0']), ('\u{2d07}', ['\u{10a7}', '\0',
+        '\0']), ('\u{2d08}', ['\u{10a8}', '\0', '\0']), ('\u{2d09}', ['\u{10a9}', '\0', '\0']),
+        ('\u{2d0a}', ['\u{10aa}', '\0', '\0']), ('\u{2d0b}', ['\u{10ab}', '\0', '\0']), ('\u{2d0c}',
+        ['\u{10ac}', '\0', '\0']), ('\u{2d0d}', ['\u{10ad}', '\0', '\0']), ('\u{2d0e}', ['\u{10ae}',
+        '\0', '\0']), ('\u{2d0f}', ['\u{10af}', '\0', '\0']), ('\u{2d10}', ['\u{10b0}', '\0',
+        '\0']), ('\u{2d11}', ['\u{10b1}', '\0', '\0']), ('\u{2d12}', ['\u{10b2}', '\0', '\0']),
+        ('\u{2d13}', ['\u{10b3}', '\0', '\0']), ('\u{2d14}', ['\u{10b4}', '\0', '\0']), ('\u{2d15}',
+        ['\u{10b5}', '\0', '\0']), ('\u{2d16}', ['\u{10b6}', '\0', '\0']), ('\u{2d17}', ['\u{10b7}',
+        '\0', '\0']), ('\u{2d18}', ['\u{10b8}', '\0', '\0']), ('\u{2d19}', ['\u{10b9}', '\0',
+        '\0']), ('\u{2d1a}', ['\u{10ba}', '\0', '\0']), ('\u{2d1b}', ['\u{10bb}', '\0', '\0']),
+        ('\u{2d1c}', ['\u{10bc}', '\0', '\0']), ('\u{2d1d}', ['\u{10bd}', '\0', '\0']), ('\u{2d1e}',
+        ['\u{10be}', '\0', '\0']), ('\u{2d1f}', ['\u{10bf}', '\0', '\0']), ('\u{2d20}', ['\u{10c0}',
+        '\0', '\0']), ('\u{2d21}', ['\u{10c1}', '\0', '\0']), ('\u{2d22}', ['\u{10c2}', '\0',
+        '\0']), ('\u{2d23}', ['\u{10c3}', '\0', '\0']), ('\u{2d24}', ['\u{10c4}', '\0', '\0']),
+        ('\u{2d25}', ['\u{10c5}', '\0', '\0']), ('\u{2d27}', ['\u{10c7}', '\0', '\0']), ('\u{2d2d}',
+        ['\u{10cd}', '\0', '\0']), ('\u{a641}', ['\u{a640}', '\0', '\0']), ('\u{a643}', ['\u{a642}',
+        '\0', '\0']), ('\u{a645}', ['\u{a644}', '\0', '\0']), ('\u{a647}', ['\u{a646}', '\0',
+        '\0']), ('\u{a649}', ['\u{a648}', '\0', '\0']), ('\u{a64b}', ['\u{a64a}', '\0', '\0']),
+        ('\u{a64d}', ['\u{a64c}', '\0', '\0']), ('\u{a64f}', ['\u{a64e}', '\0', '\0']), ('\u{a651}',
+        ['\u{a650}', '\0', '\0']), ('\u{a653}', ['\u{a652}', '\0', '\0']), ('\u{a655}', ['\u{a654}',
+        '\0', '\0']), ('\u{a657}', ['\u{a656}', '\0', '\0']), ('\u{a659}', ['\u{a658}', '\0',
+        '\0']), ('\u{a65b}', ['\u{a65a}', '\0', '\0']), ('\u{a65d}', ['\u{a65c}', '\0', '\0']),
+        ('\u{a65f}', ['\u{a65e}', '\0', '\0']), ('\u{a661}', ['\u{a660}', '\0', '\0']), ('\u{a663}',
+        ['\u{a662}', '\0', '\0']), ('\u{a665}', ['\u{a664}', '\0', '\0']), ('\u{a667}', ['\u{a666}',
+        '\0', '\0']), ('\u{a669}', ['\u{a668}', '\0', '\0']), ('\u{a66b}', ['\u{a66a}', '\0',
+        '\0']), ('\u{a66d}', ['\u{a66c}', '\0', '\0']), ('\u{a681}', ['\u{a680}', '\0', '\0']),
+        ('\u{a683}', ['\u{a682}', '\0', '\0']), ('\u{a685}', ['\u{a684}', '\0', '\0']), ('\u{a687}',
+        ['\u{a686}', '\0', '\0']), ('\u{a689}', ['\u{a688}', '\0', '\0']), ('\u{a68b}', ['\u{a68a}',
+        '\0', '\0']), ('\u{a68d}', ['\u{a68c}', '\0', '\0']), ('\u{a68f}', ['\u{a68e}', '\0',
+        '\0']), ('\u{a691}', ['\u{a690}', '\0', '\0']), ('\u{a693}', ['\u{a692}', '\0', '\0']),
+        ('\u{a695}', ['\u{a694}', '\0', '\0']), ('\u{a697}', ['\u{a696}', '\0', '\0']), ('\u{a699}',
+        ['\u{a698}', '\0', '\0']), ('\u{a69b}', ['\u{a69a}', '\0', '\0']), ('\u{a723}', ['\u{a722}',
+        '\0', '\0']), ('\u{a725}', ['\u{a724}', '\0', '\0']), ('\u{a727}', ['\u{a726}', '\0',
+        '\0']), ('\u{a729}', ['\u{a728}', '\0', '\0']), ('\u{a72b}', ['\u{a72a}', '\0', '\0']),
+        ('\u{a72d}', ['\u{a72c}', '\0', '\0']), ('\u{a72f}', ['\u{a72e}', '\0', '\0']), ('\u{a733}',
+        ['\u{a732}', '\0', '\0']), ('\u{a735}', ['\u{a734}', '\0', '\0']), ('\u{a737}', ['\u{a736}',
+        '\0', '\0']), ('\u{a739}', ['\u{a738}', '\0', '\0']), ('\u{a73b}', ['\u{a73a}', '\0',
+        '\0']), ('\u{a73d}', ['\u{a73c}', '\0', '\0']), ('\u{a73f}', ['\u{a73e}', '\0', '\0']),
+        ('\u{a741}', ['\u{a740}', '\0', '\0']), ('\u{a743}', ['\u{a742}', '\0', '\0']), ('\u{a745}',
+        ['\u{a744}', '\0', '\0']), ('\u{a747}', ['\u{a746}', '\0', '\0']), ('\u{a749}', ['\u{a748}',
+        '\0', '\0']), ('\u{a74b}', ['\u{a74a}', '\0', '\0']), ('\u{a74d}', ['\u{a74c}', '\0',
+        '\0']), ('\u{a74f}', ['\u{a74e}', '\0', '\0']), ('\u{a751}', ['\u{a750}', '\0', '\0']),
+        ('\u{a753}', ['\u{a752}', '\0', '\0']), ('\u{a755}', ['\u{a754}', '\0', '\0']), ('\u{a757}',
+        ['\u{a756}', '\0', '\0']), ('\u{a759}', ['\u{a758}', '\0', '\0']), ('\u{a75b}', ['\u{a75a}',
+        '\0', '\0']), ('\u{a75d}', ['\u{a75c}', '\0', '\0']), ('\u{a75f}', ['\u{a75e}', '\0',
+        '\0']), ('\u{a761}', ['\u{a760}', '\0', '\0']), ('\u{a763}', ['\u{a762}', '\0', '\0']),
+        ('\u{a765}', ['\u{a764}', '\0', '\0']), ('\u{a767}', ['\u{a766}', '\0', '\0']), ('\u{a769}',
+        ['\u{a768}', '\0', '\0']), ('\u{a76b}', ['\u{a76a}', '\0', '\0']), ('\u{a76d}', ['\u{a76c}',
+        '\0', '\0']), ('\u{a76f}', ['\u{a76e}', '\0', '\0']), ('\u{a77a}', ['\u{a779}', '\0',
+        '\0']), ('\u{a77c}', ['\u{a77b}', '\0', '\0']), ('\u{a77f}', ['\u{a77e}', '\0', '\0']),
+        ('\u{a781}', ['\u{a780}', '\0', '\0']), ('\u{a783}', ['\u{a782}', '\0', '\0']), ('\u{a785}',
+        ['\u{a784}', '\0', '\0']), ('\u{a787}', ['\u{a786}', '\0', '\0']), ('\u{a78c}', ['\u{a78b}',
+        '\0', '\0']), ('\u{a791}', ['\u{a790}', '\0', '\0']), ('\u{a793}', ['\u{a792}', '\0',
+        '\0']), ('\u{a797}', ['\u{a796}', '\0', '\0']), ('\u{a799}', ['\u{a798}', '\0', '\0']),
+        ('\u{a79b}', ['\u{a79a}', '\0', '\0']), ('\u{a79d}', ['\u{a79c}', '\0', '\0']), ('\u{a79f}',
+        ['\u{a79e}', '\0', '\0']), ('\u{a7a1}', ['\u{a7a0}', '\0', '\0']), ('\u{a7a3}', ['\u{a7a2}',
+        '\0', '\0']), ('\u{a7a5}', ['\u{a7a4}', '\0', '\0']), ('\u{a7a7}', ['\u{a7a6}', '\0',
+        '\0']), ('\u{a7a9}', ['\u{a7a8}', '\0', '\0']), ('\u{fb00}', ['\u{46}', '\u{66}', '\0']),
+        ('\u{fb01}', ['\u{46}', '\u{69}', '\0']), ('\u{fb02}', ['\u{46}', '\u{6c}', '\0']),
+        ('\u{fb03}', ['\u{46}', '\u{66}', '\u{69}']), ('\u{fb04}', ['\u{46}', '\u{66}', '\u{6c}']),
+        ('\u{fb05}', ['\u{53}', '\u{74}', '\0']), ('\u{fb06}', ['\u{53}', '\u{74}', '\0']),
+        ('\u{fb13}', ['\u{544}', '\u{576}', '\0']), ('\u{fb14}', ['\u{544}', '\u{565}', '\0']),
+        ('\u{fb15}', ['\u{544}', '\u{56b}', '\0']), ('\u{fb16}', ['\u{54e}', '\u{576}', '\0']),
+        ('\u{fb17}', ['\u{544}', '\u{56d}', '\0']), ('\u{ff41}', ['\u{ff21}', '\0', '\0']),
+        ('\u{ff42}', ['\u{ff22}', '\0', '\0']), ('\u{ff43}', ['\u{ff23}', '\0', '\0']), ('\u{ff44}',
+        ['\u{ff24}', '\0', '\0']), ('\u{ff45}', ['\u{ff25}', '\0', '\0']), ('\u{ff46}', ['\u{ff26}',
+        '\0', '\0']), ('\u{ff47}', ['\u{ff27}', '\0', '\0']), ('\u{ff48}', ['\u{ff28}', '\0',
+        '\0']), ('\u{ff49}', ['\u{ff29}', '\0', '\0']), ('\u{ff4a}', ['\u{ff2a}', '\0', '\0']),
+        ('\u{ff4b}', ['\u{ff2b}', '\0', '\0']), ('\u{ff4c}', ['\u{ff2c}', '\0', '\0']), ('\u{ff4d}',
+        ['\u{ff2d}', '\0', '\0']), ('\u{ff4e}', ['\u{ff2e}', '\0', '\0']), ('\u{ff4f}', ['\u{ff2f}',
+        '\0', '\0']), ('\u{ff50}', ['\u{ff30}', '\0', '\0']), ('\u{ff51}', ['\u{ff31}', '\0',
+        '\0']), ('\u{ff52}', ['\u{ff32}', '\0', '\0']), ('\u{ff53}', ['\u{ff33}', '\0', '\0']),
+        ('\u{ff54}', ['\u{ff34}', '\0', '\0']), ('\u{ff55}', ['\u{ff35}', '\0', '\0']), ('\u{ff56}',
+        ['\u{ff36}', '\0', '\0']), ('\u{ff57}', ['\u{ff37}', '\0', '\0']), ('\u{ff58}', ['\u{ff38}',
+        '\0', '\0']), ('\u{ff59}', ['\u{ff39}', '\0', '\0']), ('\u{ff5a}', ['\u{ff3a}', '\0',
+        '\0']), ('\u{10428}', ['\u{10400}', '\0', '\0']), ('\u{10429}', ['\u{10401}', '\0', '\0']),
+        ('\u{1042a}', ['\u{10402}', '\0', '\0']), ('\u{1042b}', ['\u{10403}', '\0', '\0']),
+        ('\u{1042c}', ['\u{10404}', '\0', '\0']), ('\u{1042d}', ['\u{10405}', '\0', '\0']),
+        ('\u{1042e}', ['\u{10406}', '\0', '\0']), ('\u{1042f}', ['\u{10407}', '\0', '\0']),
+        ('\u{10430}', ['\u{10408}', '\0', '\0']), ('\u{10431}', ['\u{10409}', '\0', '\0']),
+        ('\u{10432}', ['\u{1040a}', '\0', '\0']), ('\u{10433}', ['\u{1040b}', '\0', '\0']),
+        ('\u{10434}', ['\u{1040c}', '\0', '\0']), ('\u{10435}', ['\u{1040d}', '\0', '\0']),
+        ('\u{10436}', ['\u{1040e}', '\0', '\0']), ('\u{10437}', ['\u{1040f}', '\0', '\0']),
+        ('\u{10438}', ['\u{10410}', '\0', '\0']), ('\u{10439}', ['\u{10411}', '\0', '\0']),
+        ('\u{1043a}', ['\u{10412}', '\0', '\0']), ('\u{1043b}', ['\u{10413}', '\0', '\0']),
+        ('\u{1043c}', ['\u{10414}', '\0', '\0']), ('\u{1043d}', ['\u{10415}', '\0', '\0']),
+        ('\u{1043e}', ['\u{10416}', '\0', '\0']), ('\u{1043f}', ['\u{10417}', '\0', '\0']),
+        ('\u{10440}', ['\u{10418}', '\0', '\0']), ('\u{10441}', ['\u{10419}', '\0', '\0']),
+        ('\u{10442}', ['\u{1041a}', '\0', '\0']), ('\u{10443}', ['\u{1041b}', '\0', '\0']),
+        ('\u{10444}', ['\u{1041c}', '\0', '\0']), ('\u{10445}', ['\u{1041d}', '\0', '\0']),
+        ('\u{10446}', ['\u{1041e}', '\0', '\0']), ('\u{10447}', ['\u{1041f}', '\0', '\0']),
+        ('\u{10448}', ['\u{10420}', '\0', '\0']), ('\u{10449}', ['\u{10421}', '\0', '\0']),
+        ('\u{1044a}', ['\u{10422}', '\0', '\0']), ('\u{1044b}', ['\u{10423}', '\0', '\0']),
+        ('\u{1044c}', ['\u{10424}', '\0', '\0']), ('\u{1044d}', ['\u{10425}', '\0', '\0']),
+        ('\u{1044e}', ['\u{10426}', '\0', '\0']), ('\u{1044f}', ['\u{10427}', '\0', '\0']),
+        ('\u{118c0}', ['\u{118a0}', '\0', '\0']), ('\u{118c1}', ['\u{118a1}', '\0', '\0']),
+        ('\u{118c2}', ['\u{118a2}', '\0', '\0']), ('\u{118c3}', ['\u{118a3}', '\0', '\0']),
+        ('\u{118c4}', ['\u{118a4}', '\0', '\0']), ('\u{118c5}', ['\u{118a5}', '\0', '\0']),
+        ('\u{118c6}', ['\u{118a6}', '\0', '\0']), ('\u{118c7}', ['\u{118a7}', '\0', '\0']),
+        ('\u{118c8}', ['\u{118a8}', '\0', '\0']), ('\u{118c9}', ['\u{118a9}', '\0', '\0']),
+        ('\u{118ca}', ['\u{118aa}', '\0', '\0']), ('\u{118cb}', ['\u{118ab}', '\0', '\0']),
+        ('\u{118cc}', ['\u{118ac}', '\0', '\0']), ('\u{118cd}', ['\u{118ad}', '\0', '\0']),
+        ('\u{118ce}', ['\u{118ae}', '\0', '\0']), ('\u{118cf}', ['\u{118af}', '\0', '\0']),
+        ('\u{118d0}', ['\u{118b0}', '\0', '\0']), ('\u{118d1}', ['\u{118b1}', '\0', '\0']),
+        ('\u{118d2}', ['\u{118b2}', '\0', '\0']), ('\u{118d3}', ['\u{118b3}', '\0', '\0']),
+        ('\u{118d4}', ['\u{118b4}', '\0', '\0']), ('\u{118d5}', ['\u{118b5}', '\0', '\0']),
+        ('\u{118d6}', ['\u{118b6}', '\0', '\0']), ('\u{118d7}', ['\u{118b7}', '\0', '\0']),
+        ('\u{118d8}', ['\u{118b8}', '\0', '\0']), ('\u{118d9}', ['\u{118b9}', '\0', '\0']),
+        ('\u{118da}', ['\u{118ba}', '\0', '\0']), ('\u{118db}', ['\u{118bb}', '\0', '\0']),
+        ('\u{118dc}', ['\u{118bc}', '\0', '\0']), ('\u{118dd}', ['\u{118bd}', '\0', '\0']),
+        ('\u{118de}', ['\u{118be}', '\0', '\0']), ('\u{118df}', ['\u{118bf}', '\0', '\0'])
     ];
 
 }
@@ -4603,7 +5682,7 @@ pub mod grapheme {
     }
 
     const grapheme_cat_table: &'static [(char, char, GraphemeCat)] = &[
-        ('\u{0}', '\u{1f}', GC_Control), ('\u{7f}', '\u{9f}', GC_Control), ('\u{ad}', '\u{ad}',
+        ('\0', '\u{1f}', GC_Control), ('\u{7f}', '\u{9f}', GC_Control), ('\u{ad}', '\u{ad}',
         GC_Control), ('\u{300}', '\u{36f}', GC_Extend), ('\u{483}', '\u{489}', GC_Extend),
         ('\u{591}', '\u{5bd}', GC_Extend), ('\u{5bf}', '\u{5bf}', GC_Extend), ('\u{5c1}', '\u{5c2}',
         GC_Extend), ('\u{5c4}', '\u{5c5}', GC_Extend), ('\u{5c7}', '\u{5c7}', GC_Extend),
index 3ce8835b1a8de76744d561010ce4a5794d7e007e..53063c6247efb8e21ab16f359e89e74624305659 100644 (file)
@@ -83,17 +83,17 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
         }
         def::DefStruct(did) => {
             record_extern_fqn(cx, did, clean::TypeStruct);
-            ret.extend(build_impls(cx, tcx, did).into_iter());
+            ret.extend(build_impls(cx, tcx, did));
             clean::StructItem(build_struct(cx, tcx, did))
         }
         def::DefTy(did, false) => {
             record_extern_fqn(cx, did, clean::TypeTypedef);
-            ret.extend(build_impls(cx, tcx, did).into_iter());
+            ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
         def::DefTy(did, true) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
-            ret.extend(build_impls(cx, tcx, did).into_iter());
+            ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
         // Assume that the enum type is reexported next to the variant, and
@@ -167,7 +167,7 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
 fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function {
     let t = ty::lookup_item_type(tcx, did);
     let (decl, style, abi) = match t.ty.sty {
-        ty::ty_bare_fn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
+        ty::TyBareFn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
         _ => panic!("bad function"),
     };
     let predicates = ty::lookup_predicates(tcx, did);
@@ -175,6 +175,7 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) ->
         decl: decl,
         generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
         unsafety: style,
+        constness: ast::Constness::NotConst,
         abi: abi,
     }
 }
@@ -203,7 +204,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
     let t = ty::lookup_item_type(tcx, did);
     let predicates = ty::lookup_predicates(tcx, did);
     match t.ty.sty {
-        ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
+        ty::TyEnum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
             return clean::EnumItem(clean::Enum {
                 generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
                 variants_stripped: false,
@@ -216,7 +217,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
     clean::TypedefItem(clean::Typedef {
         type_: t.ty.clean(cx),
         generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
-    })
+    }, false)
 }
 
 pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
@@ -348,6 +349,7 @@ pub fn build_impl(cx: &DocContext,
                     }) => {
                         clean::MethodItem(clean::Method {
                             unsafety: unsafety,
+                            constness: ast::Constness::NotConst,
                             decl: decl,
                             self_: self_,
                             generics: generics,
@@ -360,15 +362,17 @@ pub fn build_impl(cx: &DocContext,
             }
             ty::TypeTraitItem(ref assoc_ty) => {
                 let did = assoc_ty.def_id;
-                let type_scheme = ty::lookup_item_type(tcx, did);
-                let predicates = ty::lookup_predicates(tcx, did);
+                let type_scheme = ty::TypeScheme {
+                    ty: assoc_ty.ty.unwrap(),
+                    generics: ty::Generics::empty()
+                };
                 // Not sure the choice of ParamSpace actually matters here,
                 // because an associated type won't have generics on the LHS
-                let typedef = (type_scheme, predicates,
+                let typedef = (type_scheme, ty::GenericPredicates::empty(),
                                subst::ParamSpace::TypeSpace).clean(cx);
                 Some(clean::Item {
                     name: Some(assoc_ty.name.clean(cx)),
-                    inner: clean::TypedefItem(typedef),
+                    inner: clean::TypedefItem(typedef, true),
                     source: clean::Span::empty(),
                     attrs: vec![],
                     visibility: None,
@@ -447,7 +451,7 @@ fn build_module(cx: &DocContext, tcx: &ty::ctxt,
                 decoder::DlDef(def) if vis == ast::Public => {
                     if !visited.insert(def) { return }
                     match try_inline_def(cx, tcx, def) {
-                        Some(i) => items.extend(i.into_iter()),
+                        Some(i) => items.extend(i),
                         None => {}
                     }
                 }
index 4c2357f8a8f0d05b1df64fbbe00cafe4997a53e0..8ba4470c3efbd007ef5f89250ae8a73e5896af51 100644 (file)
@@ -55,7 +55,7 @@ use visit_ast;
 
 /// A stable identifier to the particular version of JSON output.
 /// Increment this when the `Crate` and related structures change.
-pub static SCHEMA_VERSION: &'static str = "0.8.3";
+pub const SCHEMA_VERSION: &'static str = "0.8.3";
 
 mod inline;
 mod simplify;
@@ -190,7 +190,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     inner: PrimitiveItem(prim),
                 });
             }
-            m.items.extend(tmp.into_iter());
+            m.items.extend(tmp);
         }
 
         let src = match cx.input {
@@ -343,7 +343,7 @@ pub enum ItemEnum {
     EnumItem(Enum),
     FunctionItem(Function),
     ModuleItem(Module),
-    TypedefItem(Typedef),
+    TypedefItem(Typedef, bool /* is associated type */),
     StaticItem(Static),
     ConstantItem(Constant),
     TraitItem(Trait),
@@ -382,17 +382,17 @@ impl Clean<Item> for doctree::Module {
 
         let mut items: Vec<Item> = vec![];
         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
-        items.extend(self.imports.iter().flat_map(|x| x.clean(cx).into_iter()));
+        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.structs.iter().map(|x| x.clean(cx)));
         items.extend(self.enums.iter().map(|x| x.clean(cx)));
         items.extend(self.fns.iter().map(|x| x.clean(cx)));
-        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx).into_iter()));
+        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
         items.extend(self.statics.iter().map(|x| x.clean(cx)));
         items.extend(self.constants.iter().map(|x| x.clean(cx)));
         items.extend(self.traits.iter().map(|x| x.clean(cx)));
-        items.extend(self.impls.iter().flat_map(|x| x.clean(cx).into_iter()));
+        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.macros.iter().map(|x| x.clean(cx)));
         items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
 
@@ -522,7 +522,7 @@ pub enum TyParamBound {
 impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
         use syntax::ast::TraitBoundModifier as TBM;
-        let mut sized_bound = ty::BuiltinBound::BoundSized.clean(cx);
+        let mut sized_bound = ty::BoundSized.clean(cx);
         if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
             *tbm = TBM::Maybe
         };
@@ -579,7 +579,6 @@ impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBound
 
 fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
                         bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
-    use rustc::middle::ty::sty;
     let lifetimes = substs.regions().get_slice(subst::TypeSpace)
                     .iter()
                     .filter_map(|v| v.clean(cx))
@@ -591,7 +590,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
         (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
             assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
-                sty::ty_tup(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return PathParameters::AngleBracketed {
                         lifetimes: lifetimes,
@@ -603,7 +602,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
             let output = None;
             // FIXME(#20299) return type comes from a projection now
             // match types[1].sty {
-            //     sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
+            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
             //     _ => Some(types[1].clean(cx))
             // };
             PathParameters::Parenthesized {
@@ -664,6 +663,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
                 path: path,
                 typarams: None,
                 did: did,
+                is_generic: false,
             },
             lifetimes: vec![]
         }, ast::TraitBoundModifier::None)
@@ -690,11 +690,10 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         // collect any late bound regions
         let mut late_bounds = vec![];
         for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
-            use rustc::middle::ty::{Region, sty};
-            if let sty::ty_tup(ref ts) = ty_s.sty {
+            if let ty::TyTuple(ref ts) = ty_s.sty {
                 for &ty_s in ts {
-                    if let sty::ty_rptr(ref reg, _) = ty_s.sty {
-                        if let &Region::ReLateBound(_, _) = *reg {
+                    if let ty::TyRef(ref reg, _) = ty_s.sty {
+                        if let &ty::Region::ReLateBound(_, _) = *reg {
                             debug!("  hit an ReLateBound {:?}", reg);
                             if let Some(lt) = reg.clean(cx) {
                                 late_bounds.push(lt)
@@ -706,25 +705,17 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         }
 
         TraitBound(PolyTrait {
-            trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
+            trait_: ResolvedPath {
+                path: path,
+                typarams: None,
+                did: self.def_id,
+                is_generic: false,
+            },
             lifetimes: late_bounds
         }, ast::TraitBoundModifier::None)
     }
 }
 
-impl<'tcx> Clean<Vec<TyParamBound>> for ty::ParamBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
-        let mut v = Vec::new();
-        for t in &self.trait_bounds {
-            v.push(t.clean(cx));
-        }
-        for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) {
-            v.push(RegionBound(r));
-        }
-        v
-    }
-}
-
 impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
     fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
         let mut v = Vec::new();
@@ -989,6 +980,7 @@ pub struct Method {
     pub generics: Generics,
     pub self_: SelfTy,
     pub unsafety: ast::Unsafety,
+    pub constness: ast::Constness,
     pub decl: FnDecl,
     pub abi: abi::Abi
 }
@@ -1010,7 +1002,8 @@ impl Clean<Method> for ast::MethodSig {
         Method {
             generics: self.generics.clean(cx),
             self_: self.explicit_self.node.clean(cx),
-            unsafety: self.unsafety.clone(),
+            unsafety: self.unsafety,
+            constness: self.constness,
             decl: decl,
             abi: self.abi
         }
@@ -1075,7 +1068,8 @@ pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
     pub unsafety: ast::Unsafety,
-    pub abi: abi::Abi
+    pub constness: ast::Constness,
+    pub abi: abi::Abi,
 }
 
 impl Clean<Item> for doctree::Function {
@@ -1091,6 +1085,7 @@ impl Clean<Item> for doctree::Function {
                 decl: self.decl.clean(cx),
                 generics: self.generics.clean(cx),
                 unsafety: self.unsafety,
+                constness: self.constness,
                 abi: self.abi,
             }),
         }
@@ -1282,7 +1277,7 @@ impl Clean<Item> for ast::ImplItem {
                     type_params: Vec::new(),
                     where_predicates: Vec::new()
                 },
-            }),
+            }, true),
             ast::MacImplItem(_) => {
                 MacroItem(Macro {
                     source: self.span.to_src(cx),
@@ -1316,7 +1311,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
                     ty::ByValueExplicitSelfCategory => SelfValue,
                     ty::ByReferenceExplicitSelfCategory(..) => {
                         match self.fty.sig.0.inputs[0].sty {
-                            ty::ty_rptr(r, mt) => {
+                            ty::TyRef(r, mt) => {
                                 SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
                             }
                             _ => unreachable!(),
@@ -1348,7 +1343,10 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
                 generics: generics,
                 self_: self_,
                 decl: decl,
-                abi: self.fty.abi
+                abi: self.fty.abi,
+
+                // trait methods canot (currently, at least) be const
+                constness: ast::Constness::NotConst,
             })
         } else {
             TyMethodItem(TyMethod {
@@ -1356,7 +1354,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
                 generics: generics,
                 self_: self_,
                 decl: decl,
-                abi: self.fty.abi
+                abi: self.fty.abi,
             })
         };
 
@@ -1394,11 +1392,13 @@ pub struct PolyTrait {
 /// it does not preserve mutability or boxes.
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum Type {
-    /// structs/enums/traits (anything that'd be an ast::TyPath)
+    /// structs/enums/traits (most that'd be an ast::TyPath)
     ResolvedPath {
         path: Path,
         typarams: Option<Vec<TyParamBound>>,
         did: ast::DefId,
+        /// true if is a `T::Name` path for associated types
+        is_generic: bool,
     },
     /// For parameterized types, so the consumer of the JSON don't go
     /// looking for types which don't exist anywhere.
@@ -1587,8 +1587,13 @@ impl Clean<Type> for ast::Ty {
             TyObjectSum(ref lhs, ref bounds) => {
                 let lhs_ty = lhs.clean(cx);
                 match lhs_ty {
-                    ResolvedPath { path, typarams: None, did } => {
-                        ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
+                    ResolvedPath { path, typarams: None, did, is_generic } => {
+                        ResolvedPath {
+                            path: path,
+                            typarams: Some(bounds.clean(cx)),
+                            did: did,
+                            is_generic: is_generic,
+                        }
                     }
                     _ => {
                         lhs_ty // shouldn't happen
@@ -1613,37 +1618,37 @@ impl Clean<Type> for ast::Ty {
 impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
     fn clean(&self, cx: &DocContext) -> Type {
         match self.sty {
-            ty::ty_bool => Primitive(Bool),
-            ty::ty_char => Primitive(Char),
-            ty::ty_int(ast::TyIs) => Primitive(Isize),
-            ty::ty_int(ast::TyI8) => Primitive(I8),
-            ty::ty_int(ast::TyI16) => Primitive(I16),
-            ty::ty_int(ast::TyI32) => Primitive(I32),
-            ty::ty_int(ast::TyI64) => Primitive(I64),
-            ty::ty_uint(ast::TyUs) => Primitive(Usize),
-            ty::ty_uint(ast::TyU8) => Primitive(U8),
-            ty::ty_uint(ast::TyU16) => Primitive(U16),
-            ty::ty_uint(ast::TyU32) => Primitive(U32),
-            ty::ty_uint(ast::TyU64) => Primitive(U64),
-            ty::ty_float(ast::TyF32) => Primitive(F32),
-            ty::ty_float(ast::TyF64) => Primitive(F64),
-            ty::ty_str => Primitive(Str),
-            ty::ty_uniq(t) => {
+            ty::TyBool => Primitive(Bool),
+            ty::TyChar => Primitive(Char),
+            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| {
                     tcx.lang_items.owned_box()
                 });
                 lang_struct(cx, box_did, t, "Box", Unique)
             }
-            ty::ty_vec(ty, None) => Vector(box ty.clean(cx)),
-            ty::ty_vec(ty, Some(i)) => FixedVector(box ty.clean(cx),
-                                                   format!("{}", i)),
-            ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
-            ty::ty_rptr(r, mt) => BorrowedRef {
+            ty::TySlice(ty) => Vector(box ty.clean(cx)),
+            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
+                                              format!("{}", i)),
+            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
+            ty::TyRef(r, mt) => BorrowedRef {
                 lifetime: r.clean(cx),
                 mutability: mt.mutbl.clean(cx),
                 type_: box mt.ty.clean(cx),
             },
-            ty::ty_bare_fn(_, ref fty) => BareFunction(box BareFunctionDecl {
+            ty::TyBareFn(_, ref fty) => BareFunction(box BareFunctionDecl {
                 unsafety: fty.unsafety,
                 generics: Generics {
                     lifetimes: Vec::new(),
@@ -1653,12 +1658,12 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 decl: (ast_util::local_def(0), &fty.sig).clean(cx),
                 abi: fty.abi.to_string(),
             }),
-            ty::ty_struct(did, substs) |
-            ty::ty_enum(did, substs) => {
+            ty::TyStruct(did, substs) |
+            ty::TyEnum(did, substs) => {
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
                 let kind = match self.sty {
-                    ty::ty_struct(..) => TypeStruct,
+                    ty::TyStruct(..) => TypeStruct,
                     _ => TypeEnum,
                 };
                 let path = external_path(cx, &fqn.last().unwrap().to_string(),
@@ -1668,9 +1673,10 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     path: path,
                     typarams: None,
                     did: did,
+                    is_generic: false,
                 }
             }
-            ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+            ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
                 let did = principal.def_id();
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
@@ -1682,18 +1688,19 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     path: path,
                     typarams: Some(typarams),
                     did: did,
+                    is_generic: false,
                 }
             }
-            ty::ty_tup(ref t) => Tuple(t.clean(cx)),
+            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
 
-            ty::ty_projection(ref data) => data.clean(cx),
+            ty::TyProjection(ref data) => data.clean(cx),
 
-            ty::ty_param(ref p) => Generic(token::get_name(p.name).to_string()),
+            ty::TyParam(ref p) => Generic(token::get_name(p.name).to_string()),
 
-            ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
+            ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
-            ty::ty_infer(..) => panic!("ty_infer"),
-            ty::ty_err => panic!("ty_err"),
+            ty::TyInfer(..) => panic!("TyInfer"),
+            ty::TyError => panic!("TyError"),
         }
     }
 }
@@ -1862,7 +1869,7 @@ impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
                 StructVariant(VariantStruct {
                     struct_type: doctree::Plain,
                     fields_stripped: false,
-                    fields: s.iter().zip(self.args.iter()).map(|(name, ty)| {
+                    fields: s.iter().zip(&self.args).map(|(name, ty)| {
                         Item {
                             source: Span::empty(),
                             name: Some(name.clean(cx)),
@@ -2078,7 +2085,7 @@ impl Clean<Item> for doctree::Typedef {
             inner: TypedefItem(Typedef {
                 type_: self.ty.clean(cx),
                 generics: self.gen.clean(cx),
-            }),
+            }, false),
         }
     }
 }
@@ -2248,7 +2255,7 @@ fn build_deref_target_impls(cx: &DocContext,
 
     for item in items {
         let target = match item.inner {
-            TypedefItem(ref t) => &t.type_,
+            TypedefItem(ref t, true) => &t.type_,
             _ => continue,
         };
         let primitive = match *target {
@@ -2353,7 +2360,7 @@ impl Clean<Vec<Item>> for doctree::Import {
                     for path in list {
                         match inline::try_inline(cx, path.node.id(), None) {
                             Some(items) => {
-                                ret.extend(items.into_iter());
+                                ret.extend(items);
                             }
                             None => {
                                 remaining.push(path.clean(cx));
@@ -2453,6 +2460,7 @@ impl Clean<Item> for ast::ForeignItem {
                     generics: generics.clean(cx),
                     unsafety: ast::Unsafety::Unsafe,
                     abi: abi::Rust,
+                    constness: ast::Constness::NotConst,
                 })
             }
             ast::ForeignItemStatic(ref ty, mutbl) => {
@@ -2498,7 +2506,7 @@ fn lit_to_string(lit: &ast::Lit) -> String {
         ast::LitStr(ref st, _) => st.to_string(),
         ast::LitBinary(ref data) => format!("{:?}", data),
         ast::LitByte(b) => {
-            let mut res = String::from_str("b'");
+            let mut res = String::from("b'");
             for c in (b as char).escape_default() {
                 res.push(c);
             }
@@ -2572,10 +2580,7 @@ fn resolve_type(cx: &DocContext,
         None => panic!("unresolved id not in defmap")
     };
 
-    match def {
-        def::DefSelfTy(..) if path.segments.len() == 1 => {
-            return Generic(token::get_name(special_idents::type_self.name).to_string());
-        }
+    let is_generic = match def {
         def::DefPrimTy(p) => match p {
             ast::TyStr => return Primitive(Str),
             ast::TyBool => return Primitive(Bool),
@@ -2593,13 +2598,14 @@ fn resolve_type(cx: &DocContext,
             ast::TyFloat(ast::TyF32) => return Primitive(F32),
             ast::TyFloat(ast::TyF64) => return Primitive(F64),
         },
-        def::DefTyParam(_, _, _, n) => {
-            return Generic(token::get_name(n).to_string())
+        def::DefSelfTy(..) if path.segments.len() == 1 => {
+            return Generic(token::get_name(special_idents::type_self.name).to_string());
         }
-        _ => {}
+        def::DefSelfTy(..) | def::DefTyParam(..) => true,
+        _ => false,
     };
     let did = register_def(&*cx, def);
-    ResolvedPath { path: path, typarams: None, did: did }
+    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
 }
 
 fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
@@ -2687,6 +2693,21 @@ impl Clean<Stability> for attr::Stability {
     }
 }
 
+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()),
+        }
+    }
+}
+
 impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
@@ -2701,43 +2722,40 @@ impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
     }
 }
 
-impl Clean<Item> for ty::AssociatedType {
+impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
-        // When loading a cross-crate associated type, the bounds for this type
-        // are actually located on the trait/impl itself, so we need to load
-        // all of the generics from there and then look for bounds that are
-        // applied to this associated type in question.
-        let predicates = ty::lookup_predicates(cx.tcx(), self.container.id());
-        let generics = match self.container {
-            ty::TraitContainer(did) => {
-                let def = ty::lookup_trait_def(cx.tcx(), did);
-                (&def.generics, &predicates, subst::TypeSpace).clean(cx)
-            }
-            ty::ImplContainer(did) => {
-                let ty = ty::lookup_item_type(cx.tcx(), did);
-                (&ty.generics, &predicates, subst::TypeSpace).clean(cx)
-            }
-        };
         let my_name = self.name.clean(cx);
-        let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
-            let (name, self_type, trait_, bounds) = match *pred {
-                WherePredicate::BoundPredicate {
-                    ty: QPath { ref name, ref self_type, ref trait_ },
-                    ref bounds
-                } => (name, self_type, trait_, bounds),
-                _ => return None,
-            };
-            if *name != my_name { return None }
-            match **trait_ {
-                ResolvedPath { did, .. } if did == self.container.id() => {}
-                _ => return None,
-            }
-            match **self_type {
-                Generic(ref s) if *s == "Self" => {}
-                _ => return None,
-            }
-            Some(bounds)
-        }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
+
+        let mut bounds = if let ty::TraitContainer(did) = self.container {
+            // When loading a cross-crate associated type, the bounds for this type
+            // are actually located on the trait/impl itself, so we need to load
+            // all of the generics from there and then look for bounds that are
+            // applied to this associated type in question.
+            let def = ty::lookup_trait_def(cx.tcx(), did);
+            let predicates = ty::lookup_predicates(cx.tcx(), did);
+            let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
+            generics.where_predicates.iter().filter_map(|pred| {
+                let (name, self_type, trait_, bounds) = match *pred {
+                    WherePredicate::BoundPredicate {
+                        ty: QPath { ref name, ref self_type, ref trait_ },
+                        ref bounds
+                    } => (name, self_type, trait_, bounds),
+                    _ => return None,
+                };
+                if *name != my_name { return None }
+                match **trait_ {
+                    ResolvedPath { did, .. } if did == self.container.id() => {}
+                    _ => return None,
+                }
+                match **self_type {
+                    Generic(ref s) if *s == "Self" => {}
+                    _ => return None,
+                }
+                Some(bounds)
+            }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
+        } else {
+            vec![]
+        };
 
         // Our Sized/?Sized bound didn't get handled when creating the generics
         // because we didn't actually get our whole set of bounds until just now
@@ -2753,7 +2771,7 @@ impl Clean<Item> for ty::AssociatedType {
             source: DUMMY_SP.clean(cx),
             name: Some(self.name.clean(cx)),
             attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
-            inner: AssociatedTypeItem(bounds, None),
+            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
             visibility: self.vis.clean(cx),
             def_id: self.def_id,
             stability: stability::lookup(cx.tcx(), self.def_id).clean(cx),
@@ -2798,6 +2816,7 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
                 }
             }],
         },
+        is_generic: false,
     }
 }
 
index 03f056a69232ed5d30a6ea8c77e6a87e95150deb..2bde8d5bfb5fc02733ae62ad39735dd4a0459f77 100644 (file)
@@ -139,7 +139,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
 }
 
 pub fn ty_params(mut params: Vec<clean::TyParam>) -> Vec<clean::TyParam> {
-    for param in params.iter_mut() {
+    for param in &mut params {
         param.bounds = ty_bounds(mem::replace(&mut param.bounds, Vec::new()));
     }
     return params;
@@ -165,7 +165,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: ast::DefId,
             } if *s == "Self" => Some(bounds),
             _ => None,
         }
-    }).flat_map(|bounds| bounds.iter()).any(|bound| {
+    }).flat_map(|bounds| bounds).any(|bound| {
         let poly_trait = match *bound {
             clean::TraitBound(ref t, _) => t,
             _ => return false,
index 1b74123c4adcde4a9fa17c9d2517e0d64a5354ae..ba9caa2f3f3568d280edd788a079f47b811740db 100644 (file)
@@ -12,13 +12,14 @@ pub use self::MaybeTyped::*;
 use rustc_lint;
 use rustc_driver::driver;
 use rustc::session::{self, config};
-use rustc::session::config::UnstableFeatures;
 use rustc::middle::{privacy, ty};
+use rustc::ast_map;
 use rustc::lint;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
 
-use syntax::{ast, ast_map, codemap, diagnostic};
+use syntax::{ast, codemap, diagnostic};
+use syntax::feature_gate::UnstableFeatures;
 
 use std::cell::{RefCell, Cell};
 use std::collections::{HashMap, HashSet};
@@ -31,17 +32,17 @@ pub use rustc::session::config::Input;
 pub use rustc::session::search_paths::SearchPaths;
 
 /// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
-pub enum MaybeTyped<'tcx> {
-    Typed(ty::ctxt<'tcx>),
+pub enum MaybeTyped<'a, 'tcx: 'a> {
+    Typed(&'a ty::ctxt<'tcx>),
     NotTyped(session::Session)
 }
 
 pub type ExternalPaths = RefCell<Option<HashMap<ast::DefId,
                                                 (Vec<String>, clean::TypeKind)>>>;
 
-pub struct DocContext<'tcx> {
+pub struct DocContext<'a, 'tcx: 'a> {
     pub krate: &'tcx ast::Crate,
-    pub maybe_typed: MaybeTyped<'tcx>,
+    pub maybe_typed: MaybeTyped<'a, 'tcx>,
     pub input: Input,
     pub external_paths: ExternalPaths,
     pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>,
@@ -51,17 +52,17 @@ pub struct DocContext<'tcx> {
     pub deref_trait_did: Cell<Option<ast::DefId>>,
 }
 
-impl<'tcx> DocContext<'tcx> {
+impl<'b, 'tcx> DocContext<'b, 'tcx> {
     pub fn sess<'a>(&'a self) -> &'a session::Session {
         match self.maybe_typed {
-            Typed(ref tcx) => &tcx.sess,
+            Typed(tcx) => &tcx.sess,
             NotTyped(ref sess) => sess
         }
     }
 
     pub fn tcx_opt<'a>(&'a self) -> Option<&'a ty::ctxt<'tcx>> {
         match self.maybe_typed {
-            Typed(ref tcx) => Some(tcx),
+            Typed(tcx) => Some(tcx),
             NotTyped(_) => None
         }
     }
@@ -105,14 +106,14 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
         target_triple: triple.unwrap_or(config::host_triple().to_string()),
         cfg: config::parse_cfgspecs(cfgs),
         // Ensure that rustdoc works even if rustc is feature-staged
-        unstable_features: UnstableFeatures::Default,
+        unstable_features: UnstableFeatures::Allow,
         ..config::basic_options().clone()
     };
 
     let codemap = codemap::CodeMap::new();
-    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
+    let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, codemap);
+        diagnostic::SpanHandler::new(diagnostic_handler, codemap);
 
     let sess = session::build_session_(sessopts, cpath,
                                        span_diagnostic_handler);
@@ -132,48 +133,49 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     let arenas = ty::CtxtArenas::new();
     let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
 
-    let ty::CrateAnalysis {
-        exported_items, public_items, ty_cx, ..
-    } = driver::phase_3_run_analysis_passes(sess,
-                                            ast_map,
-                                            &arenas,
-                                            name,
-                                            resolve::MakeGlobMap::No);
-
-    let ctxt = DocContext {
-        krate: ty_cx.map.krate(),
-        maybe_typed: Typed(ty_cx),
-        input: input,
-        external_traits: RefCell::new(Some(HashMap::new())),
-        external_typarams: RefCell::new(Some(HashMap::new())),
-        external_paths: RefCell::new(Some(HashMap::new())),
-        inlined: RefCell::new(Some(HashSet::new())),
-        populated_crate_impls: RefCell::new(HashSet::new()),
-        deref_trait_did: Cell::new(None),
-    };
-    debug!("crate: {:?}", ctxt.krate);
-
-    let mut analysis = CrateAnalysis {
-        exported_items: exported_items,
-        public_items: public_items,
-        external_paths: RefCell::new(None),
-        external_typarams: RefCell::new(None),
-        inlined: RefCell::new(None),
-        deref_trait_did: None,
-    };
-
-    let krate = {
-        let mut v = RustdocVisitor::new(&ctxt, Some(&analysis));
-        v.visit(ctxt.krate);
-        v.clean(&ctxt)
-    };
-
-    let external_paths = ctxt.external_paths.borrow_mut().take();
-    *analysis.external_paths.borrow_mut() = external_paths;
-    let map = ctxt.external_typarams.borrow_mut().take();
-    *analysis.external_typarams.borrow_mut() = map;
-    let map = ctxt.inlined.borrow_mut().take();
-    *analysis.inlined.borrow_mut() = map;
-    analysis.deref_trait_did = ctxt.deref_trait_did.get();
-    (krate, analysis)
+    driver::phase_3_run_analysis_passes(sess,
+                                        ast_map,
+                                        &arenas,
+                                        name,
+                                        resolve::MakeGlobMap::No,
+                                        |tcx, analysis| {
+        let ty::CrateAnalysis { exported_items, public_items, .. } = analysis;
+
+        let ctxt = DocContext {
+            krate: tcx.map.krate(),
+            maybe_typed: Typed(tcx),
+            input: input,
+            external_traits: RefCell::new(Some(HashMap::new())),
+            external_typarams: RefCell::new(Some(HashMap::new())),
+            external_paths: RefCell::new(Some(HashMap::new())),
+            inlined: RefCell::new(Some(HashSet::new())),
+            populated_crate_impls: RefCell::new(HashSet::new()),
+            deref_trait_did: Cell::new(None),
+        };
+        debug!("crate: {:?}", ctxt.krate);
+
+        let mut analysis = CrateAnalysis {
+            exported_items: exported_items,
+            public_items: public_items,
+            external_paths: RefCell::new(None),
+            external_typarams: RefCell::new(None),
+            inlined: RefCell::new(None),
+            deref_trait_did: None,
+        };
+
+        let krate = {
+            let mut v = RustdocVisitor::new(&ctxt, Some(&analysis));
+            v.visit(ctxt.krate);
+            v.clean(&ctxt)
+        };
+
+        let external_paths = ctxt.external_paths.borrow_mut().take();
+        *analysis.external_paths.borrow_mut() = external_paths;
+        let map = ctxt.external_typarams.borrow_mut().take();
+        *analysis.external_typarams.borrow_mut() = map;
+        let map = ctxt.inlined.borrow_mut().take();
+        *analysis.inlined.borrow_mut() = map;
+        analysis.deref_trait_did = ctxt.deref_trait_did.get();
+        (krate, analysis)
+    }).1
 }
index 8fa92304d249cb9d3adcfdba00d3b77e6250992c..cadd43ec6bfd8eee0c380883c677d55603c4bbb4 100644 (file)
@@ -133,6 +133,7 @@ pub struct Function {
     pub vis: ast::Visibility,
     pub stab: Option<attr::Stability>,
     pub unsafety: ast::Unsafety,
+    pub constness: ast::Constness,
     pub whence: Span,
     pub generics: ast::Generics,
     pub abi: abi::Abi,
index bb53d532f52f725b00453ad44dda63a16e221b70..9439fc3c5f405ffedf729376462f0dc3f5c491e6 100644 (file)
@@ -35,6 +35,10 @@ pub struct VisSpace(pub Option<ast::Visibility>);
 /// space after it.
 #[derive(Copy, Clone)]
 pub struct UnsafetySpace(pub ast::Unsafety);
+/// Similarly to VisSpace, this structure is used to render a function constness
+/// with a space after it.
+#[derive(Copy, Clone)]
+pub struct ConstnessSpace(pub ast::Constness);
 /// Wrapper struct for properly emitting a method declaration.
 pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
 /// Similar to VisSpace, but used for mutability
@@ -63,6 +67,12 @@ impl UnsafetySpace {
     }
 }
 
+impl ConstnessSpace {
+    pub fn get(&self) -> ast::Constness {
+        let ConstnessSpace(v) = *self; v
+    }
+}
+
 impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for (i, item) in self.0.iter().enumerate() {
@@ -325,8 +335,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, path: &clean::Path,
     if print_all {
         let amt = path.segments.len() - 1;
         match rel_root {
-            Some(root) => {
-                let mut root = String::from_str(&root);
+            Some(mut root) => {
                 for seg in &path.segments[..amt] {
                     if "super" == seg.name || "self" == seg.name {
                         try!(write!(w, "{}::", seg.name));
@@ -427,9 +436,9 @@ impl fmt::Display for clean::Type {
             clean::Generic(ref name) => {
                 f.write_str(name)
             }
-            clean::ResolvedPath{ did, ref typarams, ref path } => {
-                // Paths like Self::Output should be rendered with all segments
-                try!(resolved_path(f, did, path, path.segments[0].name == "Self"));
+            clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
+                // Paths like T::Output and Self::Output should be rendered with all segments
+                try!(resolved_path(f, did, path, is_generic));
                 tybounds(f, typarams)
             }
             clean::Infer => write!(f, "_"),
@@ -607,6 +616,15 @@ impl fmt::Display for UnsafetySpace {
     }
 }
 
+impl fmt::Display for ConstnessSpace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.get() {
+            ast::Constness::Const => write!(f, "const "),
+            ast::Constness::NotConst => Ok(())
+        }
+    }
+}
+
 impl fmt::Display for clean::Import {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
index d19ccabed478efdb392b7830ad67def89cbf81f3..e375ec3afc2545a7c5259e87ab35c6bd1b2878ec 100644 (file)
@@ -24,10 +24,8 @@ use syntax::parse;
 /// Highlights some source code, returning the HTML output.
 pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String {
     debug!("highlighting: ================\n{}\n==============", src);
-    let sess = parse::new_parse_sess();
-    let fm = parse::string_to_filemap(&sess,
-                                      src.to_string(),
-                                      "<stdin>".to_string());
+    let sess = parse::ParseSess::new();
+    let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
 
     let mut out = Vec::new();
     doit(&sess,
@@ -62,7 +60,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
     loop {
         let next = lexer.next_token();
 
-        let snip = |sp| sess.span_diagnostic.cm.span_to_snippet(sp).unwrap();
+        let snip = |sp| sess.codemap().span_to_snippet(sp).unwrap();
 
         if next.tok == token::Eof { break }
 
@@ -178,7 +176,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
 
         // as mentioned above, use the original source code instead of
         // stringifying this token
-        let snip = sess.span_diagnostic.cm.span_to_snippet(next.sp).unwrap();
+        let snip = sess.codemap().span_to_snippet(next.sp).unwrap();
         if klass == "" {
             try!(write!(out, "{}", Escape(&snip)));
         } else {
index 66c5a4e0db2366a6c303b69b2d96ff4bdba323ef..4982215d02f49f45d81e2a0f1c747cebcbda41de 100644 (file)
@@ -252,8 +252,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                     s.push_str(&format!("<span class='rusttest'>{}</span>", Escape(&test)));
                 });
                 s.push_str(&highlight::highlight(&text,
-                                                 None,
-                                                 Some("rust-example-rendered")));
+                                                 Some("rust-example-rendered"),
+                                                 None));
                 let output = CString::new(s).unwrap();
                 hoedown_buffer_puts(ob, output.as_ptr());
             })
index 36cf650d54e9af91d2c395d431ee9d2fab1f00fb..0080b5e5f223f6af1b6abf306d9a1b2ad7427a24 100644 (file)
@@ -51,25 +51,20 @@ use std::sync::Arc;
 
 use externalfiles::ExternalHtml;
 
-use serialize::json;
-use serialize::json::ToJson;
-use syntax::abi;
-use syntax::ast;
-use syntax::ast_util;
-use syntax::attr;
+use serialize::json::{self, ToJson};
+use syntax::{abi, ast, ast_util, attr};
 use rustc::util::nodemap::NodeSet;
 
-use clean;
+use clean::{self, SelfTy};
 use doctree;
 use fold::DocFolder;
 use html::escape::Escape;
+use html::format::{ConstnessSpace};
 use html::format::{TyParamBounds, WhereClause, href, AbiSpace};
 use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
-use html::highlight;
 use html::item_type::ItemType;
-use html::layout;
-use html::markdown::Markdown;
-use html::markdown;
+use html::markdown::{self, Markdown};
+use html::{highlight, layout};
 
 /// A pair of name and its optional document.
 pub type NameDoc = (String, Option<String>);
@@ -461,13 +456,15 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
             let did = ast_util::local_def(pid);
             match paths.get(&did) {
                 Some(&(ref fqp, _)) => {
+                    // Needed to determine `self` type.
+                    let parent_basename = Some(fqp[fqp.len() - 1].clone());
                     search_index.push(IndexItem {
                         ty: shortty(item),
                         name: item.name.clone().unwrap(),
                         path: fqp[..fqp.len() - 1].connect("::"),
                         desc: shorter(item.doc_value()),
                         parent: Some(did),
-                        search_type: None,
+                        search_type: get_index_search_type(&item, parent_basename),
                     });
                 },
                 None => {}
@@ -476,7 +473,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
 
         // Reduce `NodeId` in paths into smaller sequential numbers,
         // and prune the paths that do not appear in the index.
-        for item in &*search_index {
+        for item in search_index.iter() {
             match item.parent {
                 Some(nodeid) => {
                     if !nodeid_to_pathid.contains_key(&nodeid) {
@@ -822,7 +819,7 @@ impl<'a> SourceCollector<'a> {
 
         // Create the intermediate directories
         let mut cur = self.dst.clone();
-        let mut root_path = String::from_str("../../");
+        let mut root_path = String::from("../../");
         clean_srcpath(&self.cx.src_root, &p, false, |component| {
             cur.push(component);
             mkdir(&cur).unwrap();
@@ -870,7 +867,7 @@ impl DocFolder for Cache {
             clean::StructItem(ref s)          => self.generics(&s.generics),
             clean::EnumItem(ref e)            => self.generics(&e.generics),
             clean::FunctionItem(ref f)        => self.generics(&f.generics),
-            clean::TypedefItem(ref t)         => self.generics(&t.generics),
+            clean::TypedefItem(ref t, _)      => self.generics(&t.generics),
             clean::TraitItem(ref t)           => self.generics(&t.generics),
             clean::ImplItem(ref i)            => self.generics(&i.generics),
             clean::TyMethodItem(ref i)        => self.generics(&i.generics),
@@ -936,6 +933,10 @@ impl DocFolder for Cache {
                         ((Some(*last), path), true)
                     }
                 }
+                clean::TypedefItem(_, true) => {
+                    // skip associated types in impls
+                    ((None, None), false)
+                }
                 _ => ((None, Some(&*self.stack)), false)
             };
             let hidden_field = match item.inner {
@@ -1497,7 +1498,7 @@ impl<'a> fmt::Display for Item<'a> {
             clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t),
             clean::StructItem(ref s) => item_struct(fmt, self.item, s),
             clean::EnumItem(ref e) => item_enum(fmt, self.item, e),
-            clean::TypedefItem(ref t) => item_typedef(fmt, self.item, t),
+            clean::TypedefItem(ref t, _) => item_typedef(fmt, self.item, t),
             clean::MacroItem(ref m) => item_macro(fmt, self.item, m),
             clean::PrimitiveItem(ref p) => item_primitive(fmt, self.item, p),
             clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
@@ -1753,11 +1754,12 @@ fn item_static(w: &mut fmt::Formatter, it: &clean::Item,
 
 fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
                  f: &clean::Function) -> fmt::Result {
-    try!(write!(w, "<pre class='rust fn'>{vis}{unsafety}{abi}fn \
+    try!(write!(w, "<pre class='rust fn'>{vis}{unsafety}{abi}{constness}fn \
                     {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(it.visibility),
            unsafety = UnsafetySpace(f.unsafety),
            abi = AbiSpace(f.abi),
+           constness = ConstnessSpace(f.constness),
            name = it.name.as_ref().unwrap(),
            generics = f.generics,
            where_clause = WhereClause(&f.generics),
@@ -1957,10 +1959,16 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
 
 fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
                      link: AssocItemLink) -> fmt::Result {
-    fn method(w: &mut fmt::Formatter, it: &clean::Item,
-              unsafety: ast::Unsafety, abi: abi::Abi,
-              g: &clean::Generics, selfty: &clean::SelfTy,
-              d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result {
+    fn method(w: &mut fmt::Formatter,
+              it: &clean::Item,
+              unsafety: ast::Unsafety,
+              constness: ast::Constness,
+              abi: abi::Abi,
+              g: &clean::Generics,
+              selfty: &clean::SelfTy,
+              d: &clean::FnDecl,
+              link: AssocItemLink)
+              -> fmt::Result {
         use syntax::abi::Abi;
 
         let name = it.name.as_ref().unwrap();
@@ -1971,12 +1979,10 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
                 href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
             }
         };
-        write!(w, "{}{}fn <a href='{href}' class='fnname'>{name}</a>\
+        write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
-               match unsafety {
-                   ast::Unsafety::Unsafe => "unsafe ",
-                   _ => "",
-               },
+               UnsafetySpace(unsafety),
+               ConstnessSpace(constness),
                match abi {
                    Abi::Rust => String::new(),
                    a => format!("extern {} ", a.to_string())
@@ -1989,11 +1995,12 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
     }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
-            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
-                   link)
+            method(w, meth, m.unsafety, ast::Constness::NotConst,
+                   m.abi, &m.generics, &m.self_, &m.decl, link)
         }
         clean::MethodItem(ref m) => {
-            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
+            method(w, meth, m.unsafety, m.constness,
+                   m.abi, &m.generics, &m.self_, &m.decl,
                    link)
         }
         clean::AssociatedConstItem(ref ty, ref default) => {
@@ -2279,7 +2286,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
         }
         try!(write!(w, "<h2 id='implementations'>Trait \
                           Implementations</h2>"));
-        let (derived, manual): (Vec<_>, _) = traits.iter().partition(|i| {
+        let (derived, manual): (Vec<_>, Vec<&Impl>) = traits.iter().partition(|i| {
             i.impl_.derived
         });
         for i in &manual {
@@ -2303,10 +2310,10 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
     let deref_type = impl_.impl_.trait_.as_ref().unwrap();
     let target = impl_.impl_.items.iter().filter_map(|item| {
         match item.inner {
-            clean::TypedefItem(ref t) => Some(&t.type_),
+            clean::TypedefItem(ref t, true) => Some(&t.type_),
             _ => None,
         }
-    }).next().unwrap();
+    }).next().expect("Expected associated type binding");
     let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target };
     match *target {
         clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what),
@@ -2322,6 +2329,9 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
     }
 }
 
+// Render_header is false when we are rendering a `Deref` impl and true
+// otherwise. If render_header is false, we will avoid rendering static
+// methods, since they are not accessible for the type implementing `Deref`
 fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
                render_header: bool) -> fmt::Result {
     if render_header {
@@ -2341,16 +2351,19 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
     }
 
     fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
-                    link: AssocItemLink) -> fmt::Result {
+                    link: AssocItemLink, render_static: bool) -> fmt::Result {
         match item.inner {
             clean::MethodItem(..) | clean::TyMethodItem(..) => {
-                try!(write!(w, "<h4 id='method.{}' class='{}'><code>",
-                            *item.name.as_ref().unwrap(),
-                            shortty(item)));
+                // Only render when the method is not static or we allow static methods
+                if !is_static_method(item) || render_static {
+                    try!(write!(w, "<h4 id='method.{}' class='{}'><code>",
+                                *item.name.as_ref().unwrap(),
+                                shortty(item)));
                 try!(render_assoc_item(w, item, link));
-                try!(write!(w, "</code></h4>\n"));
+                    try!(write!(w, "</code></h4>\n"));
+                }
             }
-            clean::TypedefItem(ref tydef) => {
+            clean::TypedefItem(ref tydef, _) => {
                 let name = item.name.as_ref().unwrap();
                 try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
                             *name,
@@ -2382,22 +2395,36 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
             }
             _ => panic!("can't make docs for trait item with name {:?}", item.name)
         }
-        if let AssocItemLink::Anchor = link {
-            document(w, item)
+
+        return if let AssocItemLink::Anchor = link {
+            if is_static_method(item) && !render_static {
+                Ok(())
+            } else {
+                document(w, item)
+            }
         } else {
             Ok(())
+        };
+
+        fn is_static_method(item: &clean::Item) -> bool {
+            match item.inner {
+                clean::MethodItem(ref method) => method.self_ == SelfTy::SelfStatic,
+                clean::TyMethodItem(ref method) => method.self_ == SelfTy::SelfStatic,
+                _ => false
+            }
         }
     }
 
     try!(write!(w, "<div class='impl-items'>"));
-    for trait_item in i.impl_.items.iter() {
-        try!(doctraititem(w, trait_item, link));
+    for trait_item in &i.impl_.items {
+        try!(doctraititem(w, trait_item, link, render_header));
     }
 
     fn render_default_items(w: &mut fmt::Formatter,
                             did: ast::DefId,
                             t: &clean::Trait,
-                            i: &clean::Impl) -> fmt::Result {
+                              i: &clean::Impl,
+                              render_static: bool) -> fmt::Result {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
             match i.items.iter().find(|m| { m.name == n }) {
@@ -2405,7 +2432,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
                 None => {}
             }
 
-            try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did)));
+            try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did), render_static));
         }
         Ok(())
     }
@@ -2416,7 +2443,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
     // for them work.
     if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ {
         if let Some(t) = cache().traits.get(&did) {
-            try!(render_default_items(w, did, t, &i.impl_));
+            try!(render_default_items(w, did, t, &i.impl_, render_header));
+
         }
     }
     try!(write!(w, "</div>"));
@@ -2425,10 +2453,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
 
 fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item,
                 t: &clean::Typedef) -> fmt::Result {
-    try!(write!(w, "<pre class='rust typedef'>type {}{} = {};</pre>",
+    try!(write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
                   it.name.as_ref().unwrap(),
                   t.generics,
-                  t.type_));
+                  where_clause = WhereClause(&t.generics),
+                  type_ = t.type_));
 
     document(w, it)
 }
index 2dc5ea9906744f751e14c0bb65ded041a6ea22c5..aaebdc34cd464729ca782eea957780be535fbbc6 100644 (file)
@@ -338,17 +338,17 @@ nav.sub {
     font-size: 1em;
     position: relative;
 }
-/* Shift "where ..." part of method definition down a line */
-.content .method .where { display: block; }
+/* Shift "where ..." part of method or fn definition down a line */
+.content .method .where, .content .fn .where { display: block; }
 /* Bit of whitespace to indent it */
-.content .method .where::before { content: '  '; }
+.content .method .where::before, .content .fn .where::before { content: '  '; }
 
 .content .methods > div { margin-left: 40px; }
 
 .content .impl-items .docblock, .content .impl-items .stability {
     margin-left: 40px;
 }
-.content .impl-items .method, .content .impl-items .type {
+.content .impl-items .method, .content .impl-items .type {
     margin-left: 20px;
 }
 
@@ -443,6 +443,8 @@ a {
 .content .search-results td:first-child { padding-right: 0; }
 .content .search-results td:first-child a { padding-right: 10px; }
 
+tr.result span.primitive::after { content: ' (primitive type)'; font-style: italic; }
+
 #help {
     background: #e9e9e9;
     border-radius: 4px;
index 932a536ab18875a6be23d3f3f02d9656a7bcad8f..fb8f511795e87d01d084460dd6ebed083b9184bb 100644 (file)
@@ -13,7 +13,6 @@
 
 (function() {
     "use strict";
-    var resizeTimeout, interval;
 
     // This mapping table should match the discriminants of
     // `rustdoc::html::item_type::ItemType` type in Rust.
@@ -37,6 +36,9 @@
                      "constant",
                      "associatedconstant"];
 
+    // used for special search precedence
+    var TY_PRIMITIVE = itemTypes.indexOf("primitive");
+
     $('.js-only').removeClass('js-only');
 
     function getQueryStringParams() {
@@ -64,7 +66,7 @@
             if ($('#' + from).length === 0) {
                 return;
             }
-            if (ev === null) $('#' + from)[0].scrollIntoView();
+            if (ev === null) { $('#' + from)[0].scrollIntoView(); };
             $('.line-numbers span').removeClass('line-highlighted');
             for (i = from; i <= to; ++i) {
                 $('#' + i).addClass('line-highlighted');
@@ -74,7 +76,7 @@
     highlightSourceLines(null);
     $(window).on('hashchange', highlightSourceLines);
 
-    $(document).on('keyup', function(e) {
+    $(document).on('keyup', function handleKeyboardShortcut(e) {
         if (document.activeElement.tagName === 'INPUT') {
             return;
         }
         return function(s1, s2) {
             if (s1 === s2) {
                 return 0;
-            } else {
-                var s1_len = s1.length, s2_len = s2.length;
-                if (s1_len && s2_len) {
-                    var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
-                    while (i1 < s1_len)
-                        row[i1] = ++i1;
-                    while (i2 < s2_len) {
-                        c2 = s2.charCodeAt(i2);
-                        a = i2;
-                        ++i2;
-                        b = i2;
-                        for (i1 = 0; i1 < s1_len; ++i1) {
-                            c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
-                            a = row[i1];
-                            b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
-                            row[i1] = b;
-                        }
+            }
+            var s1_len = s1.length, s2_len = s2.length;
+            if (s1_len && s2_len) {
+                var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
+                while (i1 < s1_len) {
+                    row[i1] = ++i1;
+                }
+                while (i2 < s2_len) {
+                    c2 = s2.charCodeAt(i2);
+                    a = i2;
+                    ++i2;
+                    b = i2;
+                    for (i1 = 0; i1 < s1_len; ++i1) {
+                        c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+                        a = row[i1];
+                        b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+                        row[i1] = b;
                     }
-                    return b;
-                } else {
-                    return s1_len + s2_len;
                 }
+                return b;
             }
+            return s1_len + s2_len;
         };
     })();
 
                 results = [],
                 split = valLower.split("::");
 
-            //remove empty keywords
+            // remove empty keywords
             for (var j = 0; j < split.length; ++j) {
                 split[j].toLowerCase();
                 if (split[j] === "") {
                 return [];
             }
 
-            results.sort(function(aaa, bbb) {
+            results.sort(function sortResults(aaa, bbb) {
                 var a, b;
 
                 // Sort by non levenshtein results and then levenshtein results by the distance
                 // (less changes required to match means higher rankings)
                 a = (aaa.lev);
                 b = (bbb.lev);
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by crate (non-current crate goes later)
                 a = (aaa.item.crate !== window.currentCrate);
                 b = (bbb.item.crate !== window.currentCrate);
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by exact match (mismatch goes later)
                 a = (aaa.word !== valLower);
                 b = (bbb.word !== valLower);
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by item name length (longer goes later)
                 a = aaa.word.length;
                 b = bbb.word.length;
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by item name (lexicographically larger goes later)
                 a = aaa.word;
                 b = bbb.word;
-                if (a !== b) return (a > b ? +1 : -1);
+                if (a !== b) { return (a > b ? +1 : -1); }
 
                 // sort by index of keyword in item name (no literal occurrence goes later)
                 a = (aaa.index < 0);
                 b = (bbb.index < 0);
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
                 // (later literal occurrence, if any, goes later)
                 a = aaa.index;
                 b = bbb.index;
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
+
+                // special precedence for primitive pages
+                if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
+                    return -1;
+                }
 
                 // sort by description (no description goes later)
                 a = (aaa.item.desc === '');
                 b = (bbb.item.desc === '');
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by type (later occurrence in `itemTypes` goes later)
                 a = aaa.item.ty;
                 b = bbb.item.ty;
-                if (a !== b) return a - b;
+                if (a !== b) { return a - b; }
 
                 // sort by path (lexicographically larger goes later)
                 a = aaa.item.path;
                 b = bbb.item.path;
-                if (a !== b) return (a > b ? +1 : -1);
+                if (a !== b) { return (a > b ? +1 : -1); }
 
                 // que sera, sera
                 return 0;
          * @return {[boolean]}       [Whether the result is valid or not]
          */
         function validateResult(name, path, keys, parent) {
-            for (var i=0; i < keys.length; ++i) {
+            for (var i = 0; i < keys.length; ++i) {
                 // each check is for validation so we negate the conditions and invalidate
                 if (!(
                     // check for an exact name match
                 raw: raw,
                 query: query,
                 type: type,
-                id: query + type,
+                id: query + type
             };
         }
 
 
             $results.on('click', function() {
                 var dst = $(this).find('a')[0];
-                if (window.location.pathname == dst.pathname) {
+                if (window.location.pathname === dst.pathname) {
                     $('#search').addClass('hidden');
                     $('#main').removeClass('hidden');
                     document.location.href = dst.href;
                 return;
             }
 
+            // Update document title to maintain a meaningful browser history
+            $(document).prop("title", "Results for " + query.query + " - Rust");
+
             // Because searching is incremental by character, only the most
             // recent search query is added to the browser history.
             if (browserSupportsHistoryApi()) {
 
         function itemTypeFromName(typename) {
             for (var i = 0; i < itemTypes.length; ++i) {
-                if (itemTypes[i] === typename) return i;
+                if (itemTypes[i] === typename) { return i; }
             }
             return -1;
         }
             searchIndex = [];
             var searchWords = [];
             for (var crate in rawSearchIndex) {
-                if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
+                if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
 
                 // an array of [(Number) item type,
                 //              (String) name,
         }
 
         function plainSummaryLine(markdown) {
-            var str = markdown.replace(/\n/g, ' ')
-            str = str.replace(/'/g, "\'")
-            str = str.replace(/^#+? (.+?)/, "$1")
-            str = str.replace(/\[(.*?)\]\(.*?\)/g, "$1")
-            str = str.replace(/\[(.*?)\]\[.*?\]/g, "$1")
-            return str;
+            markdown.replace(/\n/g, ' ')
+            .replace(/'/g, "\'")
+            .replace(/^#+? (.+?)/, "$1")
+            .replace(/\[(.*?)\]\(.*?\)/g, "$1")
+            .replace(/\[(.*?)\]\[.*?\]/g, "$1");
         }
 
         index = buildIndex(rawSearchIndex);
         startSearch();
 
         // Draw a convenient sidebar of known crates if we have a listing
-        if (rootPath == '../') {
+        if (rootPath === '../') {
             var sidebar = $('.sidebar');
             var div = $('<div>').attr('class', 'block crate');
             div.append($('<h2>').text('Crates'));
 
             var crates = [];
             for (var crate in rawSearchIndex) {
-                if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
+                if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
                 crates.push(crate);
             }
             crates.sort();
             for (var i = 0; i < crates.length; ++i) {
                 var klass = 'crate';
-                if (crates[i] == window.currentCrate) {
+                if (crates[i] === window.currentCrate) {
                     klass += ' current';
                 }
                 if (rawSearchIndex[crates[i]].items[0]) {
 
         function block(shortty, longty) {
             var filtered = items[shortty];
-            if (!filtered) return;
+            if (!filtered) { return; }
 
             var div = $('<div>').attr('class', 'block ' + shortty);
             div.append($('<h2>').text(longty));
                 var desc = item[1]; // can be null
 
                 var klass = shortty;
-                if (name === current.name && shortty == current.ty) {
+                if (name === current.name && shortty === current.ty) {
                     klass += ' current';
                 }
                 var path;
         var list = $('#implementors-list');
         var libs = Object.getOwnPropertyNames(imp);
         for (var i = 0; i < libs.length; ++i) {
-            if (libs[i] == currentCrate) continue;
+            if (libs[i] === currentCrate) { continue; }
             var structs = imp[libs[i]];
             for (var j = 0; j < structs.length; ++j) {
                 var code = $('<code>').append(structs[j]);
         if (sectionIsCollapsed) {
             // button will expand the section
             return "+";
-        } else {
-            // button will collapse the section
-            // note that this text is also set in the HTML template in render.rs
-            return "\u2212"; // "\u2212" is '−' minus sign
         }
+        // button will collapse the section
+        // note that this text is also set in the HTML template in render.rs
+        return "\u2212"; // "\u2212" is '−' minus sign
     }
 
     $("#toggle-all-docs").on("click", function() {
         }
         if (relatedDoc.is(".docblock")) {
             if (relatedDoc.is(":visible")) {
-                relatedDoc.slideUp({duration:'fast', easing:'linear'});
+                relatedDoc.slideUp({duration: 'fast', easing: 'linear'});
                 toggle.parent(".toggle-wrapper").addClass("collapsed");
                 toggle.children(".inner").text(labelForToggleButton(true));
                 toggle.children(".toggle-label").fadeIn();
             } else {
-                relatedDoc.slideDown({duration:'fast', easing:'linear'});
+                relatedDoc.slideDown({duration: 'fast', easing: 'linear'});
                 toggle.parent(".toggle-wrapper").removeClass("collapsed");
                 toggle.children(".inner").text(labelForToggleButton(false));
                 toggle.children(".toggle-label").hide();
                 $('<span/>', {'class': 'toggle-label'})
                     .css('display', 'none')
                     .html('&nbsp;Expand&nbsp;description'));
-        var wrapper =  $("<div class='toggle-wrapper'>").append(mainToggle);
+        var wrapper = $("<div class='toggle-wrapper'>").append(mainToggle);
         $("#main > .docblock").before(wrapper);
     });
 
         }
 
         return function(ev) {
-            var cur_id = parseInt(ev.target.id);
+            var cur_id = parseInt(ev.target.id, 10);
 
             if (ev.shiftKey && prev_id) {
                 if (prev_id > cur_id) {
index 06b3c4e42d6334c3f7e962dd6aa12de0c1ff1198..ff947d93fca16786e56fff3a4dd5ce22316439b6 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.
 //
 /*jslint browser: true, es5: true */
 /*globals $: true, rootPath: true */
 
-(function() {
-    if (window.playgroundUrl) {
-        $('pre.rust').hover(function() {
-            var a = $('<a>').text('⇱').attr('class', 'test-arrow');
-            var code = $(this).prev(".rusttest").text();
-            a.attr('href', window.playgroundUrl + '?code=' +
-                           encodeURIComponent(code));
-            a.attr('target', '_blank');
-            $(this).append(a);
-        }, function() {
-            $(this).find('a.test-arrow').remove();
-        });
+document.addEventListener('DOMContentLoaded', function() {
+    if (!window.playgroundUrl) {
+        return;
     }
-}());
+
+    var elements = document.querySelectorAll('pre.rust');
+
+    Array.prototype.forEach.call(elements, function(el) {
+        el.onmouseover = function(e) {
+            if (el.contains(e.relatedTarget)) {
+                return;
+            }
+
+            var a = document.createElement('a');
+            a.textContent = '⇱';
+            a.setAttribute('class', 'test-arrow');
+
+            var code = el.previousElementSibling.textContent;
+            a.setAttribute('href', window.playgroundUrl + '?code=' +
+                           encodeURIComponent(code));
+            a.setAttribute('target', '_blank');
+
+            el.appendChild(a);
+        };
+
+        el.onmouseout = function(e) {
+            if (el.contains(e.relatedTarget)) {
+                return;
+            }
+
+            el.removeChild(el.querySelectorAll('a.test-arrow')[0]);
+        };
+    });
+});
index 93aa74d7005f6d8989cbae865218d8d421165596..8f3e63820dac9ca30382c143a562278539b9e0b8 100644 (file)
@@ -145,7 +145,7 @@ impl TocBuilder {
                     (0, &self.top_level)
                 }
                 Some(entry) => {
-                    sec_number = String::from_str(&entry.sec_number);
+                    sec_number = entry.sec_number.clone();
                     sec_number.push_str(".");
                     (entry.level, &entry.children)
                 }
index 9c393d6f897372531de74158e42e40d56f4251a9..17d912dd4cb333936e16e21a0b0a0305414466e6 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-   html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+   html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
    html_root_url = "http://doc.rust-lang.org/nightly/",
    html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(exit_status)]
-#![feature(set_stdio)]
+#![feature(dynamic_lib)]
 #![feature(libc)]
+#![feature(owned_ascii_ext)]
+#![feature(path_ext)]
+#![feature(path_relative_from)]
 #![feature(rustc_private)]
+#![feature(set_stdio)]
+#![feature(slice_extras)]
+#![feature(slice_patterns)]
 #![feature(staged_api)]
-#![feature(std_misc)]
+#![feature(subslice_offset)]
 #![feature(test)]
 #![feature(unicode)]
-#![feature(path_ext)]
-#![feature(path_relative_from)]
-#![feature(slice_patterns)]
+#![feature(vec_push_all)]
 
 extern crate arena;
 extern crate getopts;
@@ -58,6 +60,7 @@ use std::env;
 use std::fs::File;
 use std::io::{self, Read, Write};
 use std::path::PathBuf;
+use std::process;
 use std::rc::Rc;
 use std::sync::mpsc::channel;
 
@@ -131,7 +134,7 @@ pub fn main() {
         let s = env::args().collect::<Vec<_>>();
         main_args(&s)
     }).unwrap().join().unwrap();
-    env::set_exit_status(res as i32);
+    process::exit(res as i32);
 }
 
 pub fn opts() -> Vec<getopts::OptGroup> {
index d4d214f449d5921733ca9c2c9c9140e23b02fd9b..e48651a154eb067ecbfb7990c1c04c6b0ac17484 100644 (file)
@@ -90,7 +90,7 @@ fn libname(mut n: String) -> String {
 
 #[cfg(all(not(target_os="windows"), not(target_os="macos")))]
 fn libname(n: String) -> String {
-    let mut i = String::from_str("lib");
+    let mut i = String::from("lib");
     i.push_str(&n);
     i.push_str(".so");
     i
index f8c2626d09e317668b9558a75abfa8ed75bd9d47..1ac95177860680cd7d59d710f3f0b9fa533e0d6c 100644 (file)
@@ -65,9 +65,9 @@ pub fn run(input: &str,
     };
 
     let codemap = CodeMap::new();
-    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
+    let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
     let span_diagnostic_handler =
-    diagnostic::mk_span_handler(diagnostic_handler, codemap);
+    diagnostic::SpanHandler::new(diagnostic_handler, codemap);
 
     let sess = session::build_session_(sessopts,
                                       Some(input_path.clone()),
@@ -75,7 +75,7 @@ pub fn run(input: &str,
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess);
-    cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
+    cfg.extend(config::parse_cfgspecs(cfgs));
     let krate = driver::phase_1_parse_input(&sess, cfg, &input);
     let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                      "rustdoc-test", None)
@@ -129,12 +129,13 @@ fn scrape_test_config(krate: &::syntax::ast::Crate) -> TestOptions {
         attrs: Vec::new(),
     };
 
-    let attrs = krate.attrs.iter().filter(|a| a.check_name("doc"))
+    let attrs = krate.attrs.iter()
+                     .filter(|a| a.check_name("doc"))
                      .filter_map(|a| a.meta_item_list())
-                     .flat_map(|l| l.iter())
+                     .flat_map(|l| l)
                      .filter(|a| a.check_name("test"))
                      .filter_map(|a| a.meta_item_list())
-                     .flat_map(|l| l.iter());
+                     .flat_map(|l| l);
     for attr in attrs {
         if attr.check_name("no_crate_inject") {
             opts.no_crate_inject = true;
@@ -184,7 +185,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     // it with a sink that is also passed to rustc itself. When this function
     // returns the output of the sink is copied onto the output of our own thread.
     //
-    // The basic idea is to not use a default_handler() for rustc, and then also
+    // The basic idea is to not use a default Handler for rustc, and then also
     // not print things by default to the actual stderr.
     struct Sink(Arc<Mutex<Vec<u8>>>);
     impl Write for Sink {
@@ -206,9 +207,9 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
 
     // Compile the code
     let codemap = CodeMap::new();
-    let diagnostic_handler = diagnostic::mk_handler(true, box emitter);
+    let diagnostic_handler = diagnostic::Handler::with_emitter(true, box emitter);
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, codemap);
+        diagnostic::SpanHandler::new(diagnostic_handler, codemap);
 
     let sess = session::build_session_(sessopts,
                                        None,
@@ -239,7 +240,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
         let path = env::var_os(var).unwrap_or(OsString::new());
         let mut path = env::split_paths(&path).collect::<Vec<_>>();
         path.insert(0, libdir.clone());
-        env::join_paths(path.iter()).unwrap()
+        env::join_paths(path).unwrap()
     };
     cmd.env(var, &newpath);
 
index 4ad693578ccdc312e3aed9aa689614abe19d0e68..305747d12824a7fd567b4393d13bf960b17f50c2 100644 (file)
@@ -17,11 +17,11 @@ use std::mem;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_util;
-use syntax::ast_map;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 
+use rustc::ast_map;
 use rustc::middle::stability;
 
 use core;
@@ -38,14 +38,14 @@ use doctree::*;
 pub struct RustdocVisitor<'a, 'tcx: 'a> {
     pub module: Module,
     pub attrs: Vec<ast::Attribute>,
-    pub cx: &'a core::DocContext<'tcx>,
+    pub cx: &'a core::DocContext<'a, 'tcx>,
     pub analysis: Option<&'a core::CrateAnalysis>,
     view_item_stack: HashSet<ast::NodeId>,
     inlining_from_glob: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
-    pub fn new(cx: &'a core::DocContext<'tcx>,
+    pub fn new(cx: &'a core::DocContext<'a, 'tcx>,
                analysis: Option<&'a core::CrateAnalysis>) -> RustdocVisitor<'a, 'tcx> {
         // If the root is reexported, terminate all recursion.
         let mut stack = HashSet::new();
@@ -61,7 +61,8 @@ 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, ast_util::local_def(id)))
+        self.cx.tcx_opt().and_then(
+            |tcx| stability::lookup(tcx, ast_util::local_def(id)).map(|x| x.clone()))
     }
 
     pub fn visit(&mut self, krate: &ast::Crate) {
@@ -123,7 +124,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     pub fn visit_fn(&mut self, item: &ast::Item,
                     name: ast::Ident, fd: &ast::FnDecl,
-                    unsafety: &ast::Unsafety, abi: &abi::Abi,
+                    unsafety: &ast::Unsafety,
+                    constness: ast::Constness,
+                    abi: &abi::Abi,
                     gen: &ast::Generics) -> Function {
         debug!("Visiting fn");
         Function {
@@ -136,6 +139,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             whence: item.span,
             generics: gen.clone(),
             unsafety: *unsafety,
+            constness: constness,
             abi: *abi,
         }
     }
@@ -291,8 +295,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.enums.push(self.visit_enum_def(item, name, ed, gen)),
             ast::ItemStruct(ref sd, ref gen) =>
                 om.structs.push(self.visit_struct_def(item, name, &**sd, gen)),
-            ast::ItemFn(ref fd, ref pur, ref abi, ref gen, _) =>
-                om.fns.push(self.visit_fn(item, name, &**fd, pur, abi, gen)),
+            ast::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
+                om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
+                                          constness, abi, gen)),
             ast::ItemTy(ref ty, ref gen) => {
                 let t = Typedef {
                     ty: ty.clone(),
index adc4f69334f17f0df7f722bdc1d6d6e01966ab7f..0096d8d22ae8a1827f43d558713873e86f281976 100644 (file)
 //!         val: num.to_json(),
 //!     }).unwrap();
 //!     println!("data: {}", data);
-//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539j"};
+//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
 //! }
 //! ```
 //!
@@ -457,7 +457,7 @@ fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult {
 
 fn fmt_number_or_null(v: f64) -> string::String {
     match v.classify() {
-        Fp::Nan | Fp::Infinite => string::String::from_str("null"),
+        Fp::Nan | Fp::Infinite => string::String::from("null"),
         _ if v.fract() != 0f64 => v.to_string(),
         _ => v.to_string() + ".0",
     }
index 7f3633eb5bddad53b2733c762cdaf619cf2c9820..e7d9751cf4bc6d85718d8f975155fa8cf5c261dd 100644 (file)
@@ -23,18 +23,20 @@ Core encoding and decoding interfaces.
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(box_syntax)]
 #![feature(collections)]
-#![feature(core)]
+#![feature(enumset)]
+#![feature(hashmap_hasher)]
+#![feature(num_bits_bytes)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(std_misc)]
-#![feature(unicode)]
 #![feature(str_char)]
+#![feature(unicode)]
+#![feature(vecmap)]
 #![cfg_attr(test, feature(test))]
 
 // test harness access
index ccc56960b02ce111877e9fe6c689988770ef548b..9b94b7f7003ed62f521e37eae944b7848cf61f66 100644 (file)
@@ -18,7 +18,7 @@ use ops::Range;
 use mem;
 
 /// Extension methods for ASCII-subset only operations on owned strings
-#[unstable(feature = "std_misc",
+#[unstable(feature = "owned_ascii_ext",
            reason = "would prefer to do this in a more general way")]
 pub trait OwnedAsciiExt {
     /// Converts the string to ASCII upper case:
@@ -189,8 +189,6 @@ impl AsciiExt for str {
     }
 }
 
-#[unstable(feature = "std_misc",
-           reason = "would prefer to do this in a more general way")]
 impl OwnedAsciiExt for String {
     #[inline]
     fn into_ascii_uppercase(self) -> String {
@@ -226,7 +224,7 @@ impl AsciiExt for [u8] {
     #[inline]
     fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
         self.len() == other.len() &&
-        self.iter().zip(other.iter()).all(|(a, b)| {
+        self.iter().zip(other).all(|(a, b)| {
             a.eq_ignore_ascii_case(b)
         })
     }
@@ -244,8 +242,6 @@ impl AsciiExt for [u8] {
     }
 }
 
-#[unstable(feature = "std_misc",
-           reason = "would prefer to do this in a more general way")]
 impl OwnedAsciiExt for Vec<u8> {
     #[inline]
     fn into_ascii_uppercase(mut self) -> Vec<u8> {
index 48f65a5abfd453927e0ccbc1b679ae2e6708c8f0..1dca3b77f3880ed9497a3560cbfa223f9bbda264 100644 (file)
@@ -43,8 +43,7 @@ use super::table::BucketState::{
 use super::state::HashState;
 
 const INITIAL_LOG2_CAP: usize = 5;
-#[unstable(feature = "std_misc")]
-pub const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
+const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
 
 /// The default behavior of HashMap implements a load factor of 90.9%.
 /// This behavior is characterized by the following condition:
@@ -539,12 +538,12 @@ impl<K, V, S> HashMap<K, V, S>
 {
     /// Creates an empty hashmap which will use the given hasher to hash keys.
     ///
-    /// The creates map has the default initial capacity.
+    /// The created map has the default initial capacity.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(hashmap_hasher)]
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
@@ -553,7 +552,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]
     pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
         HashMap {
             hash_state:    hash_state,
@@ -573,7 +572,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(hashmap_hasher)]
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
@@ -582,7 +581,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]
     pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
                                         -> HashMap<K, V, S> {
         let resize_policy = DefaultResizePolicy::new();
@@ -906,7 +905,7 @@ impl<K, V, S> HashMap<K, V, S>
     ///     *val *= 2;
     /// }
     ///
-    /// for (key, val) in map.iter() {
+    /// for (key, val) in &map {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
@@ -980,7 +979,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(drain)]
     /// use std::collections::HashMap;
     ///
     /// let mut a = HashMap::new();
@@ -995,7 +994,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<K, V> {
         fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
@@ -1222,7 +1221,7 @@ impl<K, V, S> Debug for HashMap<K, V, S>
     where K: Eq + Hash + Debug, V: Debug, S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish()
+        f.debug_map().entries(self.iter()).finish()
     }
 }
 
@@ -1308,7 +1307,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> {
 }
 
 /// HashMap drain iterator.
-#[unstable(feature = "std_misc",
+#[unstable(feature = "drain",
            reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, K: 'a, V: 'a> {
     inner: iter::Map<table::Drain<'a, K, V>, fn((SafeHash, K, V)) -> (K, V)>
@@ -1480,7 +1479,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
 }
 
 impl<'a, K, V> Entry<'a, K, V> {
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "entry",
                reason = "will soon be replaced by or_insert")]
     #[deprecated(since = "1.0",
                 reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
@@ -1596,14 +1595,14 @@ impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
 /// `Hasher`, but the hashers created by two different `RandomState`
 /// instances are unlikely to produce the same result for the same values.
 #[derive(Clone)]
-#[unstable(feature = "std_misc",
+#[unstable(feature = "hashmap_hasher",
            reason = "hashing an hash maps may be altered")]
 pub struct RandomState {
     k0: u64,
     k1: u64,
 }
 
-#[unstable(feature = "std_misc",
+#[unstable(feature = "hashmap_hasher",
            reason = "hashing an hash maps may be altered")]
 impl RandomState {
     /// Constructs a new `RandomState` that is initialized with random keys.
@@ -1615,7 +1614,7 @@ impl RandomState {
     }
 }
 
-#[unstable(feature = "std_misc",
+#[unstable(feature = "hashmap_hasher",
            reason = "hashing an hash maps may be altered")]
 impl HashState for RandomState {
     type Hasher = SipHasher;
index d6754f10335cab9f0810ff5b97b223f659885826..ba50b156ab230a3f52b001e30cde2dbaf33bcacb 100644 (file)
@@ -20,9 +20,11 @@ use iter::{Iterator, IntoIterator, ExactSizeIterator, FromIterator, Map, Chain,
 use ops::{BitOr, BitAnd, BitXor, Sub};
 use option::Option::{Some, None, self};
 
-use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState};
+use super::map::{self, HashMap, Keys, RandomState};
 use super::state::HashState;
 
+const INITIAL_CAPACITY: usize = 32;
+
 // Future Optimization (FIXME!)
 // =============================
 //
@@ -152,7 +154,7 @@ impl<T, S> HashSet<T, S>
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(hashmap_hasher)]
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
@@ -161,7 +163,7 @@ impl<T, S> HashSet<T, S>
     /// set.insert(2);
     /// ```
     #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]
     pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
         HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
     }
@@ -177,7 +179,7 @@ impl<T, S> HashSet<T, S>
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(hashmap_hasher)]
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
@@ -186,7 +188,7 @@ impl<T, S> HashSet<T, S>
     /// set.insert(1);
     /// ```
     #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]
     pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
                                         -> HashSet<T, S> {
         HashSet {
@@ -406,7 +408,7 @@ impl<T, S> HashSet<T, S>
 
     /// Clears the set, returning all elements in an iterator.
     #[inline]
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
@@ -585,7 +587,7 @@ impl<T, S> fmt::Debug for HashSet<T, S>
           S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish()
+        f.debug_set().entries(self.iter()).finish()
     }
 }
 
@@ -647,7 +649,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     ///
     /// let mut i = 0;
     /// let expected = [1, 2, 3, 4, 5];
-    /// for x in set.iter() {
+    /// for x in &set {
     ///     assert!(expected.contains(x));
     ///     i += 1;
     /// }
@@ -679,7 +681,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     ///
     /// let mut i = 0;
     /// let expected = [2, 3];
-    /// for x in set.iter() {
+    /// for x in &set {
     ///     assert!(expected.contains(x));
     ///     i += 1;
     /// }
@@ -711,7 +713,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     ///
     /// let mut i = 0;
     /// let expected = [1, 2, 4, 5];
-    /// for x in set.iter() {
+    /// for x in &set {
     ///     assert!(expected.contains(x));
     ///     i += 1;
     /// }
@@ -743,7 +745,7 @@ impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
     ///
     /// let mut i = 0;
     /// let expected = [1, 2];
-    /// for x in set.iter() {
+    /// for x in &set {
     ///     assert!(expected.contains(x));
     ///     i += 1;
     /// }
@@ -838,7 +840,7 @@ impl<T, S> IntoIterator for HashSet<T, S>
     /// let v: Vec<String> = set.into_iter().collect();
     ///
     /// // Will print in an arbitrary order.
-    /// for x in v.iter() {
+    /// for x in &v {
     ///     println!("{}", x);
     /// }
     /// ```
index 3a06d2d03bf3f7046ec7c74479f9936abb704be8..365e6268b3b0de25e3d1c6d2c136dcf1baf60985 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear")]
+
 use clone::Clone;
 use default::Default;
 use hash;
@@ -25,7 +27,6 @@ use marker;
 /// algorithm can implement the `Default` trait and create hash maps with the
 /// `DefaultState` structure. This state is 0-sized and will simply delegate
 /// to `Default` when asked to create a hasher.
-#[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
 pub trait HashState {
     /// Type of the hasher that will be created.
     type Hasher: hash::Hasher;
@@ -38,7 +39,6 @@ pub trait HashState {
 /// default trait.
 ///
 /// This struct has is 0-sized and does not need construction.
-#[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
 pub struct DefaultState<H>(marker::PhantomData<H>);
 
 impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
index 4841f36c7f74719d15e0a51fb20209f4399351f5..349462aebe31b47f72b6cd6dd835ac1f068af8c8 100644 (file)
@@ -15,7 +15,7 @@ use cmp;
 use hash::{Hash, Hasher};
 use iter::{Iterator, ExactSizeIterator};
 use marker::{Copy, Send, Sync, Sized, self};
-use mem::{min_align_of, size_of};
+use mem::{align_of, size_of};
 use mem;
 use num::wrapping::OverflowingOps;
 use ops::{Deref, DerefMut, Drop};
@@ -528,6 +528,7 @@ fn test_rounding() {
 
 // Returns a tuple of (key_offset, val_offset),
 // from the start of a mallocated array.
+#[inline]
 fn calculate_offsets(hashes_size: usize,
                      keys_size: usize, keys_align: usize,
                      vals_align: usize)
@@ -552,9 +553,9 @@ fn calculate_allocation(hash_size: usize, hash_align: usize,
                                                               vals_align);
     let (end_of_vals, oflo2) = vals_offset.overflowing_add(vals_size);
 
-    let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
+    let align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
 
-    (min_align, hash_offset, end_of_vals, oflo || oflo2)
+    (align, hash_offset, end_of_vals, oflo || oflo2)
 }
 
 #[test]
@@ -596,9 +597,9 @@ impl<K, V> RawTable<K, V> {
         // factored out into a different function.
         let (malloc_alignment, hash_offset, size, oflo) =
             calculate_allocation(
-                hashes_size, min_align_of::<u64>(),
-                keys_size,   min_align_of::< K >(),
-                vals_size,   min_align_of::< V >());
+                hashes_size, align_of::<u64>(),
+                keys_size,   align_of::< K >(),
+                vals_size,   align_of::< V >());
 
         assert!(!oflo, "capacity overflow");
 
@@ -629,8 +630,8 @@ impl<K, V> RawTable<K, V> {
         let buffer = *self.hashes as *mut u8;
         let (keys_offset, vals_offset, oflo) =
             calculate_offsets(hashes_size,
-                              keys_size, min_align_of::<K>(),
-                              min_align_of::<V>());
+                              keys_size, align_of::<K>(),
+                              align_of::<V>());
         debug_assert!(!oflo, "capacity overflow");
         unsafe {
             RawBucket {
@@ -1004,9 +1005,9 @@ impl<K, V> Drop for RawTable<K, V> {
         let keys_size = self.capacity * size_of::<K>();
         let vals_size = self.capacity * size_of::<V>();
         let (align, _, size, oflo) =
-            calculate_allocation(hashes_size, min_align_of::<u64>(),
-                                 keys_size, min_align_of::<K>(),
-                                 vals_size, min_align_of::<V>());
+            calculate_allocation(hashes_size, align_of::<u64>(),
+                                 keys_size, align_of::<K>(),
+                                 vals_size, align_of::<V>());
 
         debug_assert!(!oflo, "should be impossible");
 
index 1099bf108f1dbb7116798bb8c3c8969159ab39c3..c91ebc91ef38766b1ec6c94d5dd2645910d8967e 100644 (file)
@@ -66,7 +66,7 @@
 //! ### Use a `BTreeMap` when:
 //! * You're interested in what the smallest or largest key-value pair is.
 //! * You want to find the largest or smallest key that is smaller or larger
-//!   than something
+//!   than something.
 //! * You want to be able to get all of the entries in order on-demand.
 //! * You want a sorted map.
 //!
 //! relation to the number of elements in the collection.  VecMap should only be
 //! seriously considered for small keys.
 //!
-//! Note also that BTreeMap's precise preformance depends on the value of B.
+//! Note also that BTreeMap's precise performance depends on the value of B.
 //!
 //! # Correct and Efficient Usage of Collections
 //!
 //! contents by-value. This is great when the collection itself is no longer
 //! needed, and the values are needed elsewhere. Using `extend` with `into_iter`
 //! is the main way that contents of one collection are moved into another.
+//! `extend` automatically calls `into_iter`, and takes any `T: IntoIterator`.
 //! Calling `collect` on an iterator itself is also a great way to convert one
 //! collection into another. Both of these methods should internally use the
 //! capacity management tools discussed in the previous section to do this as
 //! ```
 //! let mut vec1 = vec![1, 2, 3, 4];
 //! let vec2 = vec![10, 20, 30, 40];
-//! vec1.extend(vec2.into_iter());
+//! vec1.extend(vec2);
 //! ```
 //!
 //! ```
 //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case
 //! the only valid operation is to `insert` a value into the entry. When this is
 //! done, the vacant entry is consumed and converted into a mutable reference to
-//! the the value that was inserted. This allows for further manipulation of the
+//! the value that was inserted. This allows for further manipulation of the
 //! value beyond the lifetime of the search itself. This is useful if complex
 //! logic needs to be performed on the value regardless of whether the value was
 //! just inserted.
 //! assert_eq!(count.get(&'s'), Some(&8));
 //!
 //! println!("Number of occurrences of each character");
-//! for (char, count) in count.iter() {
+//! for (char, count) in &count {
 //!     println!("{}: {}", char, count);
 //! }
 //! ```
 //! // Our clients.
 //! let mut blood_alcohol = BTreeMap::new();
 //!
-//! for id in orders.into_iter() {
+//! 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});
@@ -409,7 +410,7 @@ pub mod hash_set {
 
 /// Experimental support for providing custom hash algorithms to a HashMap and
 /// HashSet.
-#[unstable(feature = "std_misc", reason = "module was recently added")]
+#[unstable(feature = "hashmap_hasher", reason = "module was recently added")]
 pub mod hash_state {
     pub use super::hash::state::*;
 }
index 8b90fce6fc4fc075709c354600e9d1daf4b18782..ddafe416305e11efc7fa44527c25cc7dcabb5961 100644 (file)
@@ -12,7 +12,9 @@
 //!
 //! A simple wrapper over the platform's dynamic library facilities
 
-#![unstable(feature = "std_misc")]
+#![unstable(feature = "dynamic_lib",
+            reason = "API has not been scrutinized and is highly likely to \
+                      either disappear or change")]
 #![allow(missing_docs)]
 
 use prelude::v1::*;
@@ -211,8 +213,8 @@ mod dl {
     pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
         F: FnOnce() -> T,
     {
-        use sync::{StaticMutex, MUTEX_INIT};
-        static LOCK: StaticMutex = MUTEX_INIT;
+        use sync::StaticMutex;
+        static LOCK: StaticMutex = StaticMutex::new();
         unsafe {
             // dlerror isn't thread safe, so we need to lock around this entire
             // sequence
@@ -294,7 +296,7 @@ mod dl {
         let result = match filename {
             Some(filename) => {
                 let filename_str: Vec<_> =
-                    filename.encode_wide().chain(Some(0).into_iter()).collect();
+                    filename.encode_wide().chain(Some(0)).collect();
                 let result = unsafe {
                     LoadLibraryW(filename_str.as_ptr() as *const libc::c_void)
                 };
index 126ef38b9188fc657c3ca386a28a704239d1d866..2e00e126e2378f8b7f9d385e4d184ad35b9d4411 100644 (file)
@@ -23,8 +23,8 @@ use ffi::{OsStr, OsString};
 use fmt;
 use io;
 use path::{Path, PathBuf};
-use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
-use sync::{StaticMutex, MUTEX_INIT};
+use sync::atomic::{AtomicIsize, Ordering};
+use sync::StaticMutex;
 use sys::os as os_imp;
 
 /// Returns the current working directory as a `PathBuf`.
@@ -70,7 +70,7 @@ pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> {
     os_imp::chdir(p.as_ref())
 }
 
-static ENV_LOCK: StaticMutex = MUTEX_INIT;
+static ENV_LOCK: StaticMutex = StaticMutex::new();
 
 /// An iterator over a snapshot of the environment variables of this process.
 ///
@@ -365,7 +365,7 @@ pub struct JoinPathsError {
 /// if let Some(path) = env::var_os("PATH") {
 ///     let mut paths = env::split_paths(&path).collect::<Vec<_>>();
 ///     paths.push(PathBuf::from("/home/xyz/bin"));
-///     let new_path = env::join_paths(paths.iter()).unwrap();
+///     let new_path = env::join_paths(paths).unwrap();
 ///     env::set_var("PATH", &new_path);
 /// }
 /// ```
@@ -475,7 +475,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     os_imp::current_exe()
 }
 
-static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
+static EXIT_STATUS: AtomicIsize = AtomicIsize::new(0);
 
 /// Sets the process exit code
 ///
@@ -486,6 +486,7 @@ static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
 ///
 /// Note that this is not synchronized against modifications of other threads.
 #[unstable(feature = "exit_status", reason = "managing the exit status may change")]
+#[deprecated(since = "1.2.0", reason = "use process::exit instead")]
 pub fn set_exit_status(code: i32) {
     EXIT_STATUS.store(code as isize, Ordering::SeqCst)
 }
@@ -493,6 +494,7 @@ pub fn set_exit_status(code: i32) {
 /// Fetches the process's current exit code. This defaults to 0 and can change
 /// by calling `set_exit_status`.
 #[unstable(feature = "exit_status", reason = "managing the exit status may change")]
+#[deprecated(since = "1.2.0", reason = "use process::exit instead")]
 pub fn get_exit_status() -> i32 {
     EXIT_STATUS.load(Ordering::SeqCst) as i32
 }
@@ -598,40 +600,94 @@ pub fn page_size() -> usize {
 pub mod consts {
     /// A string describing the architecture of the CPU that this is currently
     /// in use.
+    ///
+    /// Some possible values:
+    ///
+    /// - x86
+    /// - x86_64
+    /// - arm
+    /// - aarch64
+    /// - mips
+    /// - mipsel
+    /// - powerpc
     #[stable(feature = "env", since = "1.0.0")]
     pub const ARCH: &'static str = super::arch::ARCH;
 
     /// The family of the operating system. In this case, `unix`.
+    ///
+    /// Some possible values:
+    ///
+    /// - unix
+    /// - windows
     #[stable(feature = "env", since = "1.0.0")]
     pub const FAMILY: &'static str = super::os::FAMILY;
 
     /// A string describing the specific operating system in use: in this
     /// case, `linux`.
+    ///
+    /// Some possible values:
+    ///
+    /// - linux
+    /// - macos
+    /// - ios
+    /// - freebsd
+    /// - dragonfly
+    /// - bitrig
+    /// - openbsd
+    /// - android
+    /// - windows
     #[stable(feature = "env", since = "1.0.0")]
     pub const OS: &'static str = super::os::OS;
 
     /// Specifies the filename prefix used for shared libraries on this
     /// platform: in this case, `lib`.
+    ///
+    /// Some possible values:
+    ///
+    /// - lib
+    /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
     pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
 
     /// Specifies the filename suffix used for shared libraries on this
     /// platform: in this case, `.so`.
+    ///
+    /// Some possible values:
+    ///
+    /// - .so
+    /// - .dylib
+    /// - .dll
     #[stable(feature = "env", since = "1.0.0")]
     pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
 
     /// Specifies the file extension used for shared libraries on this
     /// platform that goes after the dot: in this case, `so`.
+    ///
+    /// Some possible values:
+    ///
+    /// - .so
+    /// - .dylib
+    /// - .dll
     #[stable(feature = "env", since = "1.0.0")]
     pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
 
     /// Specifies the filename suffix used for executable binaries on this
     /// platform: in this case, the empty string.
+    ///
+    /// Some possible values:
+    ///
+    /// - exe
+    /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
     pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
 
     /// Specifies the file extension, if any, used for executable binaries
     /// on this platform: in this case, the empty string.
+    ///
+    /// Some possible values:
+    ///
+    /// - exe
+    /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
     pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
 
index 6d23df970000cab16ce5dbfa8473788abcb16875..b21b2edf2ecd81fe58209160d134a869f08dcf27 100644 (file)
@@ -48,7 +48,7 @@
 // reconsider what crate these items belong in.
 
 use any::TypeId;
-use boxed::{self, Box};
+use boxed::Box;
 use convert::From;
 use fmt::{self, Debug, Display};
 use marker::{Send, Sync, Reflect};
@@ -77,7 +77,7 @@ pub trait Error: Debug + Display + Reflect {
 
     /// Get the `TypeId` of `self`
     #[doc(hidden)]
-    #[unstable(feature = "core",
+    #[unstable(feature = "error_type_id",
                reason = "unclear whether to commit to this public implementation detail")]
     fn type_id(&self) -> TypeId where Self: 'static {
         TypeId::of::<Self>()
@@ -121,7 +121,7 @@ impl From<String> for Box<Error + Send + Sync> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
     fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
-        From::from(String::from_str(err))
+        From::from(String::from(err))
     }
 }
 
@@ -140,7 +140,7 @@ impl Error for str::Utf8Error {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Error for num::ParseIntError {
     fn description(&self) -> &str {
-        self.description()
+        self.__description()
     }
 }
 
@@ -249,7 +249,7 @@ impl Error {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
-                let raw = boxed::into_raw(self);
+                let raw = Box::into_raw(self);
                 let to: TraitObject =
                     transmute::<*mut Error, TraitObject>(raw);
 
index 04513e9d048bedfd5ec312119a9941c051fc780c..ffc204ada60fb92a0468654690c95afa0e51b6b3 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc")]
-
+use borrow::{Cow, ToOwned};
+use boxed::Box;
+use clone::Clone;
 use convert::{Into, From};
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
 use error::Error;
@@ -22,6 +23,7 @@ use ops::Deref;
 use option::Option::{self, Some, None};
 use result::Result::{self, Ok, Err};
 use slice;
+use str;
 use string::String;
 use vec::Vec;
 
@@ -53,17 +55,16 @@ use vec::Vec;
 ///     fn my_printer(s: *const libc::c_char);
 /// }
 ///
-/// let to_print = &b"Hello, world!"[..];
-/// let c_to_print = CString::new(to_print).unwrap();
+/// let c_to_print = CString::new("Hello, world!").unwrap();
 /// unsafe {
 ///     my_printer(c_to_print.as_ptr());
 /// }
 /// # }
 /// ```
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CString {
-    inner: Vec<u8>,
+    inner: Box<[u8]>,
 }
 
 /// Representation of a borrowed C string.
@@ -114,6 +115,26 @@ pub struct CString {
 ///     work(&s);
 /// }
 /// ```
+///
+/// Converting a foreign C string into a Rust `String`
+///
+/// ```no_run
+/// # #![feature(libc,cstr_to_str)]
+/// extern crate libc;
+/// use std::ffi::CStr;
+///
+/// extern { fn my_string() -> *const libc::c_char; }
+///
+/// fn my_string_safe() -> String {
+///     unsafe {
+///         CStr::from_ptr(my_string()).to_string_lossy().into_owned()
+///     }
+/// }
+///
+/// fn main() {
+///     println!("string: {}", my_string_safe());
+/// }
+/// ```
 #[derive(Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CStr {
@@ -176,7 +197,39 @@ impl CString {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
         v.push(0);
-        CString { inner: v }
+        CString { inner: v.into_boxed_slice() }
+    }
+
+    /// 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
+    /// using the pointer.
+    #[unstable(feature = "cstr_memory", reason = "recently added")]
+    // NB: may want to be called from_raw, needs to consider CStr::from_ptr,
+    //     Box::from_raw (or whatever it's currently called), and
+    //     slice::from_raw_parts
+    pub unsafe fn from_ptr(ptr: *const libc::c_char) -> CString {
+        let len = libc::strlen(ptr) + 1; // Including the NUL byte
+        let slice = slice::from_raw_parts(ptr, len as usize);
+        CString { inner: mem::transmute(slice) }
+    }
+
+    /// 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
+    /// should *not* use the standard C `free` function to deallocate
+    /// this string.
+    ///
+    /// Failure to call `from_ptr` will lead to a memory leak.
+    #[unstable(feature = "cstr_memory", reason = "recently added")]
+    // NB: may want to be called into_raw, see comments on from_ptr
+    pub fn into_ptr(self) -> *const libc::c_char {
+        // It is important that the bytes be sized to fit - we need
+        // the capacity to be determinable from the string length, and
+        // shrinking to fit is the only way to be sure.
+        Box::into_raw(self.inner) as *const libc::c_char
     }
 
     /// Returns the contents of this `CString` as a slice of bytes.
@@ -196,6 +249,13 @@ impl CString {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Clone for CString {
+    fn clone(&self) -> Self {
+        CString { inner: self.inner.to_owned().into_boxed_slice() }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Deref for CString {
     type Target = CStr;
@@ -328,6 +388,39 @@ impl CStr {
     pub fn to_bytes_with_nul(&self) -> &[u8] {
         unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
     }
+
+    /// Yields a `&str` slice if the `CStr` contains valid UTF-8.
+    ///
+    /// This function will calculate the length of this string and check for
+    /// UTF-8 validity, and then return the `&str` if it's valid.
+    ///
+    /// > **Note**: This method is currently implemented to check for validity
+    /// > after a 0-cost cast, but it is planned to alter its definition in the
+    /// > future to perform the length calculation in addition to the UTF-8
+    /// > check whenever this method is called.
+    #[unstable(feature = "cstr_to_str", reason = "recently added")]
+    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
+        // NB: When CStr is changed to perform the length check in .to_bytes() instead of in
+        // from_ptr(), it may be worth considering if this should be rewritten to do the UTF-8
+        // check inline with the length calculation instead of doing it afterwards.
+        str::from_utf8(self.to_bytes())
+    }
+
+    /// Converts a `CStr` into a `Cow<str>`.
+    ///
+    /// This function will calculate the length of this string (which normally
+    /// requires a linear amount of work to be done) and then return the
+    /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
+    /// with `U+FFFD REPLACEMENT CHARACTER`.
+    ///
+    /// > **Note**: This method is currently implemented to check for validity
+    /// > after a 0-cost cast, but it is planned to alter its definition in the
+    /// > future to perform the length calculation in addition to the UTF-8
+    /// > check whenever this method is called.
+    #[unstable(feature = "cstr_to_str", reason = "recently added")]
+    pub fn to_string_lossy(&self) -> Cow<str> {
+        String::from_utf8_lossy(self.to_bytes())
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -356,6 +449,7 @@ mod tests {
     use prelude::v1::*;
     use super::*;
     use libc;
+    use borrow::Cow::{Borrowed, Owned};
 
     #[test]
     fn c_to_rust() {
@@ -405,4 +499,20 @@ mod tests {
             assert_eq!(s.to_bytes_with_nul(), b"12\0");
         }
     }
+
+    #[test]
+    fn to_str() {
+        let data = b"123\xE2\x80\xA6\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+        unsafe {
+            assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…"));
+            assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…"));
+        }
+        let data = b"123\xE2\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+        unsafe {
+            assert!(CStr::from_ptr(ptr).to_str().is_err());
+            assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::<str>(format!("123\u{FFFD}")));
+        }
+    }
 }
index cfb6128620b7d44e76fb4ded4ccf2612299622a1..2b0f17fb2bb9c07be19e42d8dcc9d31805503878 100644 (file)
@@ -805,6 +805,8 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
 
 /// Rename a file or directory to a new name.
 ///
+/// This will not work if the new name is on a different mount point.
+///
 /// # Errors
 ///
 /// This function will return an error if the provided `from` doesn't exist, if
@@ -910,7 +912,7 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
 /// # Ok(())
 /// # }
 /// ```
-#[deprecated(since = "1.0.0",
+#[deprecated(since = "1.1.0",
              reason = "replaced with std::os::unix::fs::symlink and \
                        std::os::windows::fs::{symlink_file, symlink_dir}")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1060,20 +1062,19 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// # Examples
 ///
 /// ```
-/// # #![feature(path_ext)]
 /// use std::io;
-/// use std::fs::{self, PathExt, DirEntry};
+/// use std::fs::{self, DirEntry};
 /// use std::path::Path;
 ///
 /// // one possible implementation of fs::walk_dir only visiting files
-/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> {
-///     if dir.is_dir() {
+/// fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
+///     if try!(fs::metadata(dir)).is_dir() {
 ///         for entry in try!(fs::read_dir(dir)) {
 ///             let entry = try!(entry);
-///             if entry.path().is_dir() {
+///             if try!(fs::metadata(entry.path())).is_dir() {
 ///                 try!(visit_dirs(&entry.path(), cb));
 ///             } else {
-///                 cb(entry);
+///                 cb(&entry);
 ///             }
 ///         }
 ///     }
@@ -1139,8 +1140,9 @@ impl Iterator for WalkDir {
 
 /// Utility methods for paths.
 #[unstable(feature = "path_ext",
-           reason = "the precise set of methods exposed on this trait may \
-                     change and some methods may be removed")]
+           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.")]
 pub trait PathExt {
     /// Gets information on the file, directory, etc at this path.
     ///
index 43a2629261882fafecd531f7e242331c0bc2c809..1d0152e275117801482c1805699de2cace64784e 100644 (file)
@@ -27,6 +27,24 @@ use iter;
 /// For example, every call to `read` on `TcpStream` results in a system call.
 /// A `BufReader` performs large, infrequent reads on the underlying `Read`
 /// and maintains an in-memory buffer of the results.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::io::BufReader;
+/// use std::fs::File;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut f = try!(File::open("log.txt"));
+/// let mut reader = BufReader::new(f);
+///
+/// let mut line = String::new();
+/// let len = try!(reader.read_line(&mut line));
+/// println!("First line is {} bytes long", len);
+/// # Ok(())
+/// # }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufReader<R> {
     inner: R,
@@ -436,6 +454,8 @@ impl<W: Read + Write> Read for InternalBufWriter<W> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[deprecated(since = "1.2.0",
+             reason = "use the crates.io `bufstream` crate instead")]
 pub struct BufStream<S: Write> {
     inner: BufReader<InternalBufWriter<S>>
 }
@@ -443,6 +463,9 @@ pub struct BufStream<S: Write> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[deprecated(since = "1.2.0",
+             reason = "use the crates.io `bufstream` crate instead")]
+#[allow(deprecated)]
 impl<S: Read + Write> BufStream<S> {
     /// Creates a new buffered stream with explicitly listed capacities for the
     /// reader/writer buffer.
@@ -494,6 +517,7 @@ impl<S: Read + Write> BufStream<S> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[allow(deprecated)]
 impl<S: Read + Write> BufRead for BufStream<S> {
     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
     fn consume(&mut self, amt: usize) { self.inner.consume(amt) }
@@ -502,6 +526,7 @@ impl<S: Read + Write> BufRead for BufStream<S> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[allow(deprecated)]
 impl<S: Read + Write> Read for BufStream<S> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
@@ -511,6 +536,7 @@ impl<S: Read + Write> Read for BufStream<S> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[allow(deprecated)]
 impl<S: Read + Write> Write for BufStream<S> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.inner.get_mut().write(buf)
@@ -523,6 +549,7 @@ impl<S: Read + Write> Write for BufStream<S> {
 #[unstable(feature = "buf_stream",
            reason = "unsure about semantics of buffering two directions, \
                      leading to issues like #17136")]
+#[allow(deprecated)]
 impl<S: Write> fmt::Debug for BufStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
index 97c5a29d308a11c8975611bac9680094f78a153e..a66789bf2873dc01b08e86e6ad6fd745a6ceee6e 100644 (file)
@@ -37,7 +37,6 @@ pub struct Error {
     repr: Repr,
 }
 
-#[derive(Debug)]
 enum Repr {
     Os(i32),
     Custom(Box<Custom>),
@@ -95,6 +94,13 @@ pub enum ErrorKind {
     /// A parameter was incorrect.
     #[stable(feature = "rust1", since = "1.0.0")]
     InvalidInput,
+    /// Data not valid for the operation were encountered.
+    ///
+    /// Unlike `InvalidInput`, this typically means that the operation
+    /// parameters were valid, however the error was caused by malformed
+    /// input data.
+    #[stable(feature = "io_invalid_data", since = "1.2.0")]
+    InvalidData,
     /// The I/O operation's timeout expired, causing it to be canceled.
     #[stable(feature = "rust1", since = "1.0.0")]
     TimedOut,
@@ -116,7 +122,7 @@ pub enum ErrorKind {
     Other,
 
     /// Any I/O error not part of this list.
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "io_error_internals",
                reason = "better expressed through extensible enums that this \
                          enum cannot be exhaustively matched against")]
     #[doc(hidden)]
@@ -129,9 +135,7 @@ impl Error {
     ///
     /// This function is used to generically create I/O errors which do not
     /// originate from the OS itself. The `error` argument is an arbitrary
-    /// payload which will be contained in this `Error`. Accessors as well as
-    /// downcasting will soon be added to this type as well to access the custom
-    /// information.
+    /// payload which will be contained in this `Error`.
     ///
     /// # Examples
     ///
@@ -174,8 +178,9 @@ impl Error {
 
     /// Returns the OS error that this error represents (if any).
     ///
-    /// If this `Error` was constructed via `last_os_error` then this function
-    /// will return `Some`, otherwise it will return `None`.
+    /// If this `Error` was constructed via `last_os_error` or
+    /// `from_raw_os_error`, then this function will return `Some`, otherwise
+    /// it will return `None`.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn raw_os_error(&self) -> Option<i32> {
         match self.repr {
@@ -184,6 +189,46 @@ impl Error {
         }
     }
 
+    /// Returns a reference to the inner error wrapped by this error (if any).
+    ///
+    /// If this `Error` was constructed via `new` then this function will
+    /// return `Some`, otherwise it will return `None`.
+    #[unstable(feature = "io_error_inner",
+               reason = "recently added and requires UFCS to downcast")]
+    pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
+        match self.repr {
+            Repr::Os(..) => None,
+            Repr::Custom(ref c) => Some(&*c.error),
+        }
+    }
+
+    /// Returns a mutable reference to the inner error wrapped by this error
+    /// (if any).
+    ///
+    /// If this `Error` was constructed via `new` then this function will
+    /// return `Some`, otherwise it will return `None`.
+    #[unstable(feature = "io_error_inner",
+               reason = "recently added and requires UFCS to downcast")]
+    pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
+        match self.repr {
+            Repr::Os(..) => None,
+            Repr::Custom(ref mut c) => Some(&mut *c.error),
+        }
+    }
+
+    /// Consumes the `Error`, returning its inner error (if any).
+    ///
+    /// If this `Error` was constructed via `new` then this function will
+    /// return `Some`, otherwise it will return `None`.
+    #[unstable(feature = "io_error_inner",
+               reason = "recently added and requires UFCS to downcast")]
+    pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
+        match self.repr {
+            Repr::Os(..) => None,
+            Repr::Custom(c) => Some(c.error)
+        }
+    }
+
     /// Returns the corresponding `ErrorKind` for this error.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn kind(&self) -> ErrorKind {
@@ -194,6 +239,17 @@ impl Error {
     }
 }
 
+impl fmt::Debug for Repr {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &Repr::Os(ref code) =>
+                fmt.debug_struct("Os").field("code", code)
+                   .field("message", &sys::os::error_string(*code)).finish(),
+            &Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Error {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
@@ -215,9 +271,62 @@ impl error::Error for Error {
             Repr::Custom(ref c) => c.error.description(),
         }
     }
+
+    fn cause(&self) -> Option<&error::Error> {
+        match self.repr {
+            Repr::Os(..) => None,
+            Repr::Custom(ref c) => c.error.cause(),
+        }
+    }
 }
 
 fn _assert_error_is_sync_send() {
     fn _is_sync_send<T: Sync+Send>() {}
     _is_sync_send::<Error>();
 }
+
+#[cfg(test)]
+mod test {
+    use prelude::v1::*;
+    use super::{Error, ErrorKind};
+    use error;
+    use error::Error as error_Error;
+    use fmt;
+    use sys::os::error_string;
+
+    #[test]
+    fn test_debug_error() {
+        let code = 6;
+        let msg = error_string(code);
+        let err = Error { repr: super::Repr::Os(code) };
+        let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
+        assert_eq!(format!("{:?}", err), expected);
+    }
+
+    #[test]
+    fn test_downcasting() {
+        #[derive(Debug)]
+        struct TestError;
+
+        impl fmt::Display for TestError {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                Ok(())
+            }
+        }
+
+        impl error::Error for TestError {
+            fn description(&self) -> &str {
+                "asdf"
+            }
+        }
+
+        // we have to call all of these UFCS style right now since method
+        // resolution won't implicitly drop the Send+Sync bounds
+        let mut err = Error::new(ErrorKind::Other, TestError);
+        assert!(error::Error::is::<TestError>(err.get_ref().unwrap()));
+        assert_eq!("asdf", err.get_ref().unwrap().description());
+        assert!(error::Error::is::<TestError>(err.get_mut().unwrap()));
+        let extracted = err.into_inner().unwrap();
+        error::Error::downcast::<TestError>(extracted).unwrap();
+    }
+}
index df280dab37d467221afff885df9cdd78004e01ba..c3e309d182b9587ca34775723343fd75d3d54633 100644 (file)
 
 use prelude::v1::*;
 
-use boxed;
-use cell::UnsafeCell;
+use cell::Cell;
 use rt;
 use sync::{StaticMutex, Arc};
 
 pub struct Lazy<T> {
-    pub lock: StaticMutex,
-    pub ptr: UnsafeCell<*mut Arc<T>>,
-    pub init: fn() -> Arc<T>,
+    lock: StaticMutex,
+    ptr: Cell<*mut Arc<T>>,
+    init: fn() -> Arc<T>,
 }
 
 unsafe impl<T> Sync for Lazy<T> {}
 
-macro_rules! lazy_init {
-    ($init:expr) => (::io::lazy::Lazy {
-        lock: ::sync::MUTEX_INIT,
-        ptr: ::cell::UnsafeCell { value: 0 as *mut _ },
-        init: $init,
-    })
-}
-
 impl<T: Send + Sync + 'static> Lazy<T> {
+    pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+        Lazy {
+            lock: StaticMutex::new(),
+            ptr: Cell::new(0 as *mut _),
+            init: init
+        }
+    }
+
     pub fn get(&'static self) -> Option<Arc<T>> {
         let _g = self.lock.lock();
+        let ptr = self.ptr.get();
         unsafe {
-            let ptr = *self.ptr.get();
             if ptr.is_null() {
                 Some(self.init())
             } else if ptr as usize == 1 {
@@ -53,14 +52,14 @@ impl<T: Send + Sync + 'static> Lazy<T> {
         // `Arc`.
         let registered = rt::at_exit(move || {
             let g = self.lock.lock();
-            let ptr = *self.ptr.get();
-            *self.ptr.get() = 1 as *mut _;
+            let ptr = self.ptr.get();
+            self.ptr.set(1 as *mut _);
             drop(g);
             drop(Box::from_raw(ptr))
         });
         let ret = (self.init)();
         if registered.is_ok() {
-            *self.ptr.get() = boxed::into_raw(Box::new(ret.clone()));
+            self.ptr.set(Box::into_raw(Box::new(ret.clone())));
         }
         return ret
     }
index e7b2b01d09f35eea9e12efee7b654d43cdf6ce34..9021f32fad003c465781cf81f4e2b00808e62511 100644 (file)
@@ -36,13 +36,12 @@ pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
 #[doc(no_inline, hidden)]
 pub use self::stdio::{set_panic, set_print};
 
-#[macro_use] mod lazy;
-
 pub mod prelude;
 mod buffered;
 mod cursor;
 mod error;
 mod impls;
+mod lazy;
 mod util;
 mod stdio;
 
@@ -81,7 +80,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
         let ret = f(g.s);
         if str::from_utf8(&g.s[g.len..]).is_err() {
             ret.and_then(|_| {
-                Err(Error::new(ErrorKind::InvalidInput,
+                Err(Error::new(ErrorKind::InvalidData,
                                "stream did not contain valid UTF-8"))
             })
         } else {
@@ -307,7 +306,7 @@ pub trait Write {
     /// any wrapped object.
     ///
     /// Calls to `write` are not guaranteed to block waiting for data to be
-    /// written, and a write which would otherwise block can indicated through
+    /// written, and a write which would otherwise block can be indicated through
     /// an `Err` variant.
     ///
     /// If the return value is `Ok(n)` then it must be guaranteed that
@@ -506,11 +505,14 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
     }
 }
 
-/// A Buffer is a type of reader which has some form of internal buffering to
+/// A `BufRead` is a type of reader which has some form of internal buffering to
 /// allow certain kinds of reading operations to be more optimized than others.
 ///
 /// This type extends the `Read` trait with a few methods that are not
 /// possible to reasonably implement with purely a read interface.
+///
+/// You can use the [`BufReader` wrapper type](struct.BufReader.html) to turn any
+/// reader into a buffered reader.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BufRead: Read {
     /// Fills the internal buffer of this object, returning the buffer contents.
@@ -569,7 +571,7 @@ pub trait BufRead: Read {
         read_until(self, byte, buf)
     }
 
-    /// Read all bytes until a newline byte (the 0xA byte) is reached, and
+    /// Read all bytes until a newline (the 0xA byte) is reached, and
     /// append them to the provided buffer.
     ///
     /// This function will continue to read (and buffer) bytes from the
index a14c472333c6eb0f93a263e456722f356088f9f2..9fd48f6795039733337f67094b57b80556d8a071 100644 (file)
@@ -19,6 +19,7 @@ use io::{self, BufReader, LineWriter};
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
+use libc;
 
 /// Stdout used by print! and println! macros
 thread_local! {
@@ -52,7 +53,7 @@ struct StderrRaw(stdio::Stderr);
 /// handles is **not** available to raw handles returned from this function.
 ///
 /// The returned handle has no external synchronization or buffering.
-fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
+fn stdin_raw() -> io::Result<StdinRaw> { stdio::Stdin::new().map(StdinRaw) }
 
 /// Constructs a new raw handle to the standard input stream of this process.
 ///
@@ -63,7 +64,7 @@ fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
+fn stdout_raw() -> io::Result<StdoutRaw> { stdio::Stdout::new().map(StdoutRaw) }
 
 /// Constructs a new raw handle to the standard input stream of this process.
 ///
@@ -72,7 +73,7 @@ fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }
+fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
 
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
@@ -86,6 +87,48 @@ impl Write for StderrRaw {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
+enum Maybe<T> {
+    Real(T),
+    Fake,
+}
+
+impl<W: io::Write> io::Write for Maybe<W> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        match *self {
+            Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
+            Maybe::Fake => Ok(buf.len())
+        }
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        match *self {
+            Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
+            Maybe::Fake => Ok(())
+        }
+    }
+}
+
+impl<R: io::Read> io::Read for Maybe<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        match *self {
+            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), buf.len()),
+            Maybe::Fake => Ok(0)
+        }
+    }
+}
+
+fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
+    #[cfg(windows)]
+    const ERR: libc::c_int = libc::ERROR_INVALID_HANDLE;
+    #[cfg(not(windows))]
+    const ERR: libc::c_int = libc::EBADF;
+
+    match r {
+        Err(ref e) if e.raw_os_error() == Some(ERR) => Ok(default),
+        r => r
+    }
+}
+
 /// A handle to the standard input stream of a process.
 ///
 /// Each handle is a shared reference to a global buffer of input data to this
@@ -99,7 +142,7 @@ impl Write for StderrRaw {
 /// Created by the function `io::stdin()`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdin {
-    inner: Arc<Mutex<BufReader<StdinRaw>>>,
+    inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
 }
 
 /// A locked reference to the a `Stdin` handle.
@@ -108,7 +151,7 @@ pub struct Stdin {
 /// constructed via the `lock` method on `Stdin`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdinLock<'a> {
-    inner: MutexGuard<'a, BufReader<StdinRaw>>,
+    inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
 }
 
 /// Creates a new handle to the global standard input stream of this process.
@@ -122,20 +165,25 @@ pub struct StdinLock<'a> {
 /// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
+    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
     return Stdin {
         inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
     };
 
-    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
+    fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
+        let stdin = match stdin_raw() {
+            Ok(stdin) => Maybe::Real(stdin),
+            _ => Maybe::Fake
+        };
+
         // The default buffer capacity is 64k, but apparently windows
         // doesn't like 64k reads on stdin. See #13304 for details, but the
         // idea is that on windows we use a slightly smaller buffer that's
         // been seen to be acceptable.
         Arc::new(Mutex::new(if cfg!(windows) {
-            BufReader::with_capacity(8 * 1024, stdin_raw())
+            BufReader::with_capacity(8 * 1024, stdin)
         } else {
-            BufReader::new(stdin_raw())
+            BufReader::new(stdin)
         }))
     }
 }
@@ -181,6 +229,7 @@ impl<'a> Read for StdinLock<'a> {
         self.inner.read(buf)
     }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> BufRead for StdinLock<'a> {
     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
@@ -215,7 +264,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
+    inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
 }
 
 /// A locked reference to the a `Stdout` handle.
@@ -224,7 +273,7 @@ pub struct Stdout {
 /// method on `Stdout`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
+    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
 }
 
 /// Constructs a new reference to the standard output of the current process.
@@ -236,13 +285,18 @@ pub struct StdoutLock<'a> {
 /// The returned handle implements the `Write` trait.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = lazy_init!(stdout_init);
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
+        = Lazy::new(stdout_init);
     return Stdout {
         inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
     };
 
-    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
-        Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))))
+    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
+        let stdout = match stdout_raw() {
+            Ok(stdout) => Maybe::Real(stdout),
+            _ => Maybe::Fake,
+        };
+        Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))))
     }
 }
 
@@ -288,7 +342,7 @@ impl<'a> Write for StdoutLock<'a> {
 /// For more information, see `stderr`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: Arc<ReentrantMutex<RefCell<StderrRaw>>>,
+    inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
 }
 
 /// A locked reference to the a `Stderr` handle.
@@ -297,7 +351,7 @@ pub struct Stderr {
 /// method on `Stderr`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StderrLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
+    inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
 }
 
 /// Constructs a new reference to the standard error stream of a process.
@@ -308,13 +362,17 @@ pub struct StderrLock<'a> {
 /// The returned handle implements the `Write` trait.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<StderrRaw>>> = lazy_init!(stderr_init);
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
     return Stderr {
         inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
     };
 
-    fn stderr_init() -> Arc<ReentrantMutex<RefCell<StderrRaw>>> {
-        Arc::new(ReentrantMutex::new(RefCell::new(stderr_raw())))
+    fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
+        let stderr = match stderr_raw() {
+            Ok(stderr) => Maybe::Real(stderr),
+            _ => Maybe::Fake,
+        };
+        Arc::new(ReentrantMutex::new(RefCell::new(stderr)))
     }
 }
 
index d797e757a483ecf687d686327ed876a64c987223..d8c999f8948379eb9c80c325606bf438a32c1654 100644 (file)
@@ -16,11 +16,12 @@ use io::{self, Read, Write, ErrorKind, BufRead};
 
 /// Copies the entire contents of a reader into a writer.
 ///
-/// This function will continuously read data from `r` and then write it into
-/// `w` in a streaming fashion until `r` returns EOF.
+/// This function will continuously read data from `reader` and then
+/// write it into `writer` in a streaming fashion until `reader`
+/// returns EOF.
 ///
-/// On success the total number of bytes that were copied from `r` to `w` is
-/// returned.
+/// On success, the total number of bytes that were copied from
+/// `reader` to `writer` is returned.
 ///
 /// # Errors
 ///
@@ -28,17 +29,17 @@ use io::{self, Read, Write, ErrorKind, BufRead};
 /// `write` returns an error. All instances of `ErrorKind::Interrupted` are
 /// handled by this function and the underlying operation is retried.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn copy<R: Read, W: Write>(r: &mut R, w: &mut W) -> io::Result<u64> {
+pub fn copy<R: Read, W: Write>(reader: &mut R, writer: &mut W) -> io::Result<u64> {
     let mut buf = [0; super::DEFAULT_BUF_SIZE];
     let mut written = 0;
     loop {
-        let len = match r.read(&mut buf) {
+        let len = match reader.read(&mut buf) {
             Ok(0) => return Ok(written),
             Ok(len) => len,
             Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
             Err(e) => return Err(e),
         };
-        try!(w.write_all(&buf[..len]));
+        try!(writer.write_all(&buf[..len]));
         written += len as u64;
     }
 }
@@ -77,7 +78,7 @@ pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Read for Repeat {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        for slot in buf.iter_mut() {
+        for slot in &mut *buf {
             *slot = self.byte;
         }
         Ok(buf.len())
index 2e48cde18f361fbb84d2e9911900277a411ac786..e27e4ba5af2cfef796865d179ed93e6779004448 100644 (file)
@@ -26,7 +26,7 @@
 //!
 //! ## What is in the standard library
 //!
-//! The standard library is minimal, a set of battle-tested
+//! The standard library is a set of minimal, battle-tested
 //! core types and shared abstractions for the [broader Rust
 //! ecosystem](https://crates.io) to build on.
 //!
@@ -60,7 +60,7 @@
 //! [`FromStr`](str/trait.FromStr.html) trait.
 //!
 //! Data may be shared by placing it in a reference-counted box or the
-//! [`Rc`][rc/index.html] type, and if further contained in a [`Cell`
+//! [`Rc`](rc/index.html) type, and if further contained in a [`Cell`
 //! or `RefCell`](cell/index.html), may be mutated as well as shared.
 //! Likewise, in a concurrent setting it is common to pair an
 //! atomically-reference-counted box, [`Arc`](sync/struct.Arc.html),
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
-       html_playground_url = "http://play.rust-lang.org/")]
-#![doc(test(no_crate_inject, attr(deny(warnings))))]
-#![doc(test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
+       html_playground_url = "http://play.rust-lang.org/",
+       test(no_crate_inject, attr(deny(warnings))),
+       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
 #![feature(alloc)]
 #![feature(allow_internal_unstable)]
 #![feature(associated_consts)]
+#![feature(borrow_state)]
+#![feature(box_raw)]
 #![feature(box_syntax)]
+#![feature(char_internals)]
+#![feature(clone_from_slice)]
 #![feature(collections)]
+#![feature(collections_bound)]
+#![feature(const_fn)]
 #![feature(core)]
-#![feature(debug_builders)]
+#![feature(core_float)]
+#![feature(core_intrinsics)]
+#![feature(core_prelude)]
+#![feature(core_simd)]
+#![feature(fnbox)]
+#![feature(heap_api)]
+#![feature(int_error_internals)]
 #![feature(into_cow)]
+#![feature(iter_order)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(linkage, thread_local, asm)]
 #![feature(macro_reexport)]
+#![feature(slice_concat_ext)]
+#![feature(slice_position_elem)]
+#![feature(no_std)]
+#![feature(oom)]
 #![feature(optin_builtin_traits)]
 #![feature(rand)]
+#![feature(raw)]
+#![feature(reflect_marker)]
+#![feature(slice_bytes)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
-#![feature(std_misc)]
 #![feature(str_char)]
+#![feature(str_internals)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
+#![feature(vec_push_all)]
+#![feature(wrapping)]
 #![feature(zero_one)]
-#![cfg_attr(test, feature(float_from_str_radix))]
-#![cfg_attr(test, feature(test, rustc_private, std_misc))]
+#![cfg_attr(windows, feature(str_utf16))]
+#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))]
+#![cfg_attr(test, feature(test, rustc_private, float_consts))]
 
 // Don't link to std. We are std.
-#![feature(no_std)]
 #![no_std]
 
 #![allow(trivial_casts)]
index 32193b4089d3079682130866499deb31d4ba2d4b..02c35e9526d36d071c0f211a1b42f63b7aa48393 100644 (file)
@@ -14,8 +14,6 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
-#![unstable(feature = "std_misc")]
-
 /// The entry point for panic of Rust threads.
 ///
 /// This macro is used to inject panic into a Rust thread, causing the thread to
@@ -117,7 +115,34 @@ macro_rules! println {
 }
 
 /// Helper macro for unwrapping `Result` values while returning early with an
-/// error if the value of the expression is `Err`.
+/// error if the value of the expression is `Err`. Can only be used in
+/// functions that return `Result` because of the early return of `Err` that
+/// it provides.
+///
+/// # Examples
+///
+/// ```
+/// use std::io;
+/// use std::fs::File;
+/// use std::io::prelude::*;
+///
+/// fn write_to_file_using_try() -> Result<(), io::Error> {
+///     let mut file = try!(File::create("my_best_friends.txt"));
+///     try!(file.write_all(b"This is a list of my best friends."));
+///     println!("I wrote to the file");
+///     Ok(())
+/// }
+/// // This is equivalent to:
+/// fn write_to_file_using_match() -> Result<(), io::Error> {
+///     let mut file = try!(File::create("my_best_friends.txt"));
+///     match file.write_all(b"This is a list of my best friends.") {
+///         Ok(_) => (),
+///         Err(e) => return Err(e),
+///     }
+///     println!("I wrote to the file");
+///     Ok(())
+/// }
+/// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! try {
@@ -138,7 +163,7 @@ macro_rules! try {
 /// # Examples
 ///
 /// ```
-/// # #![feature(std_misc)]
+/// # #![feature(mpsc_select)]
 /// use std::thread;
 /// use std::sync::mpsc;
 ///
@@ -164,7 +189,7 @@ macro_rules! try {
 ///
 /// For more information about select, see the `std::sync::mpsc::Select` structure.
 #[macro_export]
-#[unstable(feature = "std_misc")]
+#[unstable(feature = "mpsc_select")]
 macro_rules! select {
     (
         $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
@@ -306,7 +331,7 @@ pub mod builtin {
 
     /// A macro which expands to the line number on which it was invoked.
     ///
-    /// The expanded expression has type `usize`, and the returned line is not
+    /// The expanded expression has type `u32`, and the returned line is not
     /// the invocation of the `line!()` macro itself, but rather the first macro
     /// invocation leading up to the invocation of the `line!()` macro.
     ///
@@ -321,7 +346,7 @@ pub mod builtin {
 
     /// A macro which expands to the column number on which it was invoked.
     ///
-    /// The expanded expression has type `usize`, and the returned column is not
+    /// The expanded expression has type `u32`, and the returned column is not
     /// the invocation of the `column!()` macro itself, but rather the first macro
     /// invocation leading up to the invocation of the `column!()` macro.
     ///
index a79a451305dafb6893e8aa56536ceb59858620ef..1cb8c187030317d63554a56dfba9d500b905c1ee 100644 (file)
@@ -30,8 +30,7 @@ mod udp;
 mod parser;
 #[cfg(test)] mod test;
 
-/// Possible values which can be passed to the `shutdown` method of `TcpStream`
-/// and `UdpSocket`.
+/// Possible values which can be passed to the `shutdown` method of `TcpStream`.
 #[derive(Copy, Clone, PartialEq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Shutdown {
index 69f40d7e7befe2b8850b252c946b9fa9e9da159a..b0fadb56f36ac7db9ff0a9c8dd6a77de80bf3b31 100644 (file)
@@ -63,7 +63,7 @@ impl<'a> Parser<'a> {
     // Return result of first successful parser
     fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
                -> Option<T> {
-        for pf in parsers.iter_mut() {
+        for pf in parsers {
             match self.read_atomically(|p: &mut Parser| pf(p)) {
                 Some(r) => return Some(r),
                 None => {}
index 28063c1edb3f744755fd6c61cd9ce8b5fb5b5b62..222059e4c0e6a164f6ebd0c26d021e6ee7a46429 100644 (file)
@@ -19,6 +19,7 @@ use io;
 use net::{ToSocketAddrs, SocketAddr, Shutdown};
 use sys_common::net as net_imp;
 use sys_common::{AsInner, FromInner};
+use time::Duration;
 
 /// A structure which represents a TCP stream between a local socket and a
 /// remote socket.
@@ -139,6 +140,50 @@ impl TcpStream {
     pub fn set_keepalive(&self, seconds: Option<u32>) -> io::Result<()> {
         self.0.set_keepalive(seconds)
     }
+
+    /// Sets the read timeout to the timeout specified.
+    ///
+    /// If the value specified is `None`, then `read` calls will block
+    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// method.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.0.set_read_timeout(dur)
+    }
+
+    /// Sets the write timeout to the timeout specified.
+    ///
+    /// If the value specified is `None`, then `write` calls will block
+    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// method.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.0.set_write_timeout(dur)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// If the timeout is `None`, then `read` calls will block indefinitely.
+    ///
+    /// # Note
+    ///
+    /// Some platforms do not provide access to the current timeout.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.read_timeout()
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// If the timeout is `None`, then `write` calls will block indefinitely.
+    ///
+    /// # Note
+    ///
+    /// Some platforms do not provide access to the current timeout.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.write_timeout()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -262,6 +307,7 @@ mod tests {
     use net::test::{next_test_ip4, next_test_ip6};
     use sync::mpsc::channel;
     use sys_common::AsInner;
+    use time::Duration;
     use thread;
 
     fn each_ip(f: &mut FnMut(SocketAddr)) {
@@ -437,7 +483,7 @@ mod tests {
 
     #[test]
     fn multiple_connect_interleaved_greedy_schedule() {
-        static MAX: usize = 10;
+        const MAX: usize = 10;
         each_ip(&mut |addr| {
             let acceptor = t!(TcpListener::bind(&addr));
 
@@ -844,7 +890,7 @@ mod tests {
                               socket_addr, name, listener_inner);
         assert_eq!(format!("{:?}", listener), compare);
 
-        let mut stream = t!(TcpStream::connect(&("localhost",
+        let stream = t!(TcpStream::connect(&("localhost",
                                                  socket_addr.port())));
         let stream_inner = stream.0.socket().as_inner();
         let compare = format!("TcpStream {{ addr: {:?}, \
@@ -855,4 +901,72 @@ mod tests {
                               stream_inner);
         assert_eq!(format!("{:?}", stream), compare);
     }
+
+    // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
+    //        no longer has rounding errors.
+    #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+    #[test]
+    fn timeouts() {
+        let addr = next_test_ip4();
+        let listener = t!(TcpListener::bind(&addr));
+
+        let stream = t!(TcpStream::connect(&("localhost", addr.port())));
+        let dur = Duration::new(15410, 0);
+
+        assert_eq!(None, t!(stream.read_timeout()));
+
+        t!(stream.set_read_timeout(Some(dur)));
+        assert_eq!(Some(dur), t!(stream.read_timeout()));
+
+        assert_eq!(None, t!(stream.write_timeout()));
+
+        t!(stream.set_write_timeout(Some(dur)));
+        assert_eq!(Some(dur), t!(stream.write_timeout()));
+
+        t!(stream.set_read_timeout(None));
+        assert_eq!(None, t!(stream.read_timeout()));
+
+        t!(stream.set_write_timeout(None));
+        assert_eq!(None, t!(stream.write_timeout()));
+    }
+
+    #[test]
+    fn test_read_timeout() {
+        let addr = next_test_ip4();
+        let listener = t!(TcpListener::bind(&addr));
+
+        let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
+        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        let mut buf = [0; 10];
+        let wait = Duration::span(|| {
+            let kind = stream.read(&mut buf).err().expect("expected error").kind();
+            assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+        });
+        assert!(wait > Duration::from_millis(400));
+        assert!(wait < Duration::from_millis(1600));
+    }
+
+    #[test]
+    fn test_read_with_timeout() {
+        let addr = next_test_ip4();
+        let listener = t!(TcpListener::bind(&addr));
+
+        let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
+        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        let mut other_end = t!(listener.accept()).0;
+        t!(other_end.write_all(b"hello world"));
+
+        let mut buf = [0; 11];
+        t!(stream.read(&mut buf));
+        assert_eq!(b"hello world", &buf[..]);
+
+        let wait = Duration::span(|| {
+            let kind = stream.read(&mut buf).err().expect("expected error").kind();
+            assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+        });
+        assert!(wait > Duration::from_millis(400));
+        assert!(wait < Duration::from_millis(1600));
+    }
 }
index d77d6f1d6de1e2d3fdd177cdf02e62710096b7f9..c6d839d55a865d97c8e45285d4b263b1cc0564f0 100644 (file)
@@ -12,9 +12,9 @@ use prelude::v1::*;
 
 use env;
 use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
-use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use sync::atomic::{AtomicUsize, Ordering};
 
-static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
+static PORT: AtomicUsize = AtomicUsize::new(0);
 
 pub fn next_test_ip4() -> SocketAddr {
     let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port();
index 67c7096904d6f9abe2e9da4cfba0d4d038650692..c3cf9895205e47290f49cd08d355ca8988fc84d9 100644 (file)
@@ -18,6 +18,7 @@ use io::{self, Error, ErrorKind};
 use net::{ToSocketAddrs, SocketAddr, IpAddr};
 use sys_common::net as net_imp;
 use sys_common::{AsInner, FromInner};
+use time::Duration;
 
 /// A User Datagram Protocol socket.
 ///
@@ -127,6 +128,42 @@ impl UdpSocket {
     pub fn set_time_to_live(&self, ttl: i32) -> io::Result<()> {
         self.0.time_to_live(ttl)
     }
+
+    /// Sets the read timeout to the timeout specified.
+    ///
+    /// If the value specified is `None`, then `read` calls will block
+    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// method.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.0.set_read_timeout(dur)
+    }
+
+    /// Sets the write timeout to the timeout specified.
+    ///
+    /// If the value specified is `None`, then `write` calls will block
+    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// method.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.0.set_write_timeout(dur)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// If the timeout is `None`, then `read` calls will block indefinitely.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.read_timeout()
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// If the timeout is `None`, then `write` calls will block indefinitely.
+    #[unstable(feature = "socket_timeout", reason = "RFC 1047 - recently added")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.write_timeout()
+    }
 }
 
 impl AsInner<net_imp::UdpSocket> for UdpSocket {
@@ -152,6 +189,7 @@ mod tests {
     use net::test::{next_test_ip4, next_test_ip6};
     use sync::mpsc::channel;
     use sys_common::AsInner;
+    use time::Duration;
     use thread;
 
     fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
@@ -321,4 +359,68 @@ mod tests {
                               socket_addr, name, udpsock_inner);
         assert_eq!(format!("{:?}", udpsock), compare);
     }
+
+    // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
+    //        no longer has rounding errors.
+    #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+    #[test]
+    fn timeouts() {
+        let addr = next_test_ip4();
+
+        let stream = t!(UdpSocket::bind(&addr));
+        let dur = Duration::new(15410, 0);
+
+        assert_eq!(None, t!(stream.read_timeout()));
+
+        t!(stream.set_read_timeout(Some(dur)));
+        assert_eq!(Some(dur), t!(stream.read_timeout()));
+
+        assert_eq!(None, t!(stream.write_timeout()));
+
+        t!(stream.set_write_timeout(Some(dur)));
+        assert_eq!(Some(dur), t!(stream.write_timeout()));
+
+        t!(stream.set_read_timeout(None));
+        assert_eq!(None, t!(stream.read_timeout()));
+
+        t!(stream.set_write_timeout(None));
+        assert_eq!(None, t!(stream.write_timeout()));
+    }
+
+    #[test]
+    fn test_read_timeout() {
+        let addr = next_test_ip4();
+
+        let mut stream = t!(UdpSocket::bind(&addr));
+        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        let mut buf = [0; 10];
+        let wait = Duration::span(|| {
+            let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+            assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+        });
+        assert!(wait > Duration::from_millis(400));
+        assert!(wait < Duration::from_millis(1600));
+    }
+
+    #[test]
+    fn test_read_with_timeout() {
+        let addr = next_test_ip4();
+
+        let mut stream = t!(UdpSocket::bind(&addr));
+        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        t!(stream.send_to(b"hello world", &addr));
+
+        let mut buf = [0; 11];
+        t!(stream.recv_from(&mut buf));
+        assert_eq!(b"hello world", &buf[..]);
+
+        let wait = Duration::span(|| {
+            let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+            assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+        });
+        assert!(wait > Duration::from_millis(400));
+        assert!(wait < Duration::from_millis(1600));
+    }
 }
index 1ee3aab2727a864f8540e9ef95f87e1a09d7031c..0c40f6c1fc8a8fb73a39b6ac769b66ecf1d2d103 100644 (file)
@@ -32,7 +32,6 @@ pub use core::f32::consts;
 mod cmath {
     use libc::{c_float, c_int};
 
-    #[link_name = "m"]
     extern {
         pub fn acosf(n: c_float) -> c_float;
         pub fn asinf(n: c_float) -> c_float;
@@ -44,13 +43,10 @@ mod cmath {
         pub fn erfcf(n: c_float) -> c_float;
         pub fn expm1f(n: c_float) -> c_float;
         pub fn fdimf(a: c_float, b: c_float) -> c_float;
-        pub fn frexpf(n: c_float, value: &mut c_int) -> c_float;
         pub fn fmaxf(a: c_float, b: c_float) -> c_float;
         pub fn fminf(a: c_float, b: c_float) -> c_float;
         pub fn fmodf(a: c_float, b: c_float) -> c_float;
         pub fn nextafterf(x: c_float, y: c_float) -> c_float;
-        pub fn hypotf(x: c_float, y: c_float) -> c_float;
-        pub fn ldexpf(x: c_float, n: c_int) -> c_float;
         pub fn logbf(n: c_float) -> c_float;
         pub fn log1pf(n: c_float) -> c_float;
         pub fn ilogbf(n: c_float) -> c_int;
@@ -60,12 +56,27 @@ mod cmath {
         pub fn tanhf(n: c_float) -> c_float;
         pub fn tgammaf(n: c_float) -> c_float;
 
-        #[cfg(unix)]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")]
         pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypotf")]
+        pub fn hypotf(x: c_float, y: c_float) -> c_float;
 
-        #[cfg(windows)]
-        #[link_name="__lgammaf_r"]
-        pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
+        #[cfg(any(unix, all(windows, not(target_env = "msvc"))))]
+        pub fn frexpf(n: c_float, value: &mut c_int) -> c_float;
+        #[cfg(any(unix, all(windows, not(target_env = "msvc"))))]
+        pub fn ldexpf(x: c_float, n: c_int) -> c_float;
+    }
+
+    #[cfg(all(windows, target_env = "msvc"))]
+    pub unsafe fn ldexpf(x: c_float, n: c_int) -> c_float {
+        f64::ldexp(x as f64, n as isize) as c_float
+    }
+
+    #[cfg(all(windows, target_env = "msvc"))]
+    pub unsafe fn frexpf(x: c_float, value: &mut c_int) -> c_float {
+        let (a, b) = f64::frexp(x as f64);
+        *value = b as c_int;
+        a as c_float
     }
 }
 
@@ -183,7 +194,7 @@ impl f32 {
     /// The floating point encoding is documented in the [Reference][floating-point].
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32;
     ///
     /// let num = 2.0f32;
@@ -200,9 +211,11 @@ impl f32 {
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
     /// [floating-point]: ../../../../../reference.html#machine-types
-    #[unstable(feature = "std_misc", reason = "signature is undecided")]
+    #[unstable(feature = "float_extras", reason = "signature is undecided")]
     #[inline]
-    pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
+    pub fn integer_decode(self) -> (u64, i16, i8) {
+        num::Float::integer_decode(self)
+    }
 
     /// Returns the largest integer less than or equal to a number.
     ///
@@ -544,7 +557,7 @@ impl f32 {
     /// Converts radians to degrees.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32::{self, consts};
     ///
     /// let angle = consts::PI;
@@ -553,14 +566,14 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
-    #[unstable(feature = "std_misc", reason = "desirability is unclear")]
+    #[unstable(feature = "float_extras", reason = "desirability is unclear")]
     #[inline]
     pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
 
     /// Converts degrees to radians.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32::{self, consts};
     ///
     /// let angle = 180.0f32;
@@ -569,21 +582,21 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
-    #[unstable(feature = "std_misc", reason = "desirability is unclear")]
+    #[unstable(feature = "float_extras", reason = "desirability is unclear")]
     #[inline]
     pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
 
     /// Constructs a floating point number of `x*2^exp`.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32;
     /// // 3*2^2 - 12 == 0
     /// let abs_difference = (f32::ldexp(3.0, 2) - 12.0).abs();
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "pending integer conventions")]
     #[inline]
     pub fn ldexp(x: f32, exp: isize) -> f32 {
@@ -597,7 +610,7 @@ impl f32 {
     ///  * `0.5 <= abs(x) < 1.0`
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32;
     ///
     /// let x = 4.0f32;
@@ -610,7 +623,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "pending integer conventions")]
     #[inline]
     pub fn frexp(self) -> (f32, isize) {
@@ -625,7 +638,7 @@ impl f32 {
     /// `other`.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// use std::f32;
     ///
     /// let x = 1.0f32;
@@ -634,7 +647,7 @@ impl f32 {
     ///
     /// assert!(abs_diff <= f32::EPSILON);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "unsure about its place in the world")]
     #[inline]
     pub fn next_after(self, other: f32) -> f32 {
@@ -649,6 +662,8 @@ impl f32 {
     ///
     /// assert_eq!(x.max(y), y);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f32) -> f32 {
@@ -663,6 +678,8 @@ impl f32 {
     ///
     /// assert_eq!(x.min(y), x);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f32) -> f32 {
index 398afcb553c1ce5006593e1afcf35cbfc1e14ce0..41c0fcb9797a651a2fd957fd44c3a46d7f95a0ca 100644 (file)
@@ -48,7 +48,6 @@ mod cmath {
         pub fn fmod(a: c_double, b: c_double) -> c_double;
         pub fn nextafter(x: c_double, y: c_double) -> c_double;
         pub fn frexp(n: c_double, value: &mut c_int) -> c_double;
-        pub fn hypot(x: c_double, y: c_double) -> c_double;
         pub fn ldexp(x: c_double, n: c_int) -> c_double;
         pub fn logb(n: c_double) -> c_double;
         pub fn log1p(n: c_double) -> c_double;
@@ -69,11 +68,11 @@ mod cmath {
         pub fn y1(n: c_double) -> c_double;
         pub fn yn(i: c_int, n: c_double) -> c_double;
 
-        #[cfg(unix)]
-        pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
-        #[cfg(windows)]
-        #[link_name="__lgamma_r"]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgamma_r")]
         pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
+
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypot")]
+        pub fn hypot(x: c_double, y: c_double) -> c_double;
     }
 }
 
@@ -191,7 +190,7 @@ impl f64 {
     /// The floating point encoding is documented in the [Reference][floating-point].
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// let num = 2.0f64;
     ///
     /// // (8388608, -22, 1)
@@ -206,7 +205,7 @@ impl f64 {
     /// assert!(abs_difference < 1e-10);
     /// ```
     /// [floating-point]: ../../../../../reference.html#machine-types
-    #[unstable(feature = "std_misc", reason = "signature is undecided")]
+    #[unstable(feature = "float_extras", reason = "signature is undecided")]
     #[inline]
     pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
 
@@ -568,13 +567,13 @@ impl f64 {
     /// Constructs a floating point number of `x*2^exp`.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// // 3*2^2 - 12 == 0
     /// let abs_difference = (f64::ldexp(3.0, 2) - 12.0).abs();
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "pending integer conventions")]
     #[inline]
     pub fn ldexp(x: f64, exp: isize) -> f64 {
@@ -588,7 +587,7 @@ impl f64 {
     ///  * `0.5 <= abs(x) < 1.0`
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     /// let x = 4.0_f64;
     ///
     /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0
@@ -599,7 +598,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "pending integer conventions")]
     #[inline]
     pub fn frexp(self) -> (f64, isize) {
@@ -614,7 +613,7 @@ impl f64 {
     /// `other`.
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(float_extras)]
     ///
     /// let x = 1.0f32;
     ///
@@ -622,7 +621,7 @@ impl f64 {
     ///
     /// assert!(abs_diff < 1e-10);
     /// ```
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "float_extras",
                reason = "unsure about its place in the world")]
     #[inline]
     pub fn next_after(self, other: f64) -> f64 {
@@ -637,6 +636,8 @@ impl f64 {
     ///
     /// assert_eq!(x.max(y), y);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f64) -> f64 {
@@ -651,6 +652,8 @@ impl f64 {
     ///
     /// assert_eq!(x.min(y), x);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f64) -> f64 {
index 60a548b596b1c60f719659e828fa58ca646620c6..16ad21a07d700acb842a19973f9ff4d3b98cb3fd 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 
 macro_rules! assert_approx_eq {
index af1976d5750932db4eb3d5187a2db2f778dfecc7..178fad09f9881a4d4c84a0c005f4d8141b44a96e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 
 macro_rules! int_module { ($T:ty) => (
index 7fb2cd81ababf2dbfc44f0722f3f31e781446df2..aa89f858f6f63b0c34b78577ece88320996c4391 100644 (file)
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 //! Operations and constants for pointer-sized signed integers (`isize` type)
-//!
-//! This type was recently added to replace `int`. The rollout of the
-//! new type will gradually take place over the alpha cycle along with
-//! the development of clearer conventions around integer types.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
index 96b0ba1c77f8da8c600cf02a16eebabe43fe0960..555a5cc3e20e9d747006a0963c6bd99944cf5679 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 #![allow(unsigned_negation)]
 
index 19964c306a79bbcc08bdf8047ae23e96be9e8a89..b54d8ae96c5cf468f8508e80e118ffcb9d8bf60e 100644 (file)
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 //! Operations and constants for pointer-sized unsigned integers (`usize` type)
-//!
-//! This type was recently added to replace `uint`. The rollout of the
-//! new type will gradually take place over the alpha cycle along with
-//! the development of clearer conventions around integer types.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
index 4987db22f21fc9a347da45f4ac52984e672681c1..e5e89ad800a418199dd648b4f02a51c8b8356775 100644 (file)
 
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
-use os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
-use os::unix::raw::{uid_t, gid_t};
+#[doc(inline)]
+pub use self::arch::{dev_t, mode_t, blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type blkcnt_t = u32;
-#[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 = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type ino_t = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type mode_t = u16;
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type nlink_t = u16;
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type off_t = i32;
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub type time_t = i32;
+#[cfg(target_arch = "arm")]
+mod arch {
+    use os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
+    use os::unix::raw::{uid_t, gid_t};
 
-#[repr(C)]
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_dev: c_ulonglong,
+    pub type dev_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub __pad0: [c_uchar; 4],
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub __st_ino: ino_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mode: c_uint,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_nlink: c_uint,
+    pub type mode_t = u16;
+
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_uid: uid_t,
+    pub type blkcnt_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_gid: gid_t,
+    pub type blksize_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_rdev: c_ulonglong,
+    pub type ino_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub __pad3: [c_uchar; 4],
+    pub type nlink_t = u16;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_size: c_longlong,
+    pub type off_t = i32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blksize: blksize_t,
+    pub type time_t = i32;
+
+    #[repr(C)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad0: [c_uchar; 4],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __st_ino: ino_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: uid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: gid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad3: [c_uchar; 4],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: c_longlong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: blksize_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: c_ulonglong,
+    }
+
+}
+
+
+#[cfg(target_arch = "aarch64")]
+mod arch {
+    use os::raw::{c_uchar, c_ulong};
+    use os::unix::raw::{uid_t, gid_t};
+
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blocks: c_ulonglong,
+    pub type dev_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime: time_t,
+    pub type mode_t = u32;
+
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime_nsec: c_ulong,
+    pub type blkcnt_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime: time_t,
+    pub type blksize_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime_nsec: c_ulong,
+    pub type ino_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime: time_t,
+    pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime_nsec: c_ulong,
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ino: c_ulonglong,
+    pub type time_t = i64;
+
+    #[repr(C)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad0: [c_uchar; 4],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __st_ino: ino_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: mode_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: nlink_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: uid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: gid_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad3: [c_uchar; 4],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: off_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: blksize_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: blkcnt_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: ino_t,
+    }
 }
index 7366524fd7ea82f1729f67578920b5e0ac2adc41..bb4375c1b8826203aa47b35677bacf248c8a500b 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc")]
-
 use prelude::v1::*;
 use io::prelude::*;
 
@@ -33,12 +31,12 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
             None => "Box<Any>",
         }
     };
-    let mut err = Stderr::new();
+    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 prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
-    match prev {
-        Some(mut stderr) => {
+    match (prev, err.as_mut()) {
+        (Some(mut stderr), _) => {
             // FIXME: what to do when the thread printing panics?
             let _ = writeln!(stderr,
                              "thread '{}' panicked at '{}', {}:{}\n",
@@ -51,18 +49,22 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
                 *slot.borrow_mut() = s.take();
             });
         }
-        None => {
-            let _ = writeln!(&mut err, "thread '{}' panicked at '{}', {}:{}",
+        (None, Some(ref mut err)) => {
+            let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
                              name, msg, file, line);
             if backtrace::log_enabled() {
-                let _ = backtrace::write(&mut err);
+                let _ = backtrace::write(err);
             }
         }
+        _ => {}
     }
 
     // If this is a double panic, make sure that we printed a backtrace
     // for this panic.
-    if unwind::panicking() && !backtrace::log_enabled() {
-        let _ = backtrace::write(&mut err);
+    match err {
+        Some(ref mut err) if unwind::panicking() && !backtrace::log_enabled() => {
+            let _ = backtrace::write(err);
+        }
+        _ => {}
     }
 }
index 934b3156357d64e09a2ea574c78c6be9027ff9d4..d3573345afbb070e927de6fc1f2452db7b953e81 100644 (file)
@@ -258,7 +258,7 @@ mod platform {
 /// Path prefixes (Windows only).
 ///
 /// Windows uses a variety of path styles, including references to drive
-/// volumes (like `C:`), network shared (like `\\server\share`) and
+/// volumes (like `C:`), network shared folders (like `\\server\share`) and
 /// others. In addition, some path prefixes are "verbatim", in which case
 /// `/` is *not* treated as a separator and essentially no normalization is
 /// performed.
@@ -312,14 +312,14 @@ impl<'a> Prefix<'a> {
 
     }
 
-    /// Determines if the prefix is verbatim, i.e. begins `\\?\`.
+    /// Determines if the prefix is verbatim, i.e. begins with `\\?\`.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_verbatim(&self) -> bool {
         use self::Prefix::*;
         match *self {
             Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(_, _) => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -1247,9 +1247,10 @@ impl Path {
     /// ```
     /// use std::path::Path;
     ///
-    /// let s = String::from("bar.txt");
-    /// let p = Path::new(&s);
-    /// Path::new(&p);
+    /// let string = String::from("foo.txt");
+    /// let from_string = Path::new(&string);
+    /// let from_path = Path::new(&from_string);
+    /// assert_eq!(from_string, from_path);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
@@ -1264,6 +1265,7 @@ impl Path {
     /// use std::path::Path;
     ///
     /// let os_str = Path::new("foo.txt").as_os_str();
+    /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_os_str(&self) -> &OsStr {
@@ -1280,6 +1282,7 @@ impl Path {
     /// use std::path::Path;
     ///
     /// let path_str = Path::new("foo.txt").to_str();
+    //// assert_eq!(path_str, Some("foo.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_str(&self) -> Option<&str> {
@@ -1296,6 +1299,7 @@ impl Path {
     /// use std::path::Path;
     ///
     /// let path_str = Path::new("foo.txt").to_string_lossy();
+    /// assert_eq!(path_str, "foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_string_lossy(&self) -> Cow<str> {
@@ -1309,7 +1313,8 @@ impl Path {
     /// ```
     /// use std::path::Path;
     ///
-    /// let path_str = Path::new("foo.txt").to_path_buf();
+    /// let path_buf = Path::new("foo.txt").to_path_buf();
+    /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_path_buf(&self) -> PathBuf {
@@ -1330,7 +1335,7 @@ impl Path {
     /// ```
     /// use std::path::Path;
     ///
-    /// assert_eq!(false, Path::new("foo.txt").is_absolute());
+    /// assert!(!Path::new("foo.txt").is_absolute());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_absolute(&self) -> bool {
@@ -1393,14 +1398,12 @@ impl Path {
     /// use std::path::Path;
     ///
     /// let path = Path::new("/foo/bar");
-    /// let foo = path.parent().unwrap();
-    ///
-    /// assert!(foo == Path::new("/foo"));
+    /// let parent = path.parent().unwrap();
+    /// assert_eq!(parent, Path::new("/foo"));
     ///
-    /// let root = foo.parent().unwrap();
-    ///
-    /// assert!(root == Path::new("/"));
-    /// assert!(root.parent() == None);
+    /// let grand_parent = parent.parent().unwrap();
+    /// assert_eq!(grand_parent, Path::new("/"));
+    /// assert_eq!(grand_parent.parent(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn parent(&self) -> Option<&Path> {
@@ -1416,18 +1419,19 @@ impl Path {
 
     /// The final component of the path, if it is a normal file.
     ///
-    /// If the path terminates in `.`, `..`, or consists solely or a root of
+    /// If the path terminates in `.`, `..`, or consists solely of a root of
     /// prefix, `file_name` will return `None`.
     ///
     /// # Examples
     ///
     /// ```
     /// use std::path::Path;
+    /// use std::ffi::OsStr;
     ///
-    /// let path = Path::new("hello_world.rs");
-    /// let filename = "hello_world.rs";
+    /// let path = Path::new("foo.txt");
+    /// let os_str = OsStr::new("foo.txt");
     ///
-    /// assert_eq!(filename, path.file_name().unwrap());
+    /// assert_eq!(Some(os_str), path.file_name());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn file_name(&self) -> Option<&OsStr> {
@@ -1485,7 +1489,7 @@ impl Path {
         iter_after(self.components().rev(), child.as_ref().components().rev()).is_some()
     }
 
-    /// Extracts the stem (non-extension) portion of `self.file()`.
+    /// Extracts the stem (non-extension) portion of `self.file_name()`.
     ///
     /// The stem is:
     ///
@@ -1508,7 +1512,7 @@ impl Path {
         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
     }
 
-    /// Extracts the extension of `self.file()`, if possible.
+    /// Extracts the extension of `self.file_name()`, if possible.
     ///
     /// The extension is:
     ///
@@ -1538,11 +1542,9 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
-    ///
-    /// let path = Path::new("/tmp");
+    /// use std::path::{Path, PathBuf};
     ///
-    /// let new_path = path.join("foo");
+    /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
@@ -1558,11 +1560,10 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
-    ///
-    /// let path = Path::new("/tmp/foo.rs");
+    /// use std::path::{Path, PathBuf};
     ///
-    /// let new_path = path.with_file_name("bar.rs");
+    /// let path = Path::new("/tmp/foo.txt");
+    /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
@@ -1580,10 +1581,8 @@ impl Path {
     /// ```
     /// use std::path::{Path, PathBuf};
     ///
-    /// let path = Path::new("/tmp/foo.rs");
-    ///
-    /// let new_path = path.with_extension("txt");
-    /// assert_eq!(new_path, PathBuf::from("/tmp/foo.txt"));
+    /// let path = Path::new("foo.rs");
+    /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
@@ -1597,13 +1596,15 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
+    /// use std::path::{Path, Component};
+    /// use std::ffi::OsStr;
     ///
-    /// let path = Path::new("/tmp/foo.rs");
+    /// let mut components = Path::new("/tmp/foo.txt").components();
     ///
-    /// for component in path.components() {
-    ///     println!("{:?}", component);
-    /// }
+    /// assert_eq!(components.next(), Some(Component::RootDir));
+    /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
+    /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
+    /// assert_eq!(components.next(), None)
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn components(&self) -> Components {
@@ -1622,13 +1623,14 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
-    ///
-    /// let path = Path::new("/tmp/foo.rs");
-    ///
-    /// for component in path.iter() {
-    ///     println!("{:?}", component);
-    /// }
+    /// use std::path::{self, Path};
+    /// use std::ffi::OsStr;
+    ///
+    /// let mut it = Path::new("/tmp/foo.txt").iter();
+    /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
+    /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
+    /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
+    /// assert_eq!(it.next(), None)
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter {
index 61398e16ba03613e4063433b155e1fb97d41a081..a8127b3200f36da26b6eb01e278078f12c7c7a6a 100644 (file)
@@ -22,11 +22,8 @@ use io::{self, Error, ErrorKind};
 use path;
 use sync::mpsc::{channel, Receiver};
 use sys::pipe::{self, AnonPipe};
-use sys::process::Command as CommandImp;
-use sys::process::Process as ProcessImp;
-use sys::process::ExitStatus as ExitStatusImp;
-use sys::process::Stdio as StdioImp2;
-use sys_common::{AsInner, AsInnerMut};
+use sys::process as imp;
+use sys_common::{AsInner, AsInnerMut, FromInner};
 use thread;
 
 /// Representation of a running or exited child process.
@@ -52,10 +49,10 @@ use thread;
 /// ```
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Child {
-    handle: ProcessImp,
+    handle: imp::Process,
 
     /// None until wait() or wait_with_output() is called.
-    status: Option<ExitStatusImp>,
+    status: Option<imp::ExitStatus>,
 
     /// The handle for writing to the child's stdin, if it has been captured
     #[stable(feature = "process", since = "1.0.0")]
@@ -70,6 +67,10 @@ pub struct Child {
     pub stderr: Option<ChildStderr>,
 }
 
+impl AsInner<imp::Process> for Child {
+    fn as_inner(&self) -> &imp::Process { &self.handle }
+}
+
 /// A handle to a child procesess's stdin
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdin {
@@ -87,6 +88,10 @@ impl Write for ChildStdin {
     }
 }
 
+impl AsInner<AnonPipe> for ChildStdin {
+    fn as_inner(&self) -> &AnonPipe { &self.inner }
+}
+
 /// A handle to a child procesess's stdout
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdout {
@@ -100,6 +105,10 @@ impl Read for ChildStdout {
     }
 }
 
+impl AsInner<AnonPipe> for ChildStdout {
+    fn as_inner(&self) -> &AnonPipe { &self.inner }
+}
+
 /// A handle to a child procesess's stderr
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStderr {
@@ -113,6 +122,10 @@ impl Read for ChildStderr {
     }
 }
 
+impl AsInner<AnonPipe> for ChildStderr {
+    fn as_inner(&self) -> &AnonPipe { &self.inner }
+}
+
 /// The `Command` type acts as a process builder, providing fine-grained control
 /// over how a new process should be spawned. A default configuration can be
 /// generated using `Command::new(program)`, where `program` gives a path to the
@@ -131,12 +144,12 @@ impl Read for ChildStderr {
 /// ```
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Command {
-    inner: CommandImp,
+    inner: imp::Command,
 
     // Details explained in the builder methods
-    stdin: Option<StdioImp>,
-    stdout: Option<StdioImp>,
-    stderr: Option<StdioImp>,
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
 }
 
 impl Command {
@@ -153,7 +166,7 @@ impl Command {
     #[stable(feature = "process", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
         Command {
-            inner: CommandImp::new(program.as_ref()),
+            inner: imp::Command::new(program.as_ref()),
             stdin: None,
             stdout: None,
             stderr: None,
@@ -210,36 +223,40 @@ impl Command {
     /// Configuration for the child process's stdin handle (file descriptor 0).
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
-        self.stdin = Some(cfg.0);
+        self.stdin = Some(cfg);
         self
     }
 
     /// Configuration for the child process's stdout handle (file descriptor 1).
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
-        self.stdout = Some(cfg.0);
+        self.stdout = Some(cfg);
         self
     }
 
     /// Configuration for the child process's stderr handle (file descriptor 2).
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
-        self.stderr = Some(cfg.0);
+        self.stderr = Some(cfg);
         self
     }
 
     fn spawn_inner(&self, default_io: StdioImp) -> io::Result<Child> {
-        let (their_stdin, our_stdin) = try!(
+        let default_io = Stdio(default_io);
+
+        // See comment on `setup_io` for what `_drop_later` is.
+        let (their_stdin, our_stdin, _drop_later) = try!(
             setup_io(self.stdin.as_ref().unwrap_or(&default_io), true)
         );
-        let (their_stdout, our_stdout) = try!(
+        let (their_stdout, our_stdout, _drop_later) = try!(
             setup_io(self.stdout.as_ref().unwrap_or(&default_io), false)
         );
-        let (their_stderr, our_stderr) = try!(
+        let (their_stderr, our_stderr, _drop_later) = try!(
             setup_io(self.stderr.as_ref().unwrap_or(&default_io), false)
         );
 
-        match ProcessImp::spawn(&self.inner, their_stdin, their_stdout, their_stderr) {
+        match imp::Process::spawn(&self.inner, their_stdin, their_stdout,
+                                  their_stderr) {
             Err(e) => Err(e),
             Ok(handle) => Ok(Child {
                 handle: handle,
@@ -253,7 +270,7 @@ impl Command {
 
     /// Executes the command as a child process, returning a handle to it.
     ///
-    /// By default, stdin, stdout and stderr are inherited by the parent.
+    /// By default, stdin, stdout and stderr are inherited from the parent.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn spawn(&mut self) -> io::Result<Child> {
         self.spawn_inner(StdioImp::Inherit)
@@ -279,13 +296,13 @@ impl Command {
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn output(&mut self) -> io::Result<Output> {
-        self.spawn_inner(StdioImp::Piped).and_then(|p| p.wait_with_output())
+        self.spawn_inner(StdioImp::MakePipe).and_then(|p| p.wait_with_output())
     }
 
     /// Executes a command as a child process, waiting for it to finish and
     /// collecting its exit status.
     ///
-    /// By default, stdin, stdout and stderr are inherited by the parent.
+    /// By default, stdin, stdout and stderr are inherited from the parent.
     ///
     /// # Examples
     ///
@@ -318,29 +335,38 @@ impl fmt::Debug for Command {
     }
 }
 
-impl AsInner<CommandImp> for Command {
-    fn as_inner(&self) -> &CommandImp { &self.inner }
+impl AsInner<imp::Command> for Command {
+    fn as_inner(&self) -> &imp::Command { &self.inner }
 }
 
-impl AsInnerMut<CommandImp> for Command {
-    fn as_inner_mut(&mut self) -> &mut CommandImp { &mut self.inner }
+impl AsInnerMut<imp::Command> for Command {
+    fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
 }
 
-fn setup_io(io: &StdioImp, readable: bool)
-            -> io::Result<(StdioImp2, Option<AnonPipe>)>
+// Takes a `Stdio` configuration (this module) and whether the to-be-owned
+// handle will be readable.
+//
+// Returns a triple of (stdio to spawn with, stdio to store, stdio to drop). The
+// stdio to spawn with is passed down to the `sys` module and indicates how the
+// stdio stream should be set up. The "stdio to store" is an object which
+// should be returned in the `Child` that makes its way out. The "stdio to drop"
+// represents the raw value of "stdio to spawn with", but is the owned variant
+// for it. This needs to be dropped after the child spawns
+fn setup_io(io: &Stdio, readable: bool)
+            -> io::Result<(imp::Stdio, Option<AnonPipe>, Option<AnonPipe>)>
 {
-    use self::StdioImp::*;
-    Ok(match *io {
-        Null => (StdioImp2::None, None),
-        Inherit => (StdioImp2::Inherit, None),
-        Piped => {
+    Ok(match io.0 {
+        StdioImp::MakePipe => {
             let (reader, writer) = try!(pipe::anon_pipe());
             if readable {
-                (StdioImp2::Piped(reader), Some(writer))
+                (imp::Stdio::Raw(reader.raw()), Some(writer), Some(reader))
             } else {
-                (StdioImp2::Piped(writer), Some(reader))
+                (imp::Stdio::Raw(writer.raw()), Some(reader), Some(writer))
             }
         }
+        StdioImp::Raw(ref owned) => (imp::Stdio::Raw(owned.raw()), None, None),
+        StdioImp::Inherit => (imp::Stdio::Inherit, None, None),
+        StdioImp::None => (imp::Stdio::None, None, None),
     })
 }
 
@@ -364,17 +390,17 @@ pub struct Output {
 pub struct Stdio(StdioImp);
 
 // The internal enum for stdio setup; see below for descriptions.
-#[derive(Clone)]
 enum StdioImp {
-    Piped,
+    MakePipe,
+    Raw(imp::RawStdio),
     Inherit,
-    Null,
+    None,
 }
 
 impl Stdio {
     /// A new pipe should be arranged to connect the parent and child processes.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn piped() -> Stdio { Stdio(StdioImp::Piped) }
+    pub fn piped() -> Stdio { Stdio(StdioImp::MakePipe) }
 
     /// The child inherits from the corresponding parent descriptor.
     #[stable(feature = "process", since = "1.0.0")]
@@ -383,13 +409,19 @@ impl Stdio {
     /// This stream will be ignored. This is the equivalent of attaching the
     /// stream to `/dev/null`
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn null() -> Stdio { Stdio(StdioImp::Null) }
+    pub fn null() -> Stdio { Stdio(StdioImp::None) }
+}
+
+impl FromInner<imp::RawStdio> for Stdio {
+    fn from_inner(inner: imp::RawStdio) -> Stdio {
+        Stdio(StdioImp::Raw(inner))
+    }
 }
 
 /// Describes the result of a process after it has terminated.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "process", since = "1.0.0")]
-pub struct ExitStatus(ExitStatusImp);
+pub struct ExitStatus(imp::ExitStatus);
 
 impl ExitStatus {
     /// Was termination successful? Signal termination not considered a success,
@@ -410,8 +442,8 @@ impl ExitStatus {
     }
 }
 
-impl AsInner<ExitStatusImp> for ExitStatus {
-    fn as_inner(&self) -> &ExitStatusImp { &self.0 }
+impl AsInner<imp::ExitStatus> for ExitStatus {
+    fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
 }
 
 #[stable(feature = "process", since = "1.0.0")]
@@ -456,6 +488,12 @@ impl Child {
         unsafe { self.handle.kill() }
     }
 
+    /// Returns the OS-assigned process identifier associated with this child.
+    #[unstable(feature = "process_id", reason = "api recently added")]
+    pub fn id(&self) -> u32 {
+        self.handle.id()
+    }
+
     /// Waits for the child to exit completely, returning the status that it
     /// exited with. This function will continue to have the same return value
     /// after it has been called at least once.
@@ -731,24 +769,6 @@ mod tests {
         }
     }
 
-    #[cfg(all(unix, not(target_os="android")))]
-    pub fn pwd_cmd() -> Command {
-        Command::new("pwd")
-    }
-    #[cfg(target_os="android")]
-    pub fn pwd_cmd() -> Command {
-        let mut cmd = Command::new("/system/bin/sh");
-        cmd.arg("-c").arg("pwd");
-        cmd
-    }
-
-    #[cfg(windows)]
-    pub fn pwd_cmd() -> Command {
-        let mut cmd = Command::new("cmd");
-        cmd.arg("/c").arg("cd");
-        cmd
-    }
-
     #[cfg(all(unix, not(target_os="android")))]
     pub fn env_cmd() -> Command {
         Command::new("env")
index e11a5818966fa2125e1d2796c7bb2b9eb41cb4f9..b806afc5951d8651c0c7b4ce987317f4f0fcf0d1 100644 (file)
@@ -95,7 +95,7 @@ impl StdRng {
     /// appropriate.
     ///
     /// Reading the randomness from the OS may fail, and any error is
-    /// propagated via the `IoResult` return value.
+    /// propagated via the `io::Result` return value.
     pub fn new() -> io::Result<StdRng> {
         OsRng::new().map(|mut r| StdRng { rng: r.gen() })
     }
index 3c36f0f1d490c223dbd01c57d52654cf8501c916..a2e6915a6a6f7db90769bf238cc0d8b7559ee2ee 100644 (file)
@@ -96,11 +96,11 @@ mod imp {
                   target_arch = "aarch64",
                   target_arch = "powerpc")))]
     fn is_getrandom_available() -> bool {
-        use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
-        use sync::{Once, ONCE_INIT};
+        use sync::atomic::{AtomicBool, Ordering};
+        use sync::Once;
 
-        static CHECKER: Once = ONCE_INIT;
-        static AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT;
+        static CHECKER: Once = Once::new();
+        static AVAILABLE: AtomicBool = AtomicBool::new(false);
 
         CHECKER.call_once(|| {
             let mut buf: [u8; 0] = [];
@@ -279,6 +279,7 @@ mod imp {
     const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
 
     #[allow(non_snake_case)]
+    #[link(name = "advapi32")]
     extern "system" {
         fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                 pszContainer: LPCSTR,
index 2329861f29bc06dc6b7428d8ecb9fc560720a573..d23a124a6ecda21ddc572d19f8dc37aa7f9dd2e2 100644 (file)
@@ -52,10 +52,10 @@ mod imp {
     use mem;
     use ffi::CStr;
 
-    use sync::{StaticMutex, MUTEX_INIT};
+    use sync::StaticMutex;
 
     static mut GLOBAL_ARGS_PTR: usize = 0;
-    static LOCK: StaticMutex = MUTEX_INIT;
+    static LOCK: StaticMutex = StaticMutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
         let args = load_argc_and_argv(argc, argv);
index beb2870807a7e1aab75edf77b704879eb78e50ca..17d2940a6f10c4ab8c2818c8b4f20d37e3b1e21e 100644 (file)
 // segfaults (the queue's memory is mysteriously gone), so
 // instead the cleanup is tied to the `std::rt` entry point.
 
-use boxed;
+use alloc::boxed::FnBox;
 use boxed::Box;
+use sys_common::mutex::Mutex;
 use vec::Vec;
-use thunk::Thunk;
-use sys_common::mutex::{Mutex, MUTEX_INIT};
 
-type Queue = Vec<Thunk<'static>>;
+type Queue = Vec<Box<FnBox()>>;
 
 // NB these are specifically not types from `std::sync` as they currently rely
 // on poisoning and this module needs to operate at a lower level than requiring
 // the thread infrastructure to be in place (useful on the borders of
 // initialization/destruction).
-static LOCK: Mutex = MUTEX_INIT;
+static LOCK: Mutex = Mutex::new();
 static mut QUEUE: *mut Queue = 0 as *mut Queue;
 
 // The maximum number of times the cleanup routines will be run. While running
@@ -40,7 +39,7 @@ const ITERS: usize = 10;
 unsafe fn init() -> bool {
     if QUEUE.is_null() {
         let state: Box<Queue> = box Vec::new();
-        QUEUE = boxed::into_raw(state);
+        QUEUE = Box::into_raw(state);
     } else if QUEUE as usize == 1 {
         // can't re-init after a cleanup
         return false
@@ -71,7 +70,7 @@ pub fn cleanup() {
     }
 }
 
-pub fn push(f: Thunk<'static>) -> bool {
+pub fn push(f: Box<FnBox()>) -> bool {
     let mut ret = true;
     unsafe {
         LOCK.lock();
index 72cbe2b533bb7fc6b62cf366861085d55945e186..2eadf36a6b4f0424abc762efff0c632bf8092dc1 100644 (file)
@@ -22,7 +22,7 @@ pub use sys::backtrace::write;
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
 pub fn log_enabled() -> bool {
-    static ENABLED: atomic::AtomicIsize = atomic::ATOMIC_ISIZE_INIT;
+    static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
     match ENABLED.load(Ordering::SeqCst) {
         1 => return false,
         2 => return true,
index 0d26206f26bcfc67630547b035b5ff7c66189f2c..1729d20da205c686d5763195b8988432f38a65ee 100644 (file)
@@ -16,7 +16,9 @@
 //! and should be considered as private implementation details for the
 //! time being.
 
-#![unstable(feature = "std_misc")]
+#![unstable(feature = "rt",
+            reason = "this public module should not exist and is highly likely \
+                      to disappear")]
 #![allow(missing_docs)]
 
 use prelude::v1::*;
@@ -137,7 +139,9 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
     if failed {
         rt::DEFAULT_ERROR_CODE
     } else {
-        env::get_exit_status() as isize
+        #[allow(deprecated)]
+        fn exit_status() -> isize { env::get_exit_status() as isize }
+        exit_status()
     }
 }
 
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
deleted file mode 100644 (file)
index b240995..0000000
+++ /dev/null
@@ -1,615 +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.
-
-//! Implementation of Rust stack unwinding
-//!
-//! For background on exception handling and stack unwinding please see
-//! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and
-//! documents linked from it.
-//! These are also good reads:
-//!     http://theofilos.cs.columbia.edu/blog/2013/09/22/base_abi/
-//!     http://monoinfinito.wordpress.com/series/exception-handling-in-c/
-//!     http://www.airs.com/blog/index.php?s=exception+frames
-//!
-//! ## A brief summary
-//!
-//! Exception handling happens in two phases: a search phase and a cleanup phase.
-//!
-//! In both phases the unwinder walks stack frames from top to bottom using
-//! information from the stack frame unwind sections of the current process's
-//! modules ("module" here refers to an OS module, i.e. an executable or a
-//! dynamic library).
-//!
-//! For each stack frame, it invokes the associated "personality routine", whose
-//! address is also stored in the unwind info section.
-//!
-//! In the search phase, the job of a personality routine is to examine exception
-//! object being thrown, and to decide whether it should be caught at that stack
-//! frame.  Once the handler frame has been identified, cleanup phase begins.
-//!
-//! In the cleanup phase, personality routines invoke cleanup code associated
-//! with their stack frames (i.e. destructors).  Once stack has been unwound down
-//! to the handler frame level, unwinding stops and the last personality routine
-//! transfers control to its catch block.
-//!
-//! ## Frame unwind info registration
-//!
-//! Each module has its own frame unwind info section (usually ".eh_frame"), and
-//! unwinder needs to know about all of them in order for unwinding to be able to
-//! cross module boundaries.
-//!
-//! On some platforms, like Linux, this is achieved by dynamically enumerating
-//! currently loaded modules via the dl_iterate_phdr() API and finding all
-//! .eh_frame sections.
-//!
-//! Others, like Windows, require modules to actively register their unwind info
-//! sections by calling __register_frame_info() API at startup.  In the latter
-//! case it is essential that there is only one copy of the unwinder runtime in
-//! the process.  This is usually achieved by linking to the dynamic version of
-//! the unwind runtime.
-//!
-//! Currently Rust uses unwind runtime provided by libgcc.
-
-use prelude::v1::*;
-
-use any::Any;
-use boxed;
-use cell::Cell;
-use cmp;
-use panicking;
-use fmt;
-use intrinsics;
-use libc::c_void;
-use mem;
-use sync::atomic::{self, Ordering};
-use sys_common::mutex::{Mutex, MUTEX_INIT};
-
-use rt::libunwind as uw;
-
-struct Exception {
-    uwe: uw::_Unwind_Exception,
-    cause: Option<Box<Any + Send + 'static>>,
-}
-
-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::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT];
-static CALLBACK_CNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
-
-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
-/// return `Err(cause)` if the closure panics. The `cause` returned is the
-/// object with which panic was originally invoked.
-///
-/// This function also is unsafe for a variety of reasons:
-///
-/// * This is not safe to call in a nested fashion. The unwinding
-///   interface for Rust is designed to have at most one try/catch block per
-///   thread, not multiple. No runtime checking is currently performed to uphold
-///   this invariant, so this function is not safe. A nested try/catch block
-///   may result in corruption of the outer try/catch block's state, especially
-///   if this is used within a thread itself.
-///
-/// * It is not sound to trigger unwinding while already unwinding. Rust threads
-///   have runtime checks in place to ensure this invariant, but it is not
-///   guaranteed that a rust thread is in place when invoking this function.
-///   Unwinding twice can lead to resource leaks where some destructors are not
-///   run.
-pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
-    let mut f = Some(f);
-
-    let prev = PANICKING.with(|s| s.get());
-    PANICKING.with(|s| s.set(false));
-    let ep = rust_try(try_fn::<F>, &mut f as *mut _ as *mut c_void);
-    PANICKING.with(|s| s.set(prev));
-    return if ep.is_null() {
-        Ok(())
-    } else {
-        let my_ep = ep as *mut Exception;
-        rtdebug!("caught {}", (*my_ep).uwe.exception_class);
-        let cause = (*my_ep).cause.take();
-        uw::_Unwind_DeleteException(ep);
-        Err(cause.unwrap())
-    };
-
-    extern fn try_fn<F: FnOnce()>(opt_closure: *mut c_void) {
-        let opt_closure = opt_closure as *mut Option<F>;
-        unsafe { (*opt_closure).take().unwrap()(); }
-    }
-
-    #[link(name = "rustrt_native", kind = "static")]
-    #[cfg(not(test))]
-    extern {}
-
-    extern {
-        // Rust's try-catch
-        // When f(...) returns normally, the return value is null.
-        // When f(...) throws, the return value is a pointer to the caught
-        // exception object.
-        fn rust_try(f: extern fn(*mut c_void),
-                    data: *mut c_void) -> *mut uw::_Unwind_Exception;
-    }
-}
-
-/// Determines whether the current thread is unwinding because of panic.
-pub fn panicking() -> bool {
-    PANICKING.with(|s| s.get())
-}
-
-// An uninlined, unmangled function upon which to slap yer breakpoints
-#[inline(never)]
-#[no_mangle]
-#[allow(private_no_mangle_fns)]
-fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
-    rtdebug!("begin_unwind()");
-
-    unsafe {
-        let exception: Box<_> = box Exception {
-            uwe: uw::_Unwind_Exception {
-                exception_class: rust_exception_class(),
-                exception_cleanup: exception_cleanup,
-                private: [0; uw::unwinder_private_data_size],
-            },
-            cause: Some(cause),
-        };
-        let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception;
-        let error = uw::_Unwind_RaiseException(exception_param);
-        rtabort!("Could not unwind stack, error = {}", error as isize)
-    }
-
-    extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code,
-                                exception: *mut uw::_Unwind_Exception) {
-        rtdebug!("exception_cleanup()");
-        unsafe {
-            let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
-        }
-    }
-}
-
-// Rust's exception class identifier.  This is used by personality routines to
-// determine whether the exception was thrown by their own runtime.
-fn rust_exception_class() -> uw::_Unwind_Exception_Class {
-    // M O Z \0  R U S T -- vendor, language
-    0x4d4f5a_00_52555354
-}
-
-// We could implement our personality routine in pure Rust, however exception
-// info decoding is tedious.  More importantly, personality routines have to
-// handle various platform quirks, which are not fun to maintain.  For this
-// reason, we attempt to reuse personality routine of the C language:
-// __gcc_personality_v0.
-//
-// Since C does not support exception catching, __gcc_personality_v0 simply
-// always returns _URC_CONTINUE_UNWIND in search phase, and always returns
-// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
-//
-// This is pretty close to Rust's exception handling approach, except that Rust
-// does have a single "catch-all" handler at the bottom of each thread's stack.
-// So we have two versions of the personality routine:
-// - rust_eh_personality, used by all cleanup landing pads, which never catches,
-//   so the behavior of __gcc_personality_v0 is perfectly adequate there, and
-// - rust_eh_personality_catch, used only by rust_try(), which always catches.
-//
-// Note, however, that for implementation simplicity, rust_eh_personality_catch
-// lacks code to install a landing pad, so in order to obtain exception object
-// pointer (which it needs to return upstream), rust_try() employs another trick:
-// it calls into the nested rust_try_inner(), whose landing pad does not resume
-// unwinds.  Instead, it extracts the exception pointer and performs a "normal"
-// return.
-//
-// See also: rt/rust_try.ll
-
-#[cfg(all(not(target_arch = "arm"),
-          not(all(windows, target_arch = "x86_64")),
-          not(test)))]
-#[doc(hidden)]
-pub mod eabi {
-    use rt::libunwind as uw;
-    use libc::c_int;
-
-    extern "C" {
-        fn __gcc_personality_v0(version: c_int,
-                                actions: uw::_Unwind_Action,
-                                exception_class: uw::_Unwind_Exception_Class,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-            -> uw::_Unwind_Reason_Code;
-    }
-
-    #[lang = "eh_personality"]
-    #[no_mangle] // referenced from rust_try.ll
-    #[allow(private_no_mangle_fns)]
-    extern fn rust_eh_personality(
-        version: c_int,
-        actions: uw::_Unwind_Action,
-        exception_class: uw::_Unwind_Exception_Class,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-        unsafe {
-            __gcc_personality_v0(version, actions, exception_class, ue_header,
-                                 context)
-        }
-    }
-
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality_catch(
-        _version: c_int,
-        actions: uw::_Unwind_Action,
-        _exception_class: uw::_Unwind_Exception_Class,
-        _ue_header: *mut uw::_Unwind_Exception,
-        _context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-
-        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        }
-        else { // cleanup phase
-            uw::_URC_INSTALL_CONTEXT
-        }
-    }
-}
-
-// iOS on armv7 is using SjLj exceptions and therefore requires to use
-// a specialized personality routine: __gcc_personality_sj0
-
-#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))]
-#[doc(hidden)]
-pub mod eabi {
-    use rt::libunwind as uw;
-    use libc::c_int;
-
-    extern "C" {
-        fn __gcc_personality_sj0(version: c_int,
-                                actions: uw::_Unwind_Action,
-                                exception_class: uw::_Unwind_Exception_Class,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-            -> uw::_Unwind_Reason_Code;
-    }
-
-    #[lang = "eh_personality"]
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality(
-        version: c_int,
-        actions: uw::_Unwind_Action,
-        exception_class: uw::_Unwind_Exception_Class,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-        unsafe {
-            __gcc_personality_sj0(version, actions, exception_class, ue_header,
-                                  context)
-        }
-    }
-
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality_catch(
-        _version: c_int,
-        actions: uw::_Unwind_Action,
-        _exception_class: uw::_Unwind_Exception_Class,
-        _ue_header: *mut uw::_Unwind_Exception,
-        _context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        }
-        else { // cleanup phase
-            unsafe {
-                __gcc_personality_sj0(_version, actions, _exception_class, _ue_header,
-                                      _context)
-            }
-        }
-    }
-}
-
-
-// ARM EHABI uses a slightly different personality routine signature,
-// but otherwise works the same.
-#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))]
-#[doc(hidden)]
-pub mod eabi {
-    use rt::libunwind as uw;
-    use libc::c_int;
-
-    extern "C" {
-        fn __gcc_personality_v0(state: uw::_Unwind_State,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-            -> uw::_Unwind_Reason_Code;
-    }
-
-    #[lang = "eh_personality"]
-    #[no_mangle] // referenced from rust_try.ll
-    #[allow(private_no_mangle_fns)]
-    extern "C" fn rust_eh_personality(
-        state: uw::_Unwind_State,
-        ue_header: *mut uw::_Unwind_Exception,
-        context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-        unsafe {
-            __gcc_personality_v0(state, ue_header, context)
-        }
-    }
-
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality_catch(
-        state: uw::_Unwind_State,
-        _ue_header: *mut uw::_Unwind_Exception,
-        _context: *mut uw::_Unwind_Context
-    ) -> uw::_Unwind_Reason_Code
-    {
-        if (state as c_int & uw::_US_ACTION_MASK as c_int)
-                           == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        }
-        else { // cleanup phase
-            uw::_URC_INSTALL_CONTEXT
-        }
-    }
-}
-
-// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx)
-//
-// This looks a bit convoluted because rather than implementing a native SEH handler,
-// GCC reuses the same personality routine as for the other architectures by wrapping it
-// with an "API translator" layer (_GCC_specific_handler).
-
-#[cfg(all(windows, target_arch = "x86_64", not(test)))]
-#[doc(hidden)]
-#[allow(non_camel_case_types, non_snake_case)]
-pub mod eabi {
-    pub use self::EXCEPTION_DISPOSITION::*;
-    use rt::libunwind as uw;
-    use libc::{c_void, c_int};
-
-    #[repr(C)]
-    pub struct EXCEPTION_RECORD;
-    #[repr(C)]
-    pub struct CONTEXT;
-    #[repr(C)]
-    pub struct DISPATCHER_CONTEXT;
-
-    #[repr(C)]
-    #[derive(Copy, Clone)]
-    pub enum EXCEPTION_DISPOSITION {
-        ExceptionContinueExecution,
-        ExceptionContinueSearch,
-        ExceptionNestedException,
-        ExceptionCollidedUnwind
-    }
-
-    type _Unwind_Personality_Fn =
-        extern "C" fn(
-            version: c_int,
-            actions: uw::_Unwind_Action,
-            exception_class: uw::_Unwind_Exception_Class,
-            ue_header: *mut uw::_Unwind_Exception,
-            context: *mut uw::_Unwind_Context
-        ) -> uw::_Unwind_Reason_Code;
-
-    extern "C" {
-        fn __gcc_personality_seh0(
-            exceptionRecord: *mut EXCEPTION_RECORD,
-            establisherFrame: *mut c_void,
-            contextRecord: *mut CONTEXT,
-            dispatcherContext: *mut DISPATCHER_CONTEXT
-        ) -> EXCEPTION_DISPOSITION;
-
-        fn _GCC_specific_handler(
-            exceptionRecord: *mut EXCEPTION_RECORD,
-            establisherFrame: *mut c_void,
-            contextRecord: *mut CONTEXT,
-            dispatcherContext: *mut DISPATCHER_CONTEXT,
-            personality: _Unwind_Personality_Fn
-        ) -> EXCEPTION_DISPOSITION;
-    }
-
-    #[lang = "eh_personality"]
-    #[no_mangle] // referenced from rust_try.ll
-    #[allow(private_no_mangle_fns)]
-    extern "C" fn rust_eh_personality(
-        exceptionRecord: *mut EXCEPTION_RECORD,
-        establisherFrame: *mut c_void,
-        contextRecord: *mut CONTEXT,
-        dispatcherContext: *mut DISPATCHER_CONTEXT
-    ) -> EXCEPTION_DISPOSITION
-    {
-        unsafe {
-            __gcc_personality_seh0(exceptionRecord, establisherFrame,
-                                   contextRecord, dispatcherContext)
-        }
-    }
-
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality_catch(
-        exceptionRecord: *mut EXCEPTION_RECORD,
-        establisherFrame: *mut c_void,
-        contextRecord: *mut CONTEXT,
-        dispatcherContext: *mut DISPATCHER_CONTEXT
-    ) -> EXCEPTION_DISPOSITION
-    {
-        extern "C" fn inner(
-                _version: c_int,
-                actions: uw::_Unwind_Action,
-                _exception_class: uw::_Unwind_Exception_Class,
-                _ue_header: *mut uw::_Unwind_Exception,
-                _context: *mut uw::_Unwind_Context
-            ) -> uw::_Unwind_Reason_Code
-        {
-            if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
-                uw::_URC_HANDLER_FOUND // catch!
-            }
-            else { // cleanup phase
-                uw::_URC_INSTALL_CONTEXT
-            }
-        }
-
-        unsafe {
-            _GCC_specific_handler(exceptionRecord, establisherFrame,
-                                  contextRecord, dispatcherContext,
-                                  inner)
-        }
-    }
-}
-
-#[cfg(not(test))]
-/// Entry point of panic from the libcore crate.
-#[lang = "panic_fmt"]
-pub extern fn rust_begin_unwind(msg: fmt::Arguments,
-                                file: &'static str, line: u32) -> ! {
-    begin_unwind_fmt(msg, &(file, line))
-}
-
-/// The entry point for unwinding with a formatted message.
-///
-/// This is designed to reduce the amount of code required at the call
-/// site as much as possible (so that `panic!()` has as low an impact
-/// on (e.g.) the inlining of other functions as possible), by moving
-/// the actual formatting into this shared place.
-#[inline(never)] #[cold]
-pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
-    use fmt::Write;
-
-    // We do two allocations here, unfortunately. But (a) they're
-    // required with the current scheme, and (b) we don't handle
-    // panic + OOM properly anyway (see comment in begin_unwind
-    // below).
-
-    let mut s = String::new();
-    let _ = s.write_fmt(msg);
-    begin_unwind_inner(Box::new(s), file_line)
-}
-
-/// This is the entry point of unwinding for panic!() and assert!().
-#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
-pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> ! {
-    // Note that this should be the only allocation performed in this code path.
-    // Currently this means that panic!() on OOM will invoke this code path,
-    // but then again we're not really ready for panic on OOM anyway. If
-    // we do start doing this, then we should propagate this allocation to
-    // be performed in the parent of this thread instead of the thread that's
-    // panicking.
-
-    // see below for why we do the `Any` coercion here.
-    begin_unwind_inner(Box::new(msg), file_line)
-}
-
-/// The core of the unwinding.
-///
-/// This is non-generic to avoid instantiation bloat in other crates
-/// (which makes compilation of small crates noticeably slower). (Note:
-/// we need the `Any` object anyway, we're not just creating it to
-/// avoid being generic.)
-///
-/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
-/// }` from ~1900/3700 (-O/no opts) to 180/590.
-#[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_INIT;
-        static mut INIT: bool = false;
-        LOCK.lock();
-        if !INIT {
-            register(panicking::on_panic);
-            INIT = true;
-        }
-        LOCK.unlock();
-    }
-
-    // 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);
-            }
-        }
-    };
-
-    // 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.
-        rterrln!("thread panicked while panicking. aborting.");
-        unsafe { intrinsics::abort() }
-    }
-    PANICKING.with(|s| s.set(true));
-    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
-        }
-    }
-}
diff --git a/src/libstd/rt/unwind/gcc.rs b/src/libstd/rt/unwind/gcc.rs
new file mode 100644 (file)
index 0000000..84c6d68
--- /dev/null
@@ -0,0 +1,341 @@
+// 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 prelude::v1::*;
+
+use any::Any;
+use libc::c_void;
+use rt::libunwind as uw;
+
+struct Exception {
+    uwe: uw::_Unwind_Exception,
+    cause: Option<Box<Any + Send + 'static>>,
+}
+
+pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
+    let exception: Box<_> = box Exception {
+        uwe: uw::_Unwind_Exception {
+            exception_class: rust_exception_class(),
+            exception_cleanup: exception_cleanup,
+            private: [0; uw::unwinder_private_data_size],
+        },
+        cause: Some(data),
+    };
+    let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
+    let error = uw::_Unwind_RaiseException(exception_param);
+    rtabort!("Could not unwind stack, error = {}", error as isize);
+
+    extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code,
+                                exception: *mut uw::_Unwind_Exception) {
+        rtdebug!("exception_cleanup()");
+        unsafe {
+            let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
+        }
+    }
+}
+
+pub unsafe fn cleanup(ptr: *mut c_void) -> Box<Any + Send + 'static> {
+    let my_ep = ptr as *mut Exception;
+    rtdebug!("caught {}", (*my_ep).uwe.exception_class);
+    let cause = (*my_ep).cause.take();
+    uw::_Unwind_DeleteException(ptr as *mut _);
+    cause.unwrap()
+}
+
+// Rust's exception class identifier.  This is used by personality routines to
+// determine whether the exception was thrown by their own runtime.
+fn rust_exception_class() -> uw::_Unwind_Exception_Class {
+    // M O Z \0  R U S T -- vendor, language
+    0x4d4f5a_00_52555354
+}
+
+// We could implement our personality routine in pure Rust, however exception
+// info decoding is tedious.  More importantly, personality routines have to
+// handle various platform quirks, which are not fun to maintain.  For this
+// reason, we attempt to reuse personality routine of the C language:
+// __gcc_personality_v0.
+//
+// Since C does not support exception catching, __gcc_personality_v0 simply
+// always returns _URC_CONTINUE_UNWIND in search phase, and always returns
+// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
+//
+// This is pretty close to Rust's exception handling approach, except that Rust
+// does have a single "catch-all" handler at the bottom of each thread's stack.
+// So we have two versions of the personality routine:
+// - rust_eh_personality, used by all cleanup landing pads, which never catches,
+//   so the behavior of __gcc_personality_v0 is perfectly adequate there, and
+// - rust_eh_personality_catch, used only by rust_try(), which always catches.
+//
+// Note, however, that for implementation simplicity, rust_eh_personality_catch
+// lacks code to install a landing pad, so in order to obtain exception object
+// pointer (which it needs to return upstream), rust_try() employs another trick:
+// it calls into the nested rust_try_inner(), whose landing pad does not resume
+// unwinds.  Instead, it extracts the exception pointer and performs a "normal"
+// return.
+//
+// See also: rt/rust_try.ll
+
+#[cfg(all(not(target_arch = "arm"),
+          not(all(windows, target_arch = "x86_64")),
+          not(test)))]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_v0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    #[allow(private_no_mangle_fns)]
+    extern fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_v0(version, actions, exception_class, ue_header,
+                                 context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        _version: c_int,
+        actions: uw::_Unwind_Action,
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            uw::_URC_INSTALL_CONTEXT
+        }
+    }
+}
+
+// iOS on armv7 is using SjLj exceptions and therefore requires to use
+// a specialized personality routine: __gcc_personality_sj0
+
+#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_sj0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_sj0(version, actions, exception_class, ue_header,
+                                  context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        _version: c_int,
+        actions: uw::_Unwind_Action,
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            unsafe {
+                __gcc_personality_sj0(_version, actions, _exception_class, _ue_header,
+                                      _context)
+            }
+        }
+    }
+}
+
+
+// ARM EHABI uses a slightly different personality routine signature,
+// but otherwise works the same.
+#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_v0(state: uw::_Unwind_State,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    #[allow(private_no_mangle_fns)]
+    extern "C" fn rust_eh_personality(
+        state: uw::_Unwind_State,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_v0(state, ue_header, context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        state: uw::_Unwind_State,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (state as c_int & uw::_US_ACTION_MASK as c_int)
+                           == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            uw::_URC_INSTALL_CONTEXT
+        }
+    }
+}
+
+// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx)
+//
+// This looks a bit convoluted because rather than implementing a native SEH
+// handler, GCC reuses the same personality routine as for the other
+// architectures by wrapping it with an "API translator" layer
+// (_GCC_specific_handler).
+
+#[cfg(all(windows, target_arch = "x86_64", not(test)))]
+#[doc(hidden)]
+#[allow(non_camel_case_types, non_snake_case)]
+pub mod eabi {
+    pub use self::EXCEPTION_DISPOSITION::*;
+    use rt::libunwind as uw;
+    use libc::{c_void, c_int};
+
+    #[repr(C)]
+    pub struct EXCEPTION_RECORD;
+    #[repr(C)]
+    pub struct CONTEXT;
+    #[repr(C)]
+    pub struct DISPATCHER_CONTEXT;
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub enum EXCEPTION_DISPOSITION {
+        ExceptionContinueExecution,
+        ExceptionContinueSearch,
+        ExceptionNestedException,
+        ExceptionCollidedUnwind
+    }
+
+    type _Unwind_Personality_Fn =
+        extern "C" fn(
+            version: c_int,
+            actions: uw::_Unwind_Action,
+            exception_class: uw::_Unwind_Exception_Class,
+            ue_header: *mut uw::_Unwind_Exception,
+            context: *mut uw::_Unwind_Context
+        ) -> uw::_Unwind_Reason_Code;
+
+    extern "C" {
+        fn __gcc_personality_seh0(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT
+        ) -> EXCEPTION_DISPOSITION;
+
+        fn _GCC_specific_handler(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT,
+            personality: _Unwind_Personality_Fn
+        ) -> EXCEPTION_DISPOSITION;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    #[allow(private_no_mangle_fns)]
+    extern "C" fn rust_eh_personality(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        unsafe {
+            __gcc_personality_seh0(exceptionRecord, establisherFrame,
+                                   contextRecord, dispatcherContext)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        extern "C" fn inner(
+                _version: c_int,
+                actions: uw::_Unwind_Action,
+                _exception_class: uw::_Unwind_Exception_Class,
+                _ue_header: *mut uw::_Unwind_Exception,
+                _context: *mut uw::_Unwind_Context
+            ) -> uw::_Unwind_Reason_Code
+        {
+            if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+                uw::_URC_HANDLER_FOUND // catch!
+            }
+            else { // cleanup phase
+                uw::_URC_INSTALL_CONTEXT
+            }
+        }
+
+        unsafe {
+            _GCC_specific_handler(exceptionRecord, establisherFrame,
+                                  contextRecord, dispatcherContext,
+                                  inner)
+        }
+    }
+}
+
diff --git a/src/libstd/rt/unwind/mod.rs b/src/libstd/rt/unwind/mod.rs
new file mode 100644 (file)
index 0000000..c403976
--- /dev/null
@@ -0,0 +1,319 @@
+// 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.
+
+//! Implementation of Rust stack unwinding
+//!
+//! For background on exception handling and stack unwinding please see
+//! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and
+//! documents linked from it.
+//! These are also good reads:
+//!     http://theofilos.cs.columbia.edu/blog/2013/09/22/base_abi/
+//!     http://monoinfinito.wordpress.com/series/exception-handling-in-c/
+//!     http://www.airs.com/blog/index.php?s=exception+frames
+//!
+//! ## A brief summary
+//!
+//! Exception handling happens in two phases: a search phase and a cleanup phase.
+//!
+//! In both phases the unwinder walks stack frames from top to bottom using
+//! information from the stack frame unwind sections of the current process's
+//! modules ("module" here refers to an OS module, i.e. an executable or a
+//! dynamic library).
+//!
+//! For each stack frame, it invokes the associated "personality routine", whose
+//! address is also stored in the unwind info section.
+//!
+//! In the search phase, the job of a personality routine is to examine exception
+//! object being thrown, and to decide whether it should be caught at that stack
+//! frame.  Once the handler frame has been identified, cleanup phase begins.
+//!
+//! In the cleanup phase, personality routines invoke cleanup code associated
+//! with their stack frames (i.e. destructors).  Once stack has been unwound down
+//! to the handler frame level, unwinding stops and the last personality routine
+//! transfers control to its catch block.
+//!
+//! ## Frame unwind info registration
+//!
+//! Each module has its own frame unwind info section (usually ".eh_frame"), and
+//! unwinder needs to know about all of them in order for unwinding to be able to
+//! cross module boundaries.
+//!
+//! On some platforms, like Linux, this is achieved by dynamically enumerating
+//! currently loaded modules via the dl_iterate_phdr() API and finding all
+//! .eh_frame sections.
+//!
+//! Others, like Windows, require modules to actively register their unwind info
+//! sections by calling __register_frame_info() API at startup.  In the latter
+//! case it is essential that there is only one copy of the unwinder runtime in
+//! the process.  This is usually achieved by linking to the dynamic version of
+//! the unwind runtime.
+//!
+//! Currently Rust uses unwind runtime provided by libgcc.
+
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+use prelude::v1::*;
+
+use any::Any;
+use boxed;
+use cell::Cell;
+use cmp;
+use panicking;
+use fmt;
+use intrinsics;
+use libc::c_void;
+use mem;
+use sync::atomic::{self, Ordering};
+use sys_common::mutex::Mutex;
+
+// The actual unwinding implementation is cfg'd here, and we've got two current
+// implementations. One goes through SEH on Windows and the other goes through
+// libgcc via the libunwind-like API.
+#[cfg(target_env = "msvc")] #[path = "seh.rs"] #[doc(hidden)]
+pub mod imp;
+#[cfg(not(target_env = "msvc"))] #[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) }
+
+#[link(name = "rustrt_native", kind = "static")]
+#[cfg(not(test))]
+extern {}
+
+/// Invoke a closure, capturing the cause of panic if one occurs.
+///
+/// This function will return `Ok(())` if the closure did not panic, and will
+/// return `Err(cause)` if the closure panics. The `cause` returned is the
+/// object with which panic was originally invoked.
+///
+/// This function also is unsafe for a variety of reasons:
+///
+/// * This is not safe to call in a nested fashion. The unwinding
+///   interface for Rust is designed to have at most one try/catch block per
+///   thread, not multiple. No runtime checking is currently performed to uphold
+///   this invariant, so this function is not safe. A nested try/catch block
+///   may result in corruption of the outer try/catch block's state, especially
+///   if this is used within a thread itself.
+///
+/// * It is not sound to trigger unwinding while already unwinding. Rust threads
+///   have runtime checks in place to ensure this invariant, but it is not
+///   guaranteed that a rust thread is in place when invoking this function.
+///   Unwinding twice can lead to resource leaks where some destructors are not
+///   run.
+pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
+    let mut f = Some(f);
+    return inner_try(try_fn::<F>, &mut f as *mut _ as *mut c_void);
+
+    // If an inner function were not used here, then this generic function `try`
+    // uses the native symbol `rust_try`, for which the code is statically
+    // linked into the standard library. This means that the DLL for the
+    // standard library must have `rust_try` as an exposed symbol that
+    // downstream crates can link against (because monomorphizations of `try` in
+    // downstream crates will have a reference to the `rust_try` symbol).
+    //
+    // On MSVC this requires the symbol `rust_try` to be tagged with
+    // `dllexport`, but it's easier to not have conditional `src/rt/rust_try.ll`
+    // files and instead just have this non-generic shim the compiler can take
+    // care of exposing correctly.
+    unsafe fn inner_try(f: extern fn(*mut c_void), data: *mut c_void)
+                        -> Result<(), Box<Any + Send>> {
+        let prev = PANICKING.with(|s| s.get());
+        PANICKING.with(|s| s.set(false));
+        let ep = rust_try(f, data);
+        PANICKING.with(|s| s.set(prev));
+        if ep.is_null() {
+            Ok(())
+        } else {
+            Err(imp::cleanup(ep))
+        }
+    }
+
+    extern fn try_fn<F: FnOnce()>(opt_closure: *mut c_void) {
+        let opt_closure = opt_closure as *mut Option<F>;
+        unsafe { (*opt_closure).take().unwrap()(); }
+    }
+
+    extern {
+        // Rust's try-catch
+        // When f(...) returns normally, the return value is null.
+        // When f(...) throws, the return value is a pointer to the caught
+        // exception object.
+        fn rust_try(f: extern fn(*mut c_void),
+                    data: *mut c_void) -> *mut c_void;
+    }
+}
+
+/// Determines whether the current thread is unwinding because of panic.
+pub fn panicking() -> bool {
+    PANICKING.with(|s| s.get())
+}
+
+// An uninlined, unmangled function upon which to slap yer breakpoints
+#[inline(never)]
+#[no_mangle]
+#[allow(private_no_mangle_fns)]
+fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
+    rtdebug!("begin_unwind()");
+    unsafe {
+        imp::panic(cause)
+    }
+}
+
+#[cfg(not(test))]
+/// Entry point of panic from the libcore crate.
+#[lang = "panic_fmt"]
+pub extern fn rust_begin_unwind(msg: fmt::Arguments,
+                                file: &'static str, line: u32) -> ! {
+    begin_unwind_fmt(msg, &(file, line))
+}
+
+/// The entry point for unwinding with a formatted message.
+///
+/// This is designed to reduce the amount of code required at the call
+/// site as much as possible (so that `panic!()` has as low an impact
+/// on (e.g.) the inlining of other functions as possible), by moving
+/// the actual formatting into this shared place.
+#[inline(never)] #[cold]
+pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
+    use fmt::Write;
+
+    // We do two allocations here, unfortunately. But (a) they're
+    // required with the current scheme, and (b) we don't handle
+    // panic + OOM properly anyway (see comment in begin_unwind
+    // below).
+
+    let mut s = String::new();
+    let _ = s.write_fmt(msg);
+    begin_unwind_inner(Box::new(s), file_line)
+}
+
+/// This is the entry point of unwinding for panic!() and assert!().
+#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
+pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> ! {
+    // Note that this should be the only allocation performed in this code path.
+    // Currently this means that panic!() on OOM will invoke this code path,
+    // but then again we're not really ready for panic on OOM anyway. If
+    // we do start doing this, then we should propagate this allocation to
+    // be performed in the parent of this thread instead of the thread that's
+    // panicking.
+
+    // see below for why we do the `Any` coercion here.
+    begin_unwind_inner(Box::new(msg), file_line)
+}
+
+/// The core of the unwinding.
+///
+/// This is non-generic to avoid instantiation bloat in other crates
+/// (which makes compilation of small crates noticeably slower). (Note:
+/// we need the `Any` object anyway, we're not just creating it to
+/// avoid being generic.)
+///
+/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
+/// }` from ~1900/3700 (-O/no opts) to 180/590.
+#[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();
+    }
+
+    // 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);
+            }
+        }
+    };
+
+    // 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.
+        rterrln!("thread panicked while panicking. aborting.");
+        unsafe { intrinsics::abort() }
+    }
+    PANICKING.with(|s| s.set(true));
+    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
+        }
+    }
+}
diff --git a/src/libstd/rt/unwind/seh.rs b/src/libstd/rt/unwind/seh.rs
new file mode 100644 (file)
index 0000000..a72c1de
--- /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 prelude::v1::*;
+
+use any::Any;
+use intrinsics;
+use libc::c_void;
+
+pub unsafe fn panic(_data: Box<Any + Send + 'static>) -> ! {
+    intrinsics::abort();
+}
+
+pub unsafe fn cleanup(_ptr: *mut c_void) -> Box<Any + Send + 'static> {
+    intrinsics::abort();
+}
+
+#[lang = "eh_personality"]
+#[no_mangle]
+pub extern fn rust_eh_personality() {}
+
+#[no_mangle]
+pub extern fn rust_eh_personality_catch() {}
index 31e970a9550c4316a74a3fc3f1a3aad25d0eb3e1..04f36d99c8eb5155ccb8014cc28bc5451eff2267 100644 (file)
@@ -42,7 +42,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
 }
 
 pub fn min_stack() -> usize {
-    static MIN: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
+    static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
     match MIN.load(Ordering::SeqCst) {
         0 => {}
         n => return n - 1,
@@ -63,7 +63,7 @@ pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) ||
                                   cfg!(rtassert);
 
 pub fn dumb_print(args: fmt::Arguments) {
-    let _ = Stderr::new().write_fmt(args);
+    let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
 }
 
 pub fn abort(args: fmt::Arguments) -> ! {
index a7f3bc2bdc82c3a07d5d9441599f74afc9a0d819..be674c83e221351903a0168741077c488cfbf946 100644 (file)
@@ -12,8 +12,6 @@
 //! the standard library This varies per-platform, but these libraries are
 //! necessary for running libstd.
 
-#![unstable(feature = "std_misc")]
-
 // All platforms need to link to rustrt
 #[cfg(not(test))]
 #[link(name = "rust_builtin", kind = "static")]
index 8da917916e5cd5945ba82471ba2dd82c90765994..f2c389f9426ebe3a273e6ac8bb4ff963aabc1d12 100644 (file)
@@ -10,7 +10,7 @@
 
 use prelude::v1::*;
 
-use sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
+use sync::atomic::{AtomicUsize, Ordering};
 use sync::{mutex, MutexGuard, PoisonError};
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
@@ -84,10 +84,7 @@ pub struct StaticCondvar {
 /// Constant initializer for a statically allocated condition variable.
 #[unstable(feature = "static_condvar",
            reason = "may be merged with Condvar in the future")]
-pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
-    inner: sys::CONDVAR_INIT,
-    mutex: ATOMIC_USIZE_INIT,
-};
+pub const CONDVAR_INIT: StaticCondvar = StaticCondvar::new();
 
 impl Condvar {
     /// Creates a new condition variable which is ready to be waited on and
@@ -96,7 +93,7 @@ impl Condvar {
     pub fn new() -> Condvar {
         Condvar {
             inner: box StaticCondvar {
-                inner: unsafe { sys::Condvar::new() },
+                inner: sys::Condvar::new(),
                 mutex: AtomicUsize::new(0),
             }
         }
@@ -234,6 +231,16 @@ impl Drop for Condvar {
 }
 
 impl StaticCondvar {
+    /// Creates a new condition variable
+    #[unstable(feature = "static_condvar",
+               reason = "may be merged with Condvar in the future")]
+    pub const fn new() -> StaticCondvar {
+        StaticCondvar {
+            inner: sys::Condvar::new(),
+            mutex: AtomicUsize::new(0),
+        }
+    }
+
     /// Blocks the current thread until this condition variable receives a
     /// notification.
     ///
@@ -388,10 +395,10 @@ impl StaticCondvar {
 mod tests {
     use prelude::v1::*;
 
-    use super::{StaticCondvar, CONDVAR_INIT};
+    use super::StaticCondvar;
     use sync::mpsc::channel;
-    use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc};
-    use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use sync::{StaticMutex, Condvar, Mutex, Arc};
+    use sync::atomic::{AtomicUsize, Ordering};
     use thread;
     use time::Duration;
     use u32;
@@ -405,7 +412,7 @@ mod tests {
 
     #[test]
     fn static_smoke() {
-        static C: StaticCondvar = CONDVAR_INIT;
+        static C: StaticCondvar = StaticCondvar::new();
         C.notify_one();
         C.notify_all();
         unsafe { C.destroy(); }
@@ -413,8 +420,8 @@ mod tests {
 
     #[test]
     fn notify_one() {
-        static C: StaticCondvar = CONDVAR_INIT;
-        static M: StaticMutex = MUTEX_INIT;
+        static C: StaticCondvar = StaticCondvar::new();
+        static M: StaticMutex = StaticMutex::new();
 
         let g = M.lock().unwrap();
         let _t = thread::spawn(move|| {
@@ -464,8 +471,8 @@ mod tests {
 
     #[test]
     fn wait_timeout_ms() {
-        static C: StaticCondvar = CONDVAR_INIT;
-        static M: StaticMutex = MUTEX_INIT;
+        static C: StaticCondvar = StaticCondvar::new();
+        static M: StaticMutex = StaticMutex::new();
 
         let g = M.lock().unwrap();
         let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap();
@@ -483,9 +490,9 @@ mod tests {
 
     #[test]
     fn wait_timeout_with() {
-        static C: StaticCondvar = CONDVAR_INIT;
-        static M: StaticMutex = MUTEX_INIT;
-        static S: AtomicUsize = ATOMIC_USIZE_INIT;
+        static C: StaticCondvar = StaticCondvar::new();
+        static M: StaticMutex = StaticMutex::new();
+        static S: AtomicUsize = AtomicUsize::new(0);
 
         let g = M.lock().unwrap();
         let (g, success) = C.wait_timeout_with(g, Duration::new(0, 1000), |_| {
@@ -530,9 +537,9 @@ mod tests {
     #[test]
     #[should_panic]
     fn two_mutexes() {
-        static M1: StaticMutex = MUTEX_INIT;
-        static M2: StaticMutex = MUTEX_INIT;
-        static C: StaticCondvar = CONDVAR_INIT;
+        static M1: StaticMutex = StaticMutex::new();
+        static M2: StaticMutex = StaticMutex::new();
+        static C: StaticCondvar = StaticCondvar::new();
 
         let mut g = M1.lock().unwrap();
         let _t = thread::spawn(move|| {
index 2d281eb4e249ca2be556107d114a100b9c6523f1..28dc124f0334fca39c5cec7e1a9e6582a7a49d25 100644 (file)
@@ -14,7 +14,7 @@
 //! # Examples
 //!
 //! ```
-//! # #![feature(std_misc)]
+//! # #![feature(future)]
 //! use std::sync::Future;
 //!
 //! // a fake, for now
 //! ```
 
 #![allow(missing_docs)]
-#![unstable(feature = "std_misc",
+#![unstable(feature = "future",
             reason = "futures as-is have yet to be deeply reevaluated with recent \
                       core changes to Rust's synchronization story, and will likely \
                       become stable in the future but are unstable until that time")]
+#![deprecated(since = "1.2.0",
+              reason = "implementation does not match the quality of the \
+                        standard library and this will likely be prototyped \
+                        outside in crates.io first")]
+#![allow(deprecated)]
 
 use core::prelude::*;
 use core::mem::replace;
index 91e9714fbef48b896793f53deff438346ca804b7..ab8d4587cfd3d7ce6174120a12a04b93c293d758 100644 (file)
@@ -30,6 +30,7 @@ pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
 pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
 pub use self::semaphore::{Semaphore, SemaphoreGuard};
 
+#[allow(deprecated)]
 pub use self::future::Future;
 
 pub mod mpsc;
index 2e4155ea35128d070c7854e304a40b58a30a87ac..0e5a98591168b5d6864a092f6a3b0a55d9ce5c6a 100644 (file)
@@ -11,7 +11,7 @@
 //! Generic support for building blocking abstractions.
 
 use thread::{self, Thread};
-use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
+use sync::atomic::{AtomicBool, Ordering};
 use sync::Arc;
 use marker::{Sync, Send};
 use mem;
@@ -41,7 +41,7 @@ impl !Sync for WaitToken {}
 pub fn tokens() -> (WaitToken, SignalToken) {
     let inner = Arc::new(Inner {
         thread: thread::current(),
-        woken: ATOMIC_BOOL_INIT,
+        woken: AtomicBool::new(false),
     });
     let wait_token = WaitToken {
         inner: inner.clone(),
index 2c0da938cbf8b71c59079fa37e1c22ee6c5a02c5..d6d173e5e7e7e2ee345465a16d9e148e1e8fe166 100644 (file)
@@ -35,8 +35,6 @@
 //! method, and see the method for more information about it. Due to this
 //! caveat, this queue may not be appropriate for all use-cases.
 
-#![unstable(feature = "std_misc")]
-
 // http://www.1024cores.net/home/lock-free-algorithms
 //                         /queues/non-intrusive-mpsc-node-based-queue
 
@@ -44,7 +42,6 @@ pub use self::PopResult::*;
 
 use core::prelude::*;
 
-use alloc::boxed;
 use alloc::boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
@@ -82,7 +79,7 @@ unsafe impl<T: Send> Sync for Queue<T> { }
 
 impl<T> Node<T> {
     unsafe fn new(v: Option<T>) -> *mut Node<T> {
-        boxed::into_raw(box Node {
+        Box::into_raw(box Node {
             next: AtomicPtr::new(ptr::null_mut()),
             value: v,
         })
index 679cc550454fa77eba908a7c04b2c79b1095a801..a67138742aeeb9cbf6e7badb4cd106b57faeba27 100644 (file)
@@ -27,7 +27,7 @@
 //! # Examples
 //!
 //! ```rust
-//! # #![feature(std_misc)]
+//! # #![feature(mpsc_select)]
 //! use std::sync::mpsc::channel;
 //!
 //! let (tx1, rx1) = channel();
@@ -47,7 +47,7 @@
 //! ```
 
 #![allow(dead_code)]
-#![unstable(feature = "std_misc",
+#![unstable(feature = "mpsc_select",
             reason = "This implementation, while likely sufficient, is unsafe and \
                       likely to be error prone. At some point in the future this \
                       module will likely be replaced, and it is currently \
@@ -124,7 +124,7 @@ impl Select {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(std_misc)]
+    /// # #![feature(mpsc_select)]
     /// use std::sync::mpsc::Select;
     ///
     /// let select = Select::new();
index b72da91c0a075cffd1ed7a4421070ae980358699..3cf75de5a46ddf7e6964bb07b9da5e40b1194752 100644 (file)
 //! concurrently between two threads. This data structure is safe to use and
 //! enforces the semantics that there is one pusher and one popper.
 
-#![unstable(feature = "std_misc")]
-
 use core::prelude::*;
 
-use alloc::boxed;
 use alloc::boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
@@ -80,12 +77,10 @@ unsafe impl<T: Send> Sync for Queue<T> { }
 
 impl<T> Node<T> {
     fn new() -> *mut Node<T> {
-        unsafe {
-            boxed::into_raw(box Node {
-                value: None,
-                next: AtomicPtr::new(ptr::null_mut::<Node<T>>()),
-            })
-        }
+        Box::into_raw(box Node {
+            value: None,
+            next: AtomicPtr::new(ptr::null_mut::<Node<T>>()),
+        })
     }
 }
 
index f9ed7c863d126c1adcaff76026772abbf5fcb730..41cd11e4c6900ea88790abca9c4ba8b44d49562f 100644 (file)
@@ -85,7 +85,6 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 /// To recover from a poisoned mutex:
 ///
 /// ```
-/// # #![feature(std_misc)]
 /// use std::sync::{Arc, Mutex};
 /// use std::thread;
 ///
@@ -139,7 +138,7 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 /// # Examples
 ///
 /// ```
-/// # #![feature(std_misc)]
+/// # #![feature(static_mutex)]
 /// use std::sync::{StaticMutex, MUTEX_INIT};
 ///
 /// static LOCK: StaticMutex = MUTEX_INIT;
@@ -150,7 +149,7 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 /// }
 /// // lock is unlocked here.
 /// ```
-#[unstable(feature = "std_misc",
+#[unstable(feature = "static_mutex",
            reason = "may be merged with Mutex in the future")]
 pub struct StaticMutex {
     lock: sys::Mutex,
@@ -176,19 +175,16 @@ impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
 
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
-#[unstable(feature = "std_misc",
+#[unstable(feature = "static_mutex",
            reason = "may be merged with Mutex in the future")]
-pub const MUTEX_INIT: StaticMutex = StaticMutex {
-    lock: sys::MUTEX_INIT,
-    poison: poison::FLAG_INIT,
-};
+pub const MUTEX_INIT: StaticMutex = StaticMutex::new();
 
 impl<T> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
         Mutex {
-            inner: box MUTEX_INIT,
+            inner: box StaticMutex::new(),
             data: UnsafeCell::new(t),
         }
     }
@@ -240,7 +236,7 @@ impl<T: ?Sized> Mutex<T> {
     /// time.  You should not trust a `false` value for program correctness
     /// without additional synchronization.
     #[inline]
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn is_poisoned(&self) -> bool {
         self.inner.poison.get()
     }
@@ -271,13 +267,21 @@ impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
 
 struct Dummy(UnsafeCell<()>);
 unsafe impl Sync for Dummy {}
-static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
+static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
 
+#[unstable(feature = "static_mutex",
+           reason = "may be merged with Mutex in the future")]
 impl StaticMutex {
+    /// Creates a new mutex in an unlocked state ready for use.
+    pub const fn new() -> StaticMutex {
+        StaticMutex {
+            lock: sys::Mutex::new(),
+            poison: poison::Flag::new(),
+        }
+    }
+
     /// Acquires this lock, see `Mutex::lock`
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with Mutex in the future")]
     pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
         unsafe { self.lock.lock() }
         MutexGuard::new(self, &DUMMY.0)
@@ -285,8 +289,6 @@ impl StaticMutex {
 
     /// Attempts to grab this lock, see `Mutex::try_lock`
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with Mutex in the future")]
     pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
         if unsafe { self.lock.try_lock() } {
             Ok(try!(MutexGuard::new(self, &DUMMY.0)))
@@ -305,8 +307,6 @@ impl StaticMutex {
     /// *all* platforms. It may be the case that some platforms do not leak
     /// memory if this method is not called, but this is not guaranteed to be
     /// true on all platforms.
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with Mutex in the future")]
     pub unsafe fn destroy(&'static self) {
         self.lock.destroy()
     }
@@ -365,7 +365,7 @@ mod tests {
     use prelude::v1::*;
 
     use sync::mpsc::channel;
-    use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
+    use sync::{Arc, Mutex, StaticMutex, Condvar};
     use thread;
 
     struct Packet<T: Send>(Arc<(Mutex<T>, Condvar)>);
@@ -382,7 +382,7 @@ mod tests {
 
     #[test]
     fn smoke_static() {
-        static M: StaticMutex = MUTEX_INIT;
+        static M: StaticMutex = StaticMutex::new();
         unsafe {
             drop(M.lock().unwrap());
             drop(M.lock().unwrap());
@@ -392,7 +392,7 @@ mod tests {
 
     #[test]
     fn lots_and_lots() {
-        static M: StaticMutex = MUTEX_INIT;
+        static M: StaticMutex = StaticMutex::new();
         static mut CNT: u32 = 0;
         const J: u32 = 1000;
         const K: u32 = 3;
index 57baedaad9c8e85fef351e66874347d6414a28ad..0bda6a975a2445a95ea64ced9254297812f166b0 100644 (file)
@@ -16,8 +16,8 @@
 use prelude::v1::*;
 
 use isize;
-use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
-use sync::{StaticMutex, MUTEX_INIT};
+use sync::atomic::{AtomicIsize, Ordering};
+use sync::StaticMutex;
 
 /// A synchronization primitive which can be used to run a one-time global
 /// initialization. Useful for one-time initialization for FFI or related
@@ -44,13 +44,19 @@ pub struct Once {
 
 /// Initialization value for static `Once` values.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const ONCE_INIT: Once = Once {
-    mutex: MUTEX_INIT,
-    cnt: ATOMIC_ISIZE_INIT,
-    lock_cnt: ATOMIC_ISIZE_INIT,
-};
+pub const ONCE_INIT: Once = Once::new();
 
 impl Once {
+    /// Creates a new `Once` value.
+    #[stable(feature = "once_new", since = "1.2.0")]
+    pub const fn new() -> Once {
+        Once {
+            mutex: StaticMutex::new(),
+            cnt: AtomicIsize::new(0),
+            lock_cnt: AtomicIsize::new(0),
+        }
+    }
+
     /// Performs an initialization routine once and only once. The given closure
     /// will be executed if this is the first time `call_once` has been called,
     /// and otherwise the routine will *not* be invoked.
@@ -129,12 +135,12 @@ mod tests {
     use prelude::v1::*;
 
     use thread;
-    use super::{ONCE_INIT, Once};
+    use super::Once;
     use sync::mpsc::channel;
 
     #[test]
     fn smoke_once() {
-        static O: Once = ONCE_INIT;
+        static O: Once = Once::new();
         let mut a = 0;
         O.call_once(|| a += 1);
         assert_eq!(a, 1);
@@ -144,7 +150,7 @@ mod tests {
 
     #[test]
     fn stampede_once() {
-        static O: Once = ONCE_INIT;
+        static O: Once = Once::new();
         static mut run: bool = false;
 
         let (tx, rx) = channel();
index 36f6fbf3b72d53438d3878b035d2021a3b159e16..4ca2e282f707dc1d7429ef32e5a254c1708d5950 100644 (file)
@@ -24,6 +24,10 @@ use sys_common::rwlock as sys;
 /// of the underlying data (exclusive access) and the read portion of this lock
 /// typically allows for read-only access (shared access).
 ///
+/// The priority policy of the lock is dependent on the underlying operating
+/// system's implementation, and this type does not guarantee that any
+/// particular policy will be used.
+///
 /// The type parameter `T` represents the data that this lock protects. It is
 /// required that `T` satisfies `Send` to be shared across threads and `Sync` to
 /// allow concurrent access through readers. The RAII guards returned from the
@@ -77,7 +81,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 /// # Examples
 ///
 /// ```
-/// # #![feature(std_misc)]
+/// # #![feature(static_rwlock)]
 /// use std::sync::{StaticRwLock, RW_LOCK_INIT};
 ///
 /// static LOCK: StaticRwLock = RW_LOCK_INIT;
@@ -92,7 +96,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 /// }
 /// unsafe { LOCK.destroy() } // free all resources
 /// ```
-#[unstable(feature = "std_misc",
+#[unstable(feature = "static_rwlock",
            reason = "may be merged with RwLock in the future")]
 pub struct StaticRwLock {
     lock: sys::RWLock,
@@ -100,12 +104,9 @@ pub struct StaticRwLock {
 }
 
 /// Constant initialization for a statically-initialized rwlock.
-#[unstable(feature = "std_misc",
+#[unstable(feature = "static_rwlock",
            reason = "may be merged with RwLock in the future")]
-pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
-    lock: sys::RWLOCK_INIT,
-    poison: poison::FLAG_INIT,
-};
+pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new();
 
 /// RAII structure used to release the shared read access of a lock when
 /// dropped.
@@ -142,7 +143,7 @@ impl<T> RwLock<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> RwLock<T> {
-        RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) }
+        RwLock { inner: box StaticRwLock::new(), data: UnsafeCell::new(t) }
     }
 }
 
@@ -252,7 +253,7 @@ impl<T: ?Sized> RwLock<T> {
     /// time.  You should not trust a `false` value for program correctness
     /// without additional synchronization.
     #[inline]
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn is_poisoned(&self) -> bool {
         self.inner.poison.get()
     }
@@ -280,16 +281,24 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
 
 struct Dummy(UnsafeCell<()>);
 unsafe impl Sync for Dummy {}
-static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
+static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
 
+#[unstable(feature = "static_rwlock",
+           reason = "may be merged with RwLock in the future")]
 impl StaticRwLock {
+    /// Creates a new rwlock.
+    pub const fn new() -> StaticRwLock {
+        StaticRwLock {
+            lock: sys::RWLock::new(),
+            poison: poison::Flag::new(),
+        }
+    }
+
     /// Locks this rwlock with shared read access, blocking the current thread
     /// until it can be acquired.
     ///
     /// See `RwLock::read`.
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with RwLock in the future")]
     pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
         unsafe { self.lock.read() }
         RwLockReadGuard::new(self, &DUMMY.0)
@@ -299,8 +308,6 @@ impl StaticRwLock {
     ///
     /// See `RwLock::try_read`.
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with RwLock in the future")]
     pub fn try_read(&'static self)
                     -> TryLockResult<RwLockReadGuard<'static, ()>> {
         if unsafe { self.lock.try_read() } {
@@ -315,8 +322,6 @@ impl StaticRwLock {
     ///
     /// See `RwLock::write`.
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with RwLock in the future")]
     pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
         unsafe { self.lock.write() }
         RwLockWriteGuard::new(self, &DUMMY.0)
@@ -326,8 +331,6 @@ impl StaticRwLock {
     ///
     /// See `RwLock::try_write`.
     #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with RwLock in the future")]
     pub fn try_write(&'static self)
                      -> TryLockResult<RwLockWriteGuard<'static, ()>> {
         if unsafe { self.lock.try_write() } {
@@ -343,8 +346,6 @@ impl StaticRwLock {
     /// active users of the lock, and this also doesn't prevent any future users
     /// of this lock. This method is required to be called to not leak memory on
     /// all platforms.
-    #[unstable(feature = "std_misc",
-               reason = "may be merged with RwLock in the future")]
     pub unsafe fn destroy(&'static self) {
         self.lock.destroy()
     }
@@ -420,7 +421,7 @@ mod tests {
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
-    use sync::{Arc, RwLock, StaticRwLock, TryLockError, RW_LOCK_INIT};
+    use sync::{Arc, RwLock, StaticRwLock, TryLockError};
 
     #[test]
     fn smoke() {
@@ -433,7 +434,7 @@ mod tests {
 
     #[test]
     fn static_smoke() {
-        static R: StaticRwLock = RW_LOCK_INIT;
+        static R: StaticRwLock = StaticRwLock::new();
         drop(R.read().unwrap());
         drop(R.write().unwrap());
         drop((R.read().unwrap(), R.read().unwrap()));
@@ -443,7 +444,7 @@ mod tests {
 
     #[test]
     fn frob() {
-        static R: StaticRwLock = RW_LOCK_INIT;
+        static R: StaticRwLock = StaticRwLock::new();
         const N: usize = 10;
         const M: usize = 1000;
 
index 776b3c5064ced43f905e158b600ed4e9dc06fba1..dc9e467a8b1352524e06dac7fc3bb2589e5d55bf 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "std_misc",
+#![unstable(feature = "semaphore",
             reason = "the interaction between semaphores and the acquisition/release \
                       of resources is currently unclear")]
 
@@ -25,7 +25,7 @@ use sync::{Mutex, Condvar};
 /// # Examples
 ///
 /// ```
-/// # #![feature(std_misc)]
+/// # #![feature(semaphore)]
 /// use std::sync::Semaphore;
 ///
 /// // Create a semaphore that represents 5 resources
index 580d970af0c3da3d77a1a484da9c7497ea085e93..00932712a07a436c2526c75ced2ea6931944054c 100644 (file)
@@ -27,7 +27,7 @@ pub const HEX_WIDTH: usize = 10;
 // 2. For each element of the path, emit the length plus the element
 // 3. End the path with "E"
 //
-// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
+// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
 //
 // We're the ones printing our backtraces, so we can't rely on anything else to
 // demangle our symbols. It's *much* nicer to look at demangled symbols, so
index 9f46b0c38248fef95129fdea634311bee4552f29..33734a88cf32b18467beae65149f94a01b6fc3b9 100644 (file)
@@ -20,16 +20,12 @@ use sys::condvar as imp;
 /// this type.
 pub struct Condvar(imp::Condvar);
 
-/// Static initializer for condition variables.
-pub const CONDVAR_INIT: Condvar = Condvar(imp::CONDVAR_INIT);
-
 impl Condvar {
     /// Creates a new condition variable for use.
     ///
     /// Behavior is undefined if the condition variable is moved after it is
     /// first used with any of the functions below.
-    #[inline]
-    pub unsafe fn new() -> Condvar { Condvar(imp::Condvar::new()) }
+    pub const fn new() -> Condvar { Condvar(imp::Condvar::new()) }
 
     /// Signals one waiter on this condition variable to wake up.
     #[inline]
index 1f9dd54192ccaeae9170b4e58162b893c2551bf7..5a6dfe7fb1a1507739b6b47447490ec60d426b92 100644 (file)
@@ -20,10 +20,13 @@ pub struct Mutex(imp::Mutex);
 
 unsafe impl Sync for Mutex {}
 
-/// Constant initializer for statically allocated mutexes.
-pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);
-
 impl Mutex {
+    /// Creates a new mutex for use.
+    ///
+    /// Behavior is undefined if the mutex is moved after it is
+    /// first used with any of the functions below.
+    pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) }
+
     /// Locks the mutex blocking the current thread until it is available.
     ///
     /// Behavior is undefined if the mutex has been moved between this and any
index 7da7071670ab631c575590df8e6b6dbd95d71a6c..5890e6a78892c0ae6f931066bd58a4184b6ede46 100644 (file)
@@ -20,12 +20,13 @@ use str::from_utf8;
 use sys::c;
 use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
 use sys_common::{AsInner, FromInner, IntoInner};
+use time::Duration;
 
 ////////////////////////////////////////////////////////////////////////////////
 // sockaddr and misc bindings
 ////////////////////////////////////////////////////////////////////////////////
 
-fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
+pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
                      payload: T) -> io::Result<()> {
     unsafe {
         let payload = &payload as *const T as *const c_void;
@@ -35,16 +36,15 @@ fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
     }
 }
 
-#[allow(dead_code)]
-fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
+pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
                        val: c_int) -> io::Result<T> {
     unsafe {
         let mut slot: T = mem::zeroed();
         let mut len = mem::size_of::<T>() as socklen_t;
-        let ret = try!(cvt(c::getsockopt(*sock.as_inner(), opt, val,
-                                         &mut slot as *mut _ as *mut _,
-                                         &mut len)));
-        assert_eq!(ret as usize, mem::size_of::<T>());
+        try!(cvt(c::getsockopt(*sock.as_inner(), opt, val,
+                               &mut slot as *mut _ as *mut _,
+                               &mut len)));
+        assert_eq!(len as usize, mem::size_of::<T>());
         Ok(slot)
     }
 }
@@ -220,6 +220,22 @@ impl TcpStream {
         Ok(())
     }
 
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.inner.set_timeout(dur, libc::SO_RCVTIMEO)
+    }
+
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.inner.set_timeout(dur, libc::SO_SNDTIMEO)
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.inner.timeout(libc::SO_RCVTIMEO)
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.inner.timeout(libc::SO_SNDTIMEO)
+    }
+
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
@@ -274,16 +290,16 @@ impl fmt::Debug for TcpStream {
         let mut res = f.debug_struct("TcpStream");
 
         if let Ok(addr) = self.socket_addr() {
-            res = res.field("addr", &addr);
+            res.field("addr", &addr);
         }
 
         if let Ok(peer) = self.peer_addr() {
-            res = res.field("peer", &peer);
+            res.field("peer", &peer);
         }
 
         let name = if cfg!(windows) {"socket"} else {"fd"};
-        res = res.field(name, &self.inner.as_inner());
-        res.finish()
+        res.field(name, &self.inner.as_inner())
+            .finish()
     }
 }
 
@@ -351,12 +367,12 @@ impl fmt::Debug for TcpListener {
         let mut res = f.debug_struct("TcpListener");
 
         if let Ok(addr) = self.socket_addr() {
-            res = res.field("addr", &addr);
+            res.field("addr", &addr);
         }
 
         let name = if cfg!(windows) {"socket"} else {"fd"};
-        res = res.field(name, &self.inner.as_inner());
-        res.finish()
+        res.field(name, &self.inner.as_inner())
+            .finish()
     }
 }
 
@@ -471,6 +487,22 @@ impl UdpSocket {
     pub fn duplicate(&self) -> io::Result<UdpSocket> {
         self.inner.duplicate().map(|s| UdpSocket { inner: s })
     }
+
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.inner.set_timeout(dur, libc::SO_RCVTIMEO)
+    }
+
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        self.inner.set_timeout(dur, libc::SO_SNDTIMEO)
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.inner.timeout(libc::SO_RCVTIMEO)
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.inner.timeout(libc::SO_SNDTIMEO)
+    }
 }
 
 impl FromInner<Socket> for UdpSocket {
@@ -484,11 +516,11 @@ impl fmt::Debug for UdpSocket {
         let mut res = f.debug_struct("UdpSocket");
 
         if let Ok(addr) = self.socket_addr() {
-            res = res.field("addr", &addr);
+            res.field("addr", &addr);
         }
 
         let name = if cfg!(windows) {"socket"} else {"fd"};
-        res = res.field(name, &self.inner.as_inner());
-        res.finish()
+        res.field(name, &self.inner.as_inner())
+            .finish()
     }
 }
index 67679c11a9858b587d3e66f4539511e5161670e0..065b1d6c9acfc1b40bdd382a20e5eee214c10cfc 100644 (file)
 
 use prelude::v1::*;
 
-use marker::Reflect;
-use cell::UnsafeCell;
+use cell::Cell;
 use error::{Error};
 use fmt;
+use marker::Reflect;
 use thread;
 
-pub struct Flag { failed: UnsafeCell<bool> }
+pub struct Flag { failed: Cell<bool> }
 
 // This flag is only ever accessed with a lock previously held. Note that this
 // a totally private structure.
 unsafe impl Send for Flag {}
 unsafe impl Sync for Flag {}
 
-pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
-
 impl Flag {
+    pub const fn new() -> Flag {
+        Flag { failed: Cell::new(false) }
+    }
+
     #[inline]
     pub fn borrow(&self) -> LockResult<Guard> {
         let ret = Guard { panicking: thread::panicking() };
-        if unsafe { *self.failed.get() } {
+        if self.get() {
             Err(PoisonError::new(ret))
         } else {
             Ok(ret)
@@ -39,13 +41,13 @@ impl Flag {
     #[inline]
     pub fn done(&self, guard: &Guard) {
         if !guard.panicking && thread::panicking() {
-            unsafe { *self.failed.get() = true; }
+            self.failed.set(true);
         }
     }
 
     #[inline]
     pub fn get(&self) -> bool {
-        unsafe { *self.failed.get() }
+        self.failed.get()
     }
 }
 
@@ -118,24 +120,24 @@ impl<T: Send + Reflect> Error for PoisonError<T> {
 
 impl<T> PoisonError<T> {
     /// Creates a `PoisonError`.
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn new(guard: T) -> PoisonError<T> {
         PoisonError { guard: guard }
     }
 
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn into_inner(self) -> T { self.guard }
 
     /// Reaches into this error indicating that a lock is poisoned, returning a
     /// reference to the underlying guard to allow access regardless.
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn get_ref(&self) -> &T { &self.guard }
 
     /// Reaches into this error indicating that a lock is poisoned, returning a
     /// mutable reference to the underlying guard to allow access regardless.
-    #[unstable(feature = "std_misc")]
+    #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
 }
 
index 1a467580672b3740ce62720ea3e41799013e1a5f..8f41646417367632637c6fa9798b39968ebee271 100644 (file)
@@ -54,7 +54,7 @@ impl<T> ReentrantMutex<T> {
         unsafe {
             let mut mutex = ReentrantMutex {
                 inner: box sys::ReentrantMutex::uninitialized(),
-                poison: poison::FLAG_INIT,
+                poison: poison::Flag::new(),
                 data: t,
             };
             mutex.inner.init();
@@ -187,7 +187,7 @@ mod tests {
             assert_eq!(*lock.borrow(), 4950);
         });
         for i in 0..100 {
-            let mut lock = m.lock().unwrap();
+            let lock = m.lock().unwrap();
             *lock.borrow_mut() += i;
         }
         drop(lock);
index 725a09bcc86a99b88432adfefbc236a2369f0d66..71a4f01ec4cab9f2d3edcee78af3373f2484e24f 100644 (file)
@@ -17,10 +17,13 @@ use sys::rwlock as imp;
 /// safer types at the top level of this crate instead of this type.
 pub struct RWLock(imp::RWLock);
 
-/// Constant initializer for static RWLocks.
-pub const RWLOCK_INIT: RWLock = RWLock(imp::RWLOCK_INIT);
-
 impl RWLock {
+    /// Creates a new reader-writer lock for use.
+    ///
+    /// Behavior is undefined if the reader-writer lock is moved after it is
+    /// first used with any of the functions below.
+    pub const fn new() -> RWLock { RWLock(imp::RWLock::new()) }
+
     /// Acquires shared access to the underlying lock, blocking the current
     /// thread to do so.
     ///
index fadeebc8150017518a258cec3f653cb9924b6330..11982ebc572e5b3dc571d8a0726d7b5d5583ff8b 100644 (file)
@@ -139,7 +139,6 @@ pub unsafe fn record_os_managed_stack_bounds(stack_lo: usize, _stack_hi: usize)
 pub unsafe fn record_sp_limit(limit: usize) {
     return target_record_sp_limit(limit);
 
-    // x86-64
     #[cfg(all(target_arch = "x86_64",
               any(target_os = "macos", target_os = "ios")))]
     #[inline(always)]
@@ -164,7 +163,6 @@ pub unsafe fn record_sp_limit(limit: usize) {
         asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
     }
 
-    // x86
     #[cfg(all(target_arch = "x86",
               any(target_os = "macos", target_os = "ios")))]
     #[inline(always)]
@@ -182,8 +180,8 @@ pub unsafe fn record_sp_limit(limit: usize) {
     unsafe fn target_record_sp_limit(_: usize) {
     }
 
-    // mips, arm - Some brave soul can port these to inline asm, but it's over
-    //             my head personally
+    // mips, arm - The implementations are a bit big for inline asm!
+    //             They can be found in src/rt/arch/$target_arch/record_sp.S
     #[cfg(any(target_arch = "mips",
               target_arch = "mipsel",
               all(target_arch = "arm", not(target_os = "ios"))))]
@@ -221,7 +219,6 @@ pub unsafe fn record_sp_limit(limit: usize) {
 pub unsafe fn get_sp_limit() -> usize {
     return target_get_sp_limit();
 
-    // x86-64
     #[cfg(all(target_arch = "x86_64",
               any(target_os = "macos", target_os = "ios")))]
     #[inline(always)]
@@ -255,7 +252,6 @@ pub unsafe fn get_sp_limit() -> usize {
         return limit;
     }
 
-    // x86
     #[cfg(all(target_arch = "x86",
               any(target_os = "macos", target_os = "ios")))]
     #[inline(always)]
@@ -278,8 +274,8 @@ pub unsafe fn get_sp_limit() -> usize {
         return 1024;
     }
 
-    // mips, arm - Some brave soul can port these to inline asm, but it's over
-    //             my head personally
+    // mips, arm - The implementations are a bit big for inline asm!
+    //             They can be found in src/rt/arch/$target_arch/record_sp.S
     #[cfg(any(target_arch = "mips",
               target_arch = "mipsel",
               all(target_arch = "arm", not(target_os = "ios"))))]
index 618a389110ac1627b3853da2848d0eae670b9e32..3b2cb00d8c47dcbb6130763eb7635a0a0ee7c328 100644 (file)
@@ -86,19 +86,13 @@ use sys::thread_local as imp;
 /// }
 /// ```
 pub struct StaticKey {
-    /// Inner static TLS key (internals), created with by `INIT_INNER` in this
-    /// module.
-    pub inner: StaticKeyInner,
+    /// Inner static TLS key (internals).
+    key: AtomicUsize,
     /// Destructor for the TLS value.
     ///
     /// See `Key::new` for information about when the destructor runs and how
     /// it runs.
-    pub dtor: Option<unsafe extern fn(*mut u8)>,
-}
-
-/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
-pub struct StaticKeyInner {
-    key: AtomicUsize,
+    dtor: Option<unsafe extern fn(*mut u8)>,
 }
 
 /// A type for a safely managed OS-based TLS slot.
@@ -108,7 +102,7 @@ pub struct StaticKeyInner {
 /// type is entirely safe to use.
 ///
 /// Implementations will likely, however, contain unsafe code as this type only
-/// operates on `*mut u8`, an unsafe pointer.
+/// operates on `*mut u8`, a raw pointer.
 ///
 /// # Examples
 ///
@@ -129,19 +123,16 @@ pub struct Key {
 /// Constant initialization value for static TLS keys.
 ///
 /// This value specifies no destructor by default.
-pub const INIT: StaticKey = StaticKey {
-    inner: INIT_INNER,
-    dtor: None,
-};
-
-/// Constant initialization value for the inner part of static TLS keys.
-///
-/// This value allows specific configuration of the destructor for a TLS key.
-pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
-    key: atomic::ATOMIC_USIZE_INIT,
-};
+pub const INIT: StaticKey = StaticKey::new(None);
 
 impl StaticKey {
+    pub const fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> StaticKey {
+        StaticKey {
+            key: atomic::AtomicUsize::new(0),
+            dtor: dtor
+        }
+    }
+
     /// Gets the value associated with this TLS key
     ///
     /// This will lazily allocate a TLS key from the OS if one has not already
@@ -164,7 +155,7 @@ impl StaticKey {
     /// Note that this does *not* run the user-provided destructor if one was
     /// specified at definition time. Doing so must be done manually.
     pub unsafe fn destroy(&self) {
-        match self.inner.key.swap(0, Ordering::SeqCst) {
+        match self.key.swap(0, Ordering::SeqCst) {
             0 => {}
             n => { imp::destroy(n as imp::Key) }
         }
@@ -172,7 +163,7 @@ impl StaticKey {
 
     #[inline]
     unsafe fn key(&self) -> imp::Key {
-        match self.inner.key.load(Ordering::Relaxed) {
+        match self.key.load(Ordering::Relaxed) {
             0 => self.lazy_init() as imp::Key,
             n => n as imp::Key
         }
@@ -197,7 +188,7 @@ impl StaticKey {
             key2
         };
         assert!(key != 0);
-        match self.inner.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
+        match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
             // The CAS succeeded, so we've created the actual key
             0 => key as usize,
             // If someone beat us to the punch, use their key instead
@@ -245,7 +236,7 @@ impl Drop for Key {
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
-    use super::{Key, StaticKey, INIT_INNER};
+    use super::{Key, StaticKey};
 
     fn assert_sync<T: Sync>() {}
     fn assert_send<T: Send>() {}
@@ -267,8 +258,8 @@ mod tests {
 
     #[test]
     fn statik() {
-        static K1: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
-        static K2: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
+        static K1: StaticKey = StaticKey::new(None);
+        static K2: StaticKey = StaticKey::new(None);
 
         unsafe {
             assert!(K1.get().is_null());
index cb9239ed7ba57032fb320a6614d68adac27ee1b3..8ea673d2162d13322777c8556e66405b698cf8ed 100644 (file)
@@ -28,7 +28,7 @@
 use core::prelude::*;
 
 use core::char::{encode_utf8_raw, encode_utf16_raw};
-use core::str::{char_range_at_raw, next_code_point};
+use core::str::next_code_point;
 
 use ascii::*;
 use borrow::Cow;
@@ -480,31 +480,6 @@ impl Wtf8 {
         }
     }
 
-    /// Returns the code point at `position`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `position` is not at a code point boundary,
-    /// or is beyond the end of the string.
-    #[inline]
-    pub fn code_point_at(&self, position: usize) -> CodePoint {
-        let (code_point, _) = self.code_point_range_at(position);
-        code_point
-    }
-
-    /// Returns the code point at `position`
-    /// and the position of the next code point.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `position` is not at a code point boundary,
-    /// or is beyond the end of the string.
-    #[inline]
-    pub fn code_point_range_at(&self, position: usize) -> (CodePoint, usize) {
-        let (c, n) = char_range_at_raw(&self.bytes, position);
-        (CodePoint { value: c }, n)
-    }
-
     /// Returns an iterator for the string’s code points.
     #[inline]
     pub fn code_points(&self) -> Wtf8CodePoints {
@@ -906,8 +881,8 @@ mod tests {
 
     #[test]
     fn wtf8buf_from_string() {
-        assert_eq!(Wtf8Buf::from_string(String::from_str("")).bytes, b"");
-        assert_eq!(Wtf8Buf::from_string(String::from_str("aé 💩")).bytes,
+        assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
+        assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes,
                    b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     }
 
@@ -1049,7 +1024,7 @@ mod tests {
     #[test]
     fn wtf8buf_into_string() {
         let mut string = Wtf8Buf::from_str("aé 💩");
-        assert_eq!(string.clone().into_string(), Ok(String::from_str("aé 💩")));
+        assert_eq!(string.clone().into_string(), Ok(String::from("aé 💩")));
         string.push(CodePoint::from_u32(0xD800).unwrap());
         assert_eq!(string.clone().into_string(), Err(string));
     }
@@ -1057,9 +1032,9 @@ mod tests {
     #[test]
     fn wtf8buf_into_string_lossy() {
         let mut string = Wtf8Buf::from_str("aé 💩");
-        assert_eq!(string.clone().into_string_lossy(), String::from_str("aé 💩"));
+        assert_eq!(string.clone().into_string_lossy(), String::from("aé 💩"));
         string.push(CodePoint::from_u32(0xD800).unwrap());
-        assert_eq!(string.clone().into_string_lossy(), String::from_str("aé 💩�"));
+        assert_eq!(string.clone().into_string_lossy(), String::from("aé 💩�"));
     }
 
     #[test]
@@ -1173,30 +1148,6 @@ mod tests {
         assert_eq!(slice.ascii_byte_at(4), b'\xFF');
     }
 
-    #[test]
-    fn wtf8_code_point_at() {
-        let mut string = Wtf8Buf::from_str("aé ");
-        string.push(CodePoint::from_u32(0xD83D).unwrap());
-        string.push_char('💩');
-        assert_eq!(string.code_point_at(0), CodePoint::from_char('a'));
-        assert_eq!(string.code_point_at(1), CodePoint::from_char('é'));
-        assert_eq!(string.code_point_at(3), CodePoint::from_char(' '));
-        assert_eq!(string.code_point_at(4), CodePoint::from_u32(0xD83D).unwrap());
-        assert_eq!(string.code_point_at(7), CodePoint::from_char('💩'));
-    }
-
-    #[test]
-    fn wtf8_code_point_range_at() {
-        let mut string = Wtf8Buf::from_str("aé ");
-        string.push(CodePoint::from_u32(0xD83D).unwrap());
-        string.push_char('💩');
-        assert_eq!(string.code_point_range_at(0), (CodePoint::from_char('a'), 1));
-        assert_eq!(string.code_point_range_at(1), (CodePoint::from_char('é'), 3));
-        assert_eq!(string.code_point_range_at(3), (CodePoint::from_char(' '), 4));
-        assert_eq!(string.code_point_range_at(4), (CodePoint::from_u32(0xD83D).unwrap(), 7));
-        assert_eq!(string.code_point_range_at(7), (CodePoint::from_char('💩'), 11));
-    }
-
     #[test]
     fn wtf8_code_points() {
         fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() }
@@ -1226,7 +1177,7 @@ mod tests {
         assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩"));
         let mut string = Wtf8Buf::from_str("aé 💩");
         string.push(CodePoint::from_u32(0xD800).unwrap());
-        let expected: Cow<str> = Cow::Owned(String::from_str("aé 💩�"));
+        let expected: Cow<str> = Cow::Owned(String::from("aé 💩�"));
         assert_eq!(string.to_string_lossy(), expected);
     }
 
index 135ae1bf9163bc155bd312de295eed1150ac826f..b23a3eee1a1738e03e69f9706901a3d5e82b21fa 100644 (file)
@@ -91,7 +91,7 @@ use io;
 use libc;
 use mem;
 use str;
-use sync::{StaticMutex, MUTEX_INIT};
+use sync::StaticMutex;
 
 use sys_common::backtrace::*;
 
@@ -117,7 +117,7 @@ pub fn write(w: &mut Write) -> io::Result<()> {
     // while it doesn't requires lock for work as everything is
     // local, it still displays much nicer backtraces when a
     // couple of threads panic simultaneously
-    static LOCK: StaticMutex = MUTEX_INIT;
+    static LOCK: StaticMutex = StaticMutex::new();
     let _g = LOCK.lock();
 
     try!(writeln!(w, "stack backtrace:"));
@@ -148,7 +148,7 @@ pub fn write(w: &mut Write) -> io::Result<()> {
     // is semi-reasonable in terms of printing anyway, and we know that all
     // I/O done here is blocking I/O, not green I/O, so we don't have to
     // worry about this being a native vs green mutex.
-    static LOCK: StaticMutex = MUTEX_INIT;
+    static LOCK: StaticMutex = StaticMutex::new();
     let _g = LOCK.lock();
 
     try!(writeln!(w, "stack backtrace:"));
index 1e68eac5a67354b880b5a7e678a7ae8e67fda3ea..99a6731c57d95317d597a8ddf4ac2c02f8ff03d8 100644 (file)
@@ -8,15 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! C definitions used by libnative that don't belong in liblibc
+//! C definitions used by std::sys that don't belong in liblibc
+
+// These are definitions sufficient for the users in this directory.
+// This is not a general-purpose binding to this functionality, and in
+// some cases (notably the definition of siginfo_t), we intentionally
+// have incomplete bindings so that we don't need to fight with unions.
+//
+// Note that these types need to match the definitions from the platform
+// libc (currently glibc on Linux), not the kernel definitions / the
+// syscall interface.  This has a few weirdnesses, like glibc's sigset_t
+// being 1024 bits on all platforms. If you're adding a new GNU/Linux
+// port, check glibc's sysdeps/unix/sysv/linux, not the kernel headers.
 
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
-pub use self::select::fd_set;
-pub use self::signal::{sigaction, siginfo, sigset_t};
-pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
-pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};
+pub use self::signal_os::{sigaction, siginfo, sigset_t, sigaltstack};
+pub use self::signal_os::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSTKSZ, SIG_SETMASK};
 
 use libc;
 
@@ -26,45 +35,21 @@ use libc;
           target_os = "dragonfly",
           target_os = "bitrig",
           target_os = "openbsd"))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x8004667e;
-    pub const FIOCLEX: libc::c_ulong = 0x20006601;
-    pub const FIONCLEX: libc::c_ulong = 0x20006602;
-}
+pub const FIOCLEX: libc::c_ulong = 0x20006601;
+
 #[cfg(any(all(target_os = "linux",
               any(target_arch = "x86",
                   target_arch = "x86_64",
                   target_arch = "arm",
                   target_arch = "aarch64")),
           target_os = "android"))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x5421;
-    pub const FIOCLEX: libc::c_ulong = 0x5451;
-    pub const FIONCLEX: libc::c_ulong = 0x5450;
-}
+pub const FIOCLEX: libc::c_ulong = 0x5451;
+
 #[cfg(all(target_os = "linux",
           any(target_arch = "mips",
               target_arch = "mipsel",
               target_arch = "powerpc")))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x667e;
-    pub const FIOCLEX: libc::c_ulong = 0x6601;
-    pub const FIONCLEX: libc::c_ulong = 0x6600;
-}
-pub use self::consts::*;
-
-#[cfg(any(target_os = "macos",
-          target_os = "ios",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd"))]
-pub const MSG_DONTWAIT: libc::c_int = 0x80;
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub const MSG_DONTWAIT: libc::c_int = 0x40;
+pub const FIOCLEX: libc::c_ulong = 0x6601;
 
 pub const WNOHANG: libc::c_int = 1;
 
@@ -122,14 +107,14 @@ pub struct passwd {
     pub pw_shell: *mut libc::c_char,
 }
 
+// This is really a function pointer (or a union of multiple function
+// pointers), except for constants like SIG_DFL.
+pub type sighandler_t = *mut libc::c_void;
+
+pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
+pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
+
 extern {
-    pub fn gettimeofday(timeval: *mut libc::timeval,
-                        tzp: *mut libc::c_void) -> libc::c_int;
-    pub fn select(nfds: libc::c_int,
-                  readfds: *mut fd_set,
-                  writefds: *mut fd_set,
-                  errorfds: *mut fd_set,
-                  timeout: *mut libc::timeval) -> libc::c_int;
     pub fn getsockopt(sockfd: libc::c_int,
                       level: libc::c_int,
                       optname: libc::c_int,
@@ -141,14 +126,21 @@ extern {
     pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                    options: libc::c_int) -> libc::pid_t;
 
+    pub fn raise(signum: libc::c_int) -> libc::c_int;
+
     pub fn sigaction(signum: libc::c_int,
                      act: *const sigaction,
                      oldact: *mut sigaction) -> libc::c_int;
 
-    pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
-    pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
+    pub fn sigaltstack(ss: *const sigaltstack,
+                       oss: *mut sigaltstack) -> libc::c_int;
+
+    #[cfg(not(target_os = "android"))]
     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"))]
     pub fn getpwuid_r(uid: libc::uid_t,
                       pwd: *mut passwd,
@@ -165,161 +157,188 @@ extern {
                     -> *mut libc::c_char;
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-mod select {
-    pub const FD_SETSIZE: usize = 1024;
-
-    #[repr(C)]
-    pub struct fd_set {
-        fds_bits: [i32; (FD_SETSIZE / 32)]
-    }
-
-    pub fn fd_set(set: &mut fd_set, fd: i32) {
-        set.fds_bits[(fd / 32) as usize] |= 1 << ((fd % 32) as usize);
-    }
-}
-
-#[cfg(any(target_os = "android",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd",
-          target_os = "linux"))]
-mod select {
-    use usize;
-    use libc;
-
-    pub const FD_SETSIZE: usize = 1024;
-
-    #[repr(C)]
-    pub struct fd_set {
-        // FIXME: shouldn't this be a c_ulong?
-        fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS)]
-    }
-
-    pub fn fd_set(set: &mut fd_set, fd: i32) {
-        let fd = fd as usize;
-        set.fds_bits[fd / usize::BITS] |= 1 << (fd % usize::BITS);
-    }
+// Ugh. This is only available as an inline until Android API 21.
+#[cfg(target_os = "android")]
+pub unsafe fn sigemptyset(set: *mut sigset_t) -> libc::c_int {
+    use intrinsics;
+    intrinsics::write_bytes(set, 0, 1);
+    return 0;
 }
 
-#[cfg(any(all(target_os = "linux",
-              any(target_arch = "x86",
-                  target_arch = "x86_64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")),
+#[cfg(any(target_os = "linux",
           target_os = "android"))]
-mod signal {
+mod signal_os {
+    pub use self::arch::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_SETMASK,
+                         sigaction, sigaltstack};
     use libc;
 
-    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
-    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
-    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
-    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
-    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
-    pub const SA_RESTART: libc::c_ulong = 0x10000000;
-    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
-    pub const SIGCHLD: libc::c_int = 17;
-
-    // This definition is not as accurate as it could be, {pid, uid, status} is
-    // actually a giant union. Currently we're only interested in these fields,
-    // however.
+    #[cfg(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    pub const SIGSTKSZ: libc::size_t = 8192;
+
+    // This is smaller on musl and Android, but no harm in being generous.
+    #[cfg(any(target_arch = "aarch64",
+              target_arch = "powerpc"))]
+    pub const SIGSTKSZ: libc::size_t = 16384;
+
+    // This definition is intentionally a subset of the C structure: the
+    // fields after si_code are actually a giant union. We're only
+    // interested in si_addr for this module, though.
     #[repr(C)]
     pub struct siginfo {
-        si_signo: libc::c_int,
-        si_errno: libc::c_int,
-        si_code: libc::c_int,
-        pub pid: libc::pid_t,
-        pub uid: libc::uid_t,
-        pub status: libc::c_int,
+        _signo: libc::c_int,
+        _errno: libc::c_int,
+        _code: libc::c_int,
+        // This structure will need extra padding here for MIPS64.
+        pub si_addr: *mut libc::c_void
     }
 
+    #[cfg(all(target_os = "linux", target_pointer_width = "32"))]
     #[repr(C)]
-    pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_mask: sigset_t,
-        pub sa_flags: libc::c_ulong,
-        sa_restorer: *mut libc::c_void,
-    }
-
-    unsafe impl ::marker::Send for sigaction { }
-    unsafe impl ::marker::Sync for sigaction { }
-
-    #[repr(C)]
-    #[cfg(target_pointer_width = "32")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 32],
     }
 
+    #[cfg(all(target_os = "linux", target_pointer_width = "64"))]
     #[repr(C)]
-    #[cfg(target_pointer_width = "64")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 16],
     }
-}
 
-#[cfg(all(target_os = "linux",
-          any(target_arch = "mips",
-              target_arch = "mipsel",
-              target_arch = "powerpc")))]
-mod signal {
-    use libc;
-
-    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
-    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
-    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
-    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
-    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
-    pub const SA_RESTART: libc::c_ulong = 0x10000000;
-    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
-    pub const SIGCHLD: libc::c_int = 18;
-
-    // This definition is not as accurate as it could be, {pid, uid, status} is
-    // actually a giant union. Currently we're only interested in these fields,
-    // however.
-    #[repr(C)]
-    pub struct siginfo {
-        si_signo: libc::c_int,
-        si_code: libc::c_int,
-        si_errno: libc::c_int,
-        pub pid: libc::pid_t,
-        pub uid: libc::uid_t,
-        pub status: libc::c_int,
+    // Android for MIPS has a 128-bit sigset_t, but we don't currently
+    // support it. Android for AArch64 technically has a structure of a
+    // single ulong.
+    #[cfg(target_os = "android")]
+    pub type sigset_t = libc::c_ulong;
+
+    #[cfg(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "powerpc",
+              target_arch = "arm",
+              target_arch = "aarch64"))]
+    mod arch {
+        use libc;
+        use super::super::sighandler_t;
+        use super::sigset_t;
+
+        pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+        pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
+
+        pub const SIGBUS: libc::c_int = 7;
+
+        pub const SIG_SETMASK: libc::c_int = 2;
+
+        #[cfg(target_os = "linux")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[cfg(all(target_os = "android", target_pointer_width = "32"))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+            pub sa_mask: sigset_t,
+        }
+
+        #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_flags: libc::c_int,
+            pub ss_size: libc::size_t
+        }
     }
 
-    #[repr(C)]
-    pub struct sigaction {
-        pub sa_flags: libc::c_uint,
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_mask: sigset_t,
-        sa_restorer: *mut libc::c_void,
-        sa_resv: [libc::c_int; 1],
-    }
-
-    unsafe impl ::marker::Send for sigaction { }
-    unsafe impl ::marker::Sync for sigaction { }
-
-    #[repr(C)]
-    pub struct sigset_t {
-        __val: [libc::c_ulong; 32],
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel"))]
+    mod arch {
+        use libc;
+        use super::super::sighandler_t;
+        use super::sigset_t;
+
+        pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+        pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
+
+        pub const SIGBUS: libc::c_int = 10;
+
+        pub const SIG_SETMASK: libc::c_int = 3;
+
+        #[cfg(all(target_os = "linux", not(target_env = "musl")))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            _restorer: *mut libc::c_void,
+            _resv: [libc::c_int; 1],
+        }
+
+        #[cfg(target_env = "musl")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[cfg(target_os = "android")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_size: libc::size_t,
+            pub ss_flags: libc::c_int,
+        }
     }
 }
 
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
-mod signal {
+          target_os = "dragonfly",
+          target_os = "bitrig",
+          target_os = "openbsd"))]
+mod signal_os {
     use libc;
+    use super::sighandler_t;
 
     pub const SA_ONSTACK: libc::c_int = 0x0001;
-    pub const SA_RESTART: libc::c_int = 0x0002;
-    pub const SA_RESETHAND: libc::c_int = 0x0004;
-    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
-    pub const SA_NODEFER: libc::c_int = 0x0010;
-    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
     pub const SA_SIGINFO: libc::c_int = 0x0040;
-    pub const SIGCHLD: libc::c_int = 20;
+
+    pub const SIGBUS: libc::c_int = 10;
+
+    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    pub const SIGSTKSZ: libc::size_t = 131072;
+    // FreeBSD's is actually arch-dependent, but never more than 40960.
+    // No harm in being generous.
+    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+    pub const SIGSTKSZ: libc::size_t = 40960;
+
+    pub const SIG_SETMASK: libc::c_int = 3;
 
     #[cfg(any(target_os = "macos",
               target_os = "ios"))]
@@ -329,61 +348,53 @@ mod signal {
     pub struct sigset_t {
         bits: [u32; 4],
     }
+    #[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
     // them.
+    #[cfg(any(target_os = "macos", target_os = "ios",
+              target_os = "freebsd", target_os = "dragonfly"))]
+    #[repr(C)]
+    pub struct siginfo {
+        pub _signo: libc::c_int,
+        pub _errno: libc::c_int,
+        pub _code: libc::c_int,
+        pub _pid: libc::pid_t,
+        pub _uid: libc::uid_t,
+        pub _status: libc::c_int,
+        pub si_addr: *mut libc::c_void
+    }
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     #[repr(C)]
     pub struct siginfo {
         pub si_signo: libc::c_int,
-        pub si_errno: libc::c_int,
         pub si_code: libc::c_int,
-        pub pid: libc::pid_t,
-        pub uid: libc::uid_t,
-        pub status: libc::c_int,
+        pub si_errno: libc::c_int,
+        pub si_addr: *mut libc::c_void
     }
 
+    #[cfg(any(target_os = "macos", target_os = "ios",
+              target_os = "bitrig", target_os = "openbsd"))]
     #[repr(C)]
     pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_flags: libc::c_int,
+        pub sa_sigaction: sighandler_t,
         pub sa_mask: sigset_t,
+        pub sa_flags: libc::c_int,
     }
-}
-
-#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-mod signal {
-    use libc;
-
-    pub const SA_ONSTACK: libc::c_int = 0x0001;
-    pub const SA_RESTART: libc::c_int = 0x0002;
-    pub const SA_RESETHAND: libc::c_int = 0x0004;
-    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
-    pub const SA_NODEFER: libc::c_int = 0x0010;
-    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
-    pub const SA_SIGINFO: libc::c_int = 0x0040;
-    pub const SIGCHLD: libc::c_int = 20;
-
-    pub type sigset_t = libc::c_uint;
 
-    // This structure has more fields, but we're not all that interested in
-    // them.
+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     #[repr(C)]
-    pub struct siginfo {
-        pub si_signo: libc::c_int,
-        pub si_code: libc::c_int,
-        pub si_errno: libc::c_int,
-        // FIXME: Bitrig has a crazy union here in the siginfo, I think this
-        // layout will still work tho.  The status might be off by the size of
-        // a clock_t by my reading, but we can fix this later.
-        pub pid: libc::pid_t,
-        pub uid: libc::uid_t,
-        pub status: libc::c_int,
+    pub struct sigaction {
+        pub sa_sigaction: sighandler_t,
+        pub sa_flags: libc::c_int,
+        pub sa_mask: sigset_t,
     }
 
     #[repr(C)]
-    pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_mask: sigset_t,
-        pub sa_flags: libc::c_int,
+    pub struct sigaltstack {
+        pub ss_sp: *mut libc::c_void,
+        pub ss_size: libc::size_t,
+        pub ss_flags: libc::c_int,
     }
 }
index 29a13cc6be731549a86f4c29e8ee553981f1b806..beecb445e8d687fd6ab6aefd5804f3ec0cf68a78 100644 (file)
@@ -23,13 +23,8 @@ pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
-pub const CONDVAR_INIT: Condvar = Condvar {
-    inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
-};
-
 impl Condvar {
-    #[inline]
-    pub unsafe fn new() -> Condvar {
+    pub const fn new() -> Condvar {
         // Might be moved and address is changing it is better to avoid
         // initialization of potentially opaque OS data before it landed
         Condvar { inner: UnsafeCell::new(ffi::PTHREAD_COND_INITIALIZER) }
@@ -65,21 +60,22 @@ impl Condvar {
         let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
         debug_assert_eq!(r, 0);
 
+        let nsec = dur.extra_nanos() as libc::c_long +
+                   (sys_now.tv_usec * 1000) as libc::c_long;
+        let extra = (nsec / 1_000_000_000) as libc::time_t;
+        let nsec = nsec % 1_000_000_000;
         let seconds = dur.secs() as libc::time_t;
-        let timeout = match sys_now.tv_sec.checked_add(seconds) {
-            Some(sec) => {
-                libc::timespec {
-                    tv_sec: sec,
-                    tv_nsec: dur.extra_nanos() as libc::c_long,
-                }
-            }
-            None => {
-                libc::timespec {
-                    tv_sec: <libc::time_t>::max_value(),
-                    tv_nsec: 1_000_000_000 - 1,
-                }
+
+        let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
+            s.checked_add(seconds)
+        }).map(|s| {
+            libc::timespec { tv_sec: s, tv_nsec: nsec }
+        }).unwrap_or_else(|| {
+            libc::timespec {
+                tv_sec: <libc::time_t>::max_value(),
+                tv_nsec: 1_000_000_000 - 1,
             }
-        };
+        });
 
         // And wait!
         let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
index f4c3001e176c8b310370eeaad04f6e1ad0202ab9..97703b8305683e46031f48d9097b7e6533261e80 100644 (file)
@@ -214,7 +214,7 @@ impl DirEntryExt for fs::DirEntry {
 /// # Ok(())
 /// # }
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 {
     sys::fs::symlink(src.as_ref(), dst.as_ref())
index 45d0d62a01575b100683ca54d5a555b0bc90b51c..cfe7a1f2dda0d491d5509099b875db1d71069f38 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use os::unix::raw::{uid_t, gid_t};
+use os::unix::io::{FromRawFd, RawFd, AsRawFd};
 use prelude::v1::*;
 use process;
 use sys;
-use sys_common::{AsInnerMut, AsInner};
+use sys_common::{AsInnerMut, AsInner, FromInner};
 
 /// Unix-specific extensions to the `std::process::Command` builder
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -63,3 +64,31 @@ impl ExitStatusExt for process::ExitStatus {
         }
     }
 }
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl FromRawFd for process::Stdio {
+    unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
+        process::Stdio::from_inner(sys::fd::FileDesc::new(fd))
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStdin {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStdout {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStderr {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
index 8ec23429dba65cea493415fab4ba917c9acfd152..128284834ab01362944242581aa25349352eeb96 100644 (file)
@@ -274,8 +274,6 @@ impl File {
         Ok(File(fd))
     }
 
-    pub fn into_fd(self) -> FileDesc { self.0 }
-
     pub fn file_attr(&self) -> io::Result<FileAttr> {
         let mut stat: raw::stat = unsafe { mem::zeroed() };
         try!(cvt(unsafe {
@@ -399,12 +397,13 @@ impl fmt::Debug for File {
         }
 
         let fd = self.0.raw();
-        let mut b = f.debug_struct("File").field("fd", &fd);
+        let mut b = f.debug_struct("File");
+        b.field("fd", &fd);
         if let Some(path) = get_path(fd) {
-            b = b.field("path", &path);
+            b.field("path", &path);
         }
         if let Some((read, write)) = get_mode(fd) {
-            b = b.field("read", &read).field("write", &write);
+            b.field("read", &read).field("write", &write);
         }
         b.finish()
     }
index 70d14f63dbcc62f25b60d1c7d965c38acbc36d13..6eed403dfc08071cdd70ed404154e6a873b372e6 100644 (file)
@@ -21,20 +21,15 @@ pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
     m.inner.get()
 }
 
-pub const MUTEX_INIT: Mutex = Mutex {
-    inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
-};
-
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 #[allow(dead_code)] // sys isn't exported yet
 impl Mutex {
-    #[inline]
-    pub unsafe fn new() -> Mutex {
+    pub const fn new() -> Mutex {
         // Might be moved and address is changing it is better to avoid
         // initialization of potentially opaque OS data before it landed
-        MUTEX_INIT
+        Mutex { inner: UnsafeCell::new(ffi::PTHREAD_MUTEX_INITIALIZER) }
     }
     #[inline]
     pub unsafe fn lock(&self) {
index 2e1cbb2a1e127094269b6dee8d70fe60eab33685..1f40c18be2f107b3d106701e9b3b40e9dea8944c 100644 (file)
@@ -18,6 +18,8 @@ use sys::c;
 use net::SocketAddr;
 use sys::fd::FileDesc;
 use sys_common::{AsInner, FromInner};
+use sys_common::net::{getsockopt, setsockopt};
+use time::Duration;
 
 pub use sys::{cvt, cvt_r};
 
@@ -73,6 +75,49 @@ impl Socket {
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
     }
+
+    pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
+        let timeout = match dur {
+            Some(dur) => {
+                if dur.secs() == 0 && dur.extra_nanos() == 0 {
+                    return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                              "cannot set a 0 duration timeout"));
+                }
+
+                let secs = if dur.secs() > libc::time_t::max_value() as u64 {
+                    libc::time_t::max_value()
+                } else {
+                    dur.secs() as libc::time_t
+                };
+                let mut timeout = libc::timeval {
+                    tv_sec: secs,
+                    tv_usec: (dur.extra_nanos() / 1000) as libc::suseconds_t,
+                };
+                if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+                    timeout.tv_usec = 1;
+                }
+                timeout
+            }
+            None => {
+                libc::timeval {
+                    tv_sec: 0,
+                    tv_usec: 0,
+                }
+            }
+        };
+        setsockopt(self, libc::SOL_SOCKET, kind, timeout)
+    }
+
+    pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
+        let raw: libc::timeval = try!(getsockopt(self, libc::SOL_SOCKET, kind));
+        if raw.tv_sec == 0 && raw.tv_usec == 0 {
+            Ok(None)
+        } else {
+            let sec = raw.tv_sec as u64;
+            let nsec = (raw.tv_usec as u32) * 1000;
+            Ok(Some(Duration::new(sec, nsec)))
+        }
+    }
 }
 
 impl AsInner<c_int> for Socket {
index 5919502abde0d88eef88aa4e758d5c08f4f5187c..5178d7b8fb1a0ac962ddb058a68fb0b31ff65a20 100644 (file)
@@ -216,8 +216,8 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 pub fn current_exe() -> io::Result<PathBuf> {
-    use sync::{StaticMutex, MUTEX_INIT};
-    static LOCK: StaticMutex = MUTEX_INIT;
+    use sync::StaticMutex;
+    static LOCK: StaticMutex = StaticMutex::new();
 
     extern {
         fn rust_current_exe() -> *const c_char;
index e9d8c69fefb52035cbdb2a341211dcbf76ccab48..946857c05bc4a252d7ac83cdf7e5b9990c2ba0d9 100644 (file)
@@ -44,7 +44,6 @@ impl AnonPipe {
         self.0.write(buf)
     }
 
-    pub fn into_fd(self) -> FileDesc {
-        self.0
-    }
+    pub fn raw(&self) -> libc::c_int { self.0.raw() }
+    pub fn fd(&self) -> &FileDesc { &self.0 }
 }
index 290310f4ad90181738f44866979318ad32ee3bdb..695d0ddfaaf61f455cbb4faa23d3b276d91418c6 100644 (file)
@@ -17,10 +17,12 @@ use ffi::{OsString, OsStr, CString, CStr};
 use fmt;
 use io::{self, Error, ErrorKind};
 use libc::{self, pid_t, c_void, c_int, gid_t, uid_t};
+use mem;
 use ptr;
+use sys::fd::FileDesc;
+use sys::fs::{File, OpenOptions};
 use sys::pipe::AnonPipe;
 use sys::{self, c, cvt, cvt_r};
-use sys::fs::{File, OpenOptions};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -121,10 +123,12 @@ pub struct Process {
 
 pub enum Stdio {
     Inherit,
-    Piped(AnonPipe),
     None,
+    Raw(c_int),
 }
 
+pub type RawStdio = FileDesc;
+
 const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
 
 impl Process {
@@ -251,9 +255,9 @@ impl Process {
         }
 
         let setup = |src: Stdio, dst: c_int| {
-            let fd = match src {
-                Stdio::Inherit => return true,
-                Stdio::Piped(pipe) => pipe.into_fd(),
+            match src {
+                Stdio::Inherit => true,
+                Stdio::Raw(fd) => cvt_r(|| libc::dup2(fd, dst)).is_ok(),
 
                 // If a stdio file descriptor is set to be ignored, we open up
                 // /dev/null into that file descriptor. Otherwise, the first
@@ -267,13 +271,12 @@ impl Process {
                     let devnull = CStr::from_ptr(b"/dev/null\0".as_ptr()
                                                     as *const _);
                     if let Ok(f) = File::open_c(devnull, &opts) {
-                        f.into_fd()
+                        cvt_r(|| libc::dup2(f.fd().raw(), dst)).is_ok()
                     } else {
-                        return false
+                        false
                     }
                 }
-            };
-            cvt_r(|| libc::dup2(fd.raw(), dst)).is_ok()
+            }
         };
 
         if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
@@ -311,10 +314,31 @@ impl Process {
         if !envp.is_null() {
             *sys::os::environ() = envp as *const _;
         }
-        let _ = libc::execvp(*argv, argv as *mut _);
+
+        // Reset signal handling so the child process starts in a
+        // standardized state. libstd ignores SIGPIPE, and signal-handling
+        // libraries often set a mask. Child processes inherit ignored
+        // signals and the signal mask from their parent, but most
+        // UNIX programs do not reset these things on their own, so we
+        // need to clean things up now to avoid confusing the program
+        // we're about to run.
+        let mut set: c::sigset_t = mem::uninitialized();
+        if c::sigemptyset(&mut set) != 0 ||
+           c::pthread_sigmask(c::SIG_SETMASK, &set, ptr::null_mut()) != 0 ||
+           libc::funcs::posix01::signal::signal(
+               libc::SIGPIPE, mem::transmute(c::SIG_DFL)
+           ) == mem::transmute(c::SIG_ERR) {
+            fail(&mut output);
+        }
+
+        let _ = libc::execvp(*argv, argv);
         fail(&mut output)
     }
 
+    pub fn id(&self) -> u32 {
+        self.pid as u32
+    }
+
     pub fn wait(&self) -> io::Result<ExitStatus> {
         let mut status = 0 as c_int;
         try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) }));
@@ -412,3 +436,69 @@ fn translate_status(status: c_int) -> ExitStatus {
         ExitStatus::Signal(imp::WTERMSIG(status))
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::v1::*;
+
+    use ffi::OsStr;
+    use mem;
+    use ptr;
+    use libc;
+    use slice;
+    use sys::{self, c, cvt, pipe};
+
+    #[cfg(not(target_os = "android"))]
+    extern {
+        fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int;
+    }
+
+    #[cfg(target_os = "android")]
+    unsafe fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int {
+        let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<c::sigset_t>());
+        let bit = (signum - 1) as usize;
+        raw[bit / 8] |= 1 << (bit % 8);
+        return 0;
+    }
+
+    #[test]
+    fn test_process_mask() {
+        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 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();
+
+            let cat = Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()),
+                                           Stdio::Raw(stdout_write.raw()),
+                                           Stdio::None).unwrap();
+            drop(stdin_read);
+            drop(stdout_write);
+
+            cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set, ptr::null_mut())).unwrap();
+
+            cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t, libc::SIGINT)).unwrap();
+            // 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
+            // next scheduled.
+            let _ = stdin_write.write(b"Hello");
+            drop(stdin_write);
+
+            // Either EOF or failure (EPIPE) is okay.
+            let mut buf = [0; 5];
+            if let Ok(ret) = stdout_read.read(&mut buf) {
+                assert!(ret == 0);
+            }
+
+            cat.wait().unwrap();
+        }
+    }
+}
index 7bb9fb68c14f0a4217ca2da3c6c590f65608d838..ee687f350f02129c42988c775130d650cc997b37 100644 (file)
@@ -16,14 +16,13 @@ use sys::sync as ffi;
 
 pub struct RWLock { inner: UnsafeCell<ffi::pthread_rwlock_t> }
 
-pub const RWLOCK_INIT: RWLock = RWLock {
-    inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
-};
-
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
 impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock { inner: UnsafeCell::new(ffi::PTHREAD_RWLOCK_INITIALIZER) }
+    }
     #[inline]
     pub unsafe fn read(&self) {
         let r = ffi::pthread_rwlock_rdlock(self.inner.get());
index 2bc280d12743958fbe5a1ff36b9c96960a27b223..52494a17b9d24f314a44b4504d15fc1e8aa5ce4b 100644 (file)
@@ -44,11 +44,12 @@ mod imp {
     use mem;
     use ptr;
     use intrinsics;
-    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
-                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
-                       SIGSTKSZ};
+    use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL,
+                 SA_SIGINFO, SA_ONSTACK, sigaltstack,
+                 SIGSTKSZ, sighandler_t, raise};
     use libc;
     use libc::funcs::posix88::mman::{mmap, munmap};
+    use libc::funcs::posix01::signal::signal;
     use libc::consts::os::posix88::{SIGSEGV,
                                     PROT_READ,
                                     PROT_WRITE,
@@ -120,7 +121,7 @@ mod imp {
 
     pub unsafe fn make_handler() -> Handler {
         let alt_stack = mmap(ptr::null_mut(),
-                             signal::SIGSTKSZ,
+                             SIGSTKSZ,
                              PROT_READ | PROT_WRITE,
                              MAP_PRIVATE | MAP_ANON,
                              -1,
@@ -143,138 +144,6 @@ mod imp {
     pub unsafe fn drop_handler(handler: &mut Handler) {
         munmap(handler._data, SIGSTKSZ);
     }
-
-    pub type sighandler_t = *mut libc::c_void;
-
-    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
-              all(target_os = "linux", target_arch = "x86_64"),
-              all(target_os = "linux", target_arch = "arm"), // may not match
-              all(target_os = "linux", target_arch = "aarch64"),
-              all(target_os = "linux", target_arch = "mips"), // may not match
-              all(target_os = "linux", target_arch = "mipsel"), // may not match
-              all(target_os = "linux", target_arch = "powerpc"), // may not match
-              target_os = "android"))] // may not match
-    mod signal {
-        use libc;
-        pub use super::sighandler_t;
-
-        pub static SA_ONSTACK: libc::c_int = 0x08000000;
-        pub static SA_SIGINFO: libc::c_int = 0x00000004;
-        pub static SIGBUS: libc::c_int = 7;
-
-        pub static SIGSTKSZ: libc::size_t = 8192;
-
-        pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
-
-        // This definition is not as accurate as it could be, {si_addr} is
-        // actually a giant union. Currently we're only interested in that field,
-        // however.
-        #[repr(C)]
-        pub struct siginfo {
-            si_signo: libc::c_int,
-            si_errno: libc::c_int,
-            si_code: libc::c_int,
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[repr(C)]
-        pub struct sigaction {
-            pub sa_sigaction: sighandler_t,
-            pub sa_mask: sigset_t,
-            pub sa_flags: libc::c_int,
-            sa_restorer: *mut libc::c_void,
-        }
-
-        #[cfg(target_pointer_width = "32")]
-        #[repr(C)]
-        pub struct sigset_t {
-            __val: [libc::c_ulong; 32],
-        }
-        #[cfg(target_pointer_width = "64")]
-        #[repr(C)]
-        pub struct sigset_t {
-            __val: [libc::c_ulong; 16],
-        }
-
-        #[repr(C)]
-        pub struct sigaltstack {
-            pub ss_sp: *mut libc::c_void,
-            pub ss_flags: libc::c_int,
-            pub ss_size: libc::size_t
-        }
-
-    }
-
-    #[cfg(any(target_os = "macos",
-              target_os = "bitrig",
-              target_os = "openbsd"))]
-    mod signal {
-        use libc;
-        pub use super::sighandler_t;
-
-        pub const SA_ONSTACK: libc::c_int = 0x0001;
-        pub const SA_SIGINFO: libc::c_int = 0x0040;
-        pub const SIGBUS: libc::c_int = 10;
-
-        #[cfg(target_os = "macos")]
-        pub const SIGSTKSZ: libc::size_t = 131072;
-        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-        pub const SIGSTKSZ: libc::size_t = 40960;
-
-        pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
-
-        pub type sigset_t = u32;
-
-        // This structure has more fields, but we're not all that interested in
-        // them.
-        #[cfg(target_os = "macos")]
-        #[repr(C)]
-        pub struct siginfo {
-            pub si_signo: libc::c_int,
-            pub si_errno: libc::c_int,
-            pub si_code: libc::c_int,
-            pub pid: libc::pid_t,
-            pub uid: libc::uid_t,
-            pub status: libc::c_int,
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-        #[repr(C)]
-        pub struct siginfo {
-            pub si_signo: libc::c_int,
-            pub si_code: libc::c_int,
-            pub si_errno: libc::c_int,
-            //union
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[repr(C)]
-        pub struct sigaltstack {
-            pub ss_sp: *mut libc::c_void,
-            pub ss_size: libc::size_t,
-            pub ss_flags: libc::c_int
-        }
-
-        #[repr(C)]
-        pub struct sigaction {
-            pub sa_sigaction: sighandler_t,
-            pub sa_mask: sigset_t,
-            pub sa_flags: libc::c_int,
-        }
-    }
-
-    extern {
-        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
-        pub fn raise(signum: libc::c_int) -> libc::c_int;
-
-        pub fn sigaction(signum: libc::c_int,
-                         act: *const sigaction,
-                         oldact: *mut sigaction) -> libc::c_int;
-
-        pub fn sigaltstack(ss: *const sigaltstack,
-                           oss: *mut sigaltstack) -> libc::c_int;
-    }
 }
 
 #[cfg(not(any(target_os = "linux",
index 5f5101e96d7c485ec61ac0bdbc2f44d5a139a45a..fce52f8f92ba8e992e4d793a921fa4a455dbc75d 100644 (file)
@@ -19,7 +19,7 @@ pub struct Stdout(());
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> Stdin { Stdin(()) }
+    pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
 
     pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
         let fd = FileDesc::new(libc::STDIN_FILENO);
@@ -30,7 +30,7 @@ impl Stdin {
 }
 
 impl Stdout {
-    pub fn new() -> Stdout { Stdout(()) }
+    pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
         let fd = FileDesc::new(libc::STDOUT_FILENO);
@@ -41,7 +41,7 @@ impl Stdout {
 }
 
 impl Stderr {
-    pub fn new() -> Stderr { Stderr(()) }
+    pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
         let fd = FileDesc::new(libc::STDERR_FILENO);
index 0cb5a06e6b62f04544193bea70316bc7001e7d7a..bb0e12e8df89944afeca8653820c5e4c661c9905 100644 (file)
@@ -330,10 +330,10 @@ pub mod guard {
 #[cfg(target_os = "linux")]
 fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     use dynamic_lib::DynamicLibrary;
-    use sync::{Once, ONCE_INIT};
+    use sync::Once;
 
     type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
-    static INIT: Once = ONCE_INIT;
+    static INIT: Once = Once::new();
     static mut __pthread_get_minstack: Option<F> = None;
 
     INIT.call_once(|| {
index 9b7079ee10833de308a6cb70ba250e59f5a8d959..3afe84b25804c3c5d11836da16d80052984b7ec0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)] // sys isn't exported yet
+
 use prelude::v1::*;
 use libc::c_int;
 
index 16dfd3eebd02e5f9ccc98502441fa7a34947af8e..6b84baeca7dc9d6a2d0f298c253f53d196de2a62 100644 (file)
@@ -17,7 +17,7 @@ mod inner {
     use libc;
     use time::Duration;
     use ops::Sub;
-    use sync::{Once, ONCE_INIT};
+    use sync::Once;
     use super::NSEC_PER_SEC;
 
     pub struct SteadyTime {
@@ -42,7 +42,7 @@ mod inner {
             numer: 0,
             denom: 0,
         };
-        static ONCE: Once = ONCE_INIT;
+        static ONCE: Once = Once::new();
 
         unsafe {
             ONCE.call_once(|| {
index d94dfdeeea494fe1d315e441562b7c5c74576989..3f595762fc71b58b0149f4fdf27461daf1fccd46 100644 (file)
@@ -36,7 +36,7 @@ use mem;
 use path::Path;
 use ptr;
 use str;
-use sync::{StaticMutex, MUTEX_INIT};
+use sync::StaticMutex;
 
 use sys_common::backtrace::*;
 
@@ -295,7 +295,7 @@ impl Drop for Cleanup {
 pub fn write(w: &mut Write) -> io::Result<()> {
     // According to windows documentation, all dbghelp functions are
     // single-threaded.
-    static LOCK: StaticMutex = MUTEX_INIT;
+    static LOCK: StaticMutex = StaticMutex::new();
     let _g = LOCK.lock();
 
     // Open up dbghelp.dll, we don't link to it explicitly because it can't
index b07d063de45c992630cd76c61459b1c08ac7823e..3c9b2ef1b986ecbef40a4201ed11c51771b410aa 100644 (file)
@@ -340,10 +340,10 @@ pub mod compat {
                                       -> $rettype:ty { $fallback:expr }) => (
             #[inline(always)]
             pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
-                use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+                use sync::atomic::{AtomicUsize, Ordering};
                 use mem;
 
-                static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
+                static PTR: AtomicUsize = AtomicUsize::new(0);
 
                 fn load() -> usize {
                     ::sys::c::compat::store_func(&PTR,
@@ -482,6 +482,7 @@ extern "system" {
                                dwMilliseconds: libc::DWORD) -> libc::DWORD;
     pub fn SwitchToThread() -> libc::BOOL;
     pub fn Sleep(dwMilliseconds: libc::DWORD);
+    pub fn GetProcessId(handle: libc::HANDLE) -> libc::DWORD;
 }
 
 #[link(name = "userenv")]
index 8bb2326e4d6b9dc52d713a0a3347d4f3f22d085a..baa7d1ceea3316d41923f13ec0fafee8a5dbd6cc 100644 (file)
@@ -22,13 +22,10 @@ pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
 unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
-pub const CONDVAR_INIT: Condvar = Condvar {
-    inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT }
-};
-
 impl Condvar {
-    #[inline]
-    pub unsafe fn new() -> Condvar { CONDVAR_INIT }
+    pub const fn new() -> Condvar {
+        Condvar { inner: UnsafeCell::new(ffi::CONDITION_VARIABLE_INIT) }
+    }
 
     #[inline]
     pub unsafe fn wait(&self, mutex: &Mutex) {
index bbda23c9fef2cc96d5bc7f2db777f669bc7ef6d0..f629e983ce542aeaa438406ca607b73fb709af22 100644 (file)
@@ -26,41 +26,41 @@ use sys_common::{AsInnerMut, AsInner};
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
     /// with the specified value.
-    fn desired_access(&mut self, access: i32) -> &mut Self;
+    fn desired_access(&mut self, access: u32) -> &mut Self;
 
     /// Overrides the `dwCreationDisposition` argument to the call to
     /// `CreateFile` with the specified value.
     ///
     /// This will override any values of the standard `create` flags, for
     /// example.
-    fn creation_disposition(&mut self, val: i32) -> &mut Self;
+    fn creation_disposition(&mut self, val: u32) -> &mut Self;
 
     /// Overrides the `dwFlagsAndAttributes` argument to the call to
     /// `CreateFile` with the specified value.
     ///
     /// This will override any values of the standard flags on the
     /// `OpenOptions` structure.
-    fn flags_and_attributes(&mut self, val: i32) -> &mut Self;
+    fn flags_and_attributes(&mut self, val: u32) -> &mut Self;
 
     /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
     /// the specified value.
     ///
     /// This will override any values of the standard flags on the
     /// `OpenOptions` structure.
-    fn share_mode(&mut self, val: i32) -> &mut Self;
+    fn share_mode(&mut self, val: u32) -> &mut Self;
 }
 
 impl OpenOptionsExt for OpenOptions {
-    fn desired_access(&mut self, access: i32) -> &mut OpenOptions {
+    fn desired_access(&mut self, access: u32) -> &mut OpenOptions {
         self.as_inner_mut().desired_access(access); self
     }
-    fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions {
+    fn creation_disposition(&mut self, access: u32) -> &mut OpenOptions {
         self.as_inner_mut().creation_disposition(access); self
     }
-    fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions {
+    fn flags_and_attributes(&mut self, access: u32) -> &mut OpenOptions {
         self.as_inner_mut().flags_and_attributes(access); self
     }
-    fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
+    fn share_mode(&mut self, access: u32) -> &mut OpenOptions {
         self.as_inner_mut().share_mode(access); self
     }
 }
@@ -129,7 +129,7 @@ impl MetadataExt for Metadata {
 /// # Ok(())
 /// # }
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                     -> io::Result<()> {
     sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
@@ -150,7 +150,7 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
 /// # Ok(())
 /// # }
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
                                                    -> io::Result<()> {
     sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
index 58db1d352056288405bf82a9e05e034d20883a35..65c3c506d3c8effb27a8342026b9a561609c36c1 100644 (file)
@@ -20,6 +20,7 @@ pub mod ffi;
 pub mod fs;
 pub mod io;
 pub mod raw;
+pub mod process;
 
 /// A prelude for conveniently writing platform-specific code.
 ///
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
new file mode 100644 (file)
index 0000000..6f59be2
--- /dev/null
@@ -0,0 +1,54 @@
+// 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.
+
+//! Extensions to `std::process` for Windows.
+
+#![stable(feature = "process_extensions", since = "1.2.0")]
+
+use os::windows::io::{FromRawHandle, RawHandle, AsRawHandle};
+use process;
+use sys;
+use sys_common::{AsInner, FromInner};
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl FromRawHandle for process::Stdio {
+    unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
+        let handle = sys::handle::Handle::new(handle as *mut _);
+        process::Stdio::from_inner(handle)
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawHandle for process::Child {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawHandle for process::ChildStdin {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawHandle for process::ChildStdout {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawHandle for process::ChildStderr {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as *mut _
+    }
+}
index e1796d4b5f0737df979e14653d6caaf68653e7a5..92d53e2e4288499efb18ef0794f531f85c21813a 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Windows-specific primitives
 
-#[stable(feature = "raw_ext", since = "1.1.0")]
+#![stable(feature = "raw_ext", since = "1.1.0")]
 
 use os::raw::c_void;
 
index 03a56e2958a6e9f485b050323ac42274b744b9eb..437b2cc6491179e2020bdeeeb3244f880d994c3d 100644 (file)
@@ -158,17 +158,17 @@ impl OpenOptions {
     pub fn append(&mut self, append: bool) { self.append = append; }
     pub fn create(&mut self, create: bool) { self.create = create; }
     pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
-    pub fn creation_disposition(&mut self, val: i32) {
-        self.creation_disposition = Some(val as libc::DWORD);
+    pub fn creation_disposition(&mut self, val: u32) {
+        self.creation_disposition = Some(val);
     }
-    pub fn flags_and_attributes(&mut self, val: i32) {
-        self.flags_and_attributes = Some(val as libc::DWORD);
+    pub fn flags_and_attributes(&mut self, val: u32) {
+        self.flags_and_attributes = Some(val);
     }
-    pub fn desired_access(&mut self, val: i32) {
-        self.desired_access = Some(val as libc::DWORD);
+    pub fn desired_access(&mut self, val: u32) {
+        self.desired_access = Some(val);
     }
-    pub fn share_mode(&mut self, val: i32) {
-        self.share_mode = Some(val as libc::DWORD);
+    pub fn share_mode(&mut self, val: u32) {
+        self.share_mode = Some(val);
     }
     pub fn security_attributes(&mut self, attrs: libc::LPSECURITY_ATTRIBUTES) {
         self.security_attributes = attrs as usize;
@@ -221,7 +221,7 @@ impl File {
     fn open_reparse_point(path: &Path) -> io::Result<File> {
         let mut opts = OpenOptions::new();
         opts.read(true);
-        opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT as i32);
+        opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT);
         File::open(path, &opts)
     }
 
@@ -368,7 +368,7 @@ impl fmt::Debug for File {
 }
 
 pub fn to_utf16(s: &Path) -> Vec<u16> {
-    s.as_os_str().encode_wide().chain(Some(0).into_iter()).collect()
+    s.as_os_str().encode_wide().chain(Some(0)).collect()
 }
 
 impl FileAttr {
index c835d503388c7c57925a171d4d49337e9fb47d81..a566c5eff324e04ad6cb4a477dc7ceb6421ca9b9 100644 (file)
@@ -15,26 +15,55 @@ use io;
 use libc::funcs::extra::kernel32::{GetCurrentProcess, DuplicateHandle};
 use libc::{self, HANDLE};
 use mem;
+use ops::Deref;
 use ptr;
 use sys::cvt;
 
-pub struct Handle(HANDLE);
+/// An owned container for `HANDLE` object, closing them on Drop.
+///
+/// All methods are inherited through a `Deref` impl to `RawHandle`
+pub struct Handle(RawHandle);
 
-unsafe impl Send for Handle {}
-unsafe impl Sync for Handle {}
+/// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
+/// as well as Rust-y methods.
+///
+/// This does **not** drop the handle when it goes out of scope, use `Handle`
+/// instead for that.
+#[derive(Copy, Clone)]
+pub struct RawHandle(HANDLE);
+
+unsafe impl Send for RawHandle {}
+unsafe impl Sync for RawHandle {}
 
 impl Handle {
     pub fn new(handle: HANDLE) -> Handle {
-        Handle(handle)
+        Handle(RawHandle::new(handle))
     }
 
-    pub fn raw(&self) -> HANDLE { self.0 }
-
     pub fn into_raw(self) -> HANDLE {
-        let ret = self.0;
+        let ret = self.raw();
         mem::forget(self);
         return ret;
     }
+}
+
+impl Deref for Handle {
+    type Target = RawHandle;
+    fn deref(&self) -> &RawHandle { &self.0 }
+}
+
+impl Drop for Handle {
+    fn drop(&mut self) {
+        unsafe { let _ = libc::CloseHandle(self.raw()); }
+    }
+}
+
+impl RawHandle {
+    pub fn new(handle: HANDLE) -> RawHandle {
+        RawHandle(handle)
+    }
+
+    pub fn raw(&self) -> HANDLE { self.0 }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
@@ -79,9 +108,3 @@ impl Handle {
         Ok(Handle::new(ret))
     }
 }
-
-impl Drop for Handle {
-    fn drop(&mut self) {
-        unsafe { let _ = libc::CloseHandle(self.0); }
-    }
-}
index 6b7bff2c1c6f82929df83458d5ad68be66bd54a3..18c8add17a6d6d307103d93e6e00ac4c3805008d 100644 (file)
@@ -60,6 +60,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::WSAEINVAL => ErrorKind::InvalidInput,
         libc::WSAENOTCONN => ErrorKind::NotConnected,
         libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
+        libc::WSAETIMEDOUT => ErrorKind::TimedOut,
 
         _ => ErrorKind::Other,
     }
index 9d2624f94180e5612fc4439dba3f9c5e5a3a73d9..29e370698ad744b727f4c202c5d333a9ee6ea193 100644 (file)
@@ -16,10 +16,6 @@ use mem;
 
 pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
 
-pub const MUTEX_INIT: Mutex = Mutex {
-    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
-};
-
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
@@ -41,6 +37,9 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
 //    is there there are no guarantees of fairness.
 
 impl Mutex {
+    pub const fn new() -> Mutex {
+        Mutex { inner: UnsafeCell::new(ffi::SRWLOCK_INIT) }
+    }
     #[inline]
     pub unsafe fn lock(&self) {
         ffi::AcquireSRWLockExclusive(self.inner.get())
index 6bbcd968157aba084deecae84dbe9fad92a8456a..0b9052672369d40da703be63f36969d1b39d45e9 100644 (file)
@@ -18,9 +18,12 @@ use net::SocketAddr;
 use num::One;
 use ops::Neg;
 use rt;
-use sync::{Once, ONCE_INIT};
+use sync::Once;
+use sys;
 use sys::c;
 use sys_common::{AsInner, FromInner};
+use sys_common::net::{setsockopt, getsockopt};
+use time::Duration;
 
 pub type wrlen_t = i32;
 
@@ -29,7 +32,7 @@ pub struct Socket(libc::SOCKET);
 /// Checks whether the Windows socket interface has been started already, and
 /// if not, starts it.
 pub fn init() {
-    static START: Once = ONCE_INIT;
+    static START: Once = Once::new();
 
     START.call_once(|| unsafe {
         let mut data: c::WSADATA = mem::zeroed();
@@ -127,6 +130,32 @@ impl Socket {
             }
         }
     }
+
+    pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
+        let timeout = match dur {
+            Some(dur) => {
+                let timeout = sys::dur2timeout(dur);
+                if timeout == 0 {
+                    return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                              "cannot set a 0 duration timeout"));
+                }
+                timeout
+            }
+            None => 0
+        };
+        setsockopt(self, libc::SOL_SOCKET, kind, timeout)
+    }
+
+    pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
+        let raw: libc::DWORD = try!(getsockopt(self, libc::SOL_SOCKET, kind));
+        if raw == 0 {
+            Ok(None)
+        } else {
+            let secs = raw / 1000;
+            let nsec = (raw % 1000) * 1000000;
+            Ok(Some(Duration::new(secs as u64, nsec as u32)))
+        }
+    }
 }
 
 impl Drop for Socket {
index b441d8beedbc04dd7ab3569aafab81af3fc399c6..b2a6607314a50600b000ab8ce3c626e36ecd189d 100644 (file)
@@ -38,6 +38,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
 impl AnonPipe {
     pub fn handle(&self) -> &Handle { &self.inner }
 
+    pub fn raw(&self) -> libc::HANDLE { self.inner.raw() }
+
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
index 032a349b00eff11e211f6a6a6da2e7f3766d3003..0b0268d4746ab6b905d20222340d86b79dea753f 100644 (file)
@@ -24,11 +24,10 @@ use mem;
 use os::windows::ffi::OsStrExt;
 use path::Path;
 use ptr;
-use sync::{StaticMutex, MUTEX_INIT};
+use sync::StaticMutex;
 use sys::c;
 use sys::fs::{OpenOptions, File};
-use sys::handle::Handle;
-use sys::pipe::AnonPipe;
+use sys::handle::{Handle, RawHandle};
 use sys::stdio;
 use sys::{self, cvt};
 use sys_common::{AsInner, FromInner};
@@ -107,10 +106,12 @@ pub struct Process {
 
 pub enum Stdio {
     Inherit,
-    Piped(AnonPipe),
     None,
+    Raw(libc::HANDLE),
 }
 
+pub type RawStdio = Handle;
+
 impl Process {
     pub fn spawn(cfg: &Command,
                  in_handle: Stdio,
@@ -169,7 +170,7 @@ impl Process {
         try!(unsafe {
             // `CreateProcess` is racy!
             // http://support.microsoft.com/kb/315939
-            static CREATE_PROCESS_LOCK: StaticMutex = MUTEX_INIT;
+            static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new();
             let _lock = CREATE_PROCESS_LOCK.lock();
 
             cvt(CreateProcessW(ptr::null(),
@@ -193,6 +194,12 @@ impl Process {
         Ok(())
     }
 
+    pub fn id(&self) -> u32 {
+        unsafe {
+            c::GetProcessId(self.handle.raw()) as u32
+        }
+    }
+
     pub fn wait(&self) -> io::Result<ExitStatus> {
         use libc::{STILL_ACTIVE, INFINITE, WAIT_OBJECT_0};
         use libc::{GetExitCodeProcess, WaitForSingleObject};
@@ -211,6 +218,8 @@ impl Process {
             }
         }
     }
+
+    pub fn handle(&self) -> &Handle { &self.handle }
 }
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -356,8 +365,8 @@ impl Stdio {
                     io.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
                 })
             }
-            Stdio::Piped(ref pipe) => {
-                pipe.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
+            Stdio::Raw(handle) => {
+                RawHandle::new(handle).duplicate(0, true, DUPLICATE_SAME_ACCESS)
             }
 
             // Similarly to unix, we don't actually leave holes for the
index 009605535a0237026d18ec29e0d783feb626a362..e727638e3e9b5cddf67a2dfd14792649627a1080 100644 (file)
@@ -15,14 +15,13 @@ use sys::sync as ffi;
 
 pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
 
-pub const RWLOCK_INIT: RWLock = RWLock {
-    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
-};
-
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
 impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock { inner: UnsafeCell::new(ffi::SRWLOCK_INIT) }
+    }
     #[inline]
     pub unsafe fn read(&self) {
         ffi::AcquireSRWLockShared(self.inner.get())
index 03547165f5d8700aa3f3939b8511db9cb237724e..9961fef714abbb2228b499dd6c2063350a3d0d81 100644 (file)
@@ -77,11 +77,13 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
 }
 
 impl Stdin {
-    pub fn new() -> Stdin {
-        Stdin {
-            handle: get(c::STD_INPUT_HANDLE).unwrap(),
-            utf8: Mutex::new(Cursor::new(Vec::new())),
-        }
+    pub fn new() -> io::Result<Stdin> {
+        get(c::STD_INPUT_HANDLE).map(|handle| {
+            Stdin {
+                handle: handle,
+                utf8: Mutex::new(Cursor::new(Vec::new())),
+            }
+        })
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -116,8 +118,8 @@ impl Stdin {
 }
 
 impl Stdout {
-    pub fn new() -> Stdout {
-        Stdout(get(c::STD_OUTPUT_HANDLE).unwrap())
+    pub fn new() -> io::Result<Stdout> {
+        get(c::STD_OUTPUT_HANDLE).map(Stdout)
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
@@ -126,8 +128,8 @@ impl Stdout {
 }
 
 impl Stderr {
-    pub fn new() -> Stderr {
-        Stderr(get(c::STD_ERROR_HANDLE).unwrap())
+    pub fn new() -> io::Result<Stderr> {
+        get(c::STD_ERROR_HANDLE).map(Stderr)
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
@@ -170,5 +172,5 @@ impl Output {
 }
 
 fn invalid_encoding() -> io::Error {
-    io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode")
+    io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
index ea5af3f2830e8cd0ad58449457878707a6c1ec10..5002de559884d0f52773fd9fa75f914e9a2b0e76 100644 (file)
@@ -12,10 +12,9 @@ use prelude::v1::*;
 
 use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
 
-use boxed;
 use ptr;
 use rt;
-use sys_common::mutex::{MUTEX_INIT, Mutex};
+use sys_common::mutex::Mutex;
 
 pub type Key = DWORD;
 pub type Dtor = unsafe extern fn(*mut u8);
@@ -58,7 +57,7 @@ pub type Dtor = unsafe extern fn(*mut u8);
 // on poisoning and this module needs to operate at a lower level than requiring
 // the thread infrastructure to be in place (useful on the borders of
 // initialization/destruction).
-static DTOR_LOCK: Mutex = MUTEX_INIT;
+static DTOR_LOCK: Mutex = Mutex::new();
 static mut DTORS: *mut Vec<(Key, Dtor)> = 0 as *mut _;
 
 // -------------------------------------------------------------------------
@@ -143,7 +142,7 @@ unsafe fn init_dtors() {
         DTOR_LOCK.unlock();
     });
     if res.is_ok() {
-        DTORS = boxed::into_raw(dtors);
+        DTORS = Box::into_raw(dtors);
     } else {
         DTORS = 1 as *mut _;
     }
index e64df54a0fa035bc7285e3a08323430cac480d95..f5a70ccc90743a34ba1be9cc27b17b498c78d7b9 100644 (file)
@@ -10,7 +10,7 @@
 use libc;
 use ops::Sub;
 use time::Duration;
-use sync::{Once, ONCE_INIT};
+use sync::Once;
 
 const NANOS_PER_SEC: u64 = 1_000_000_000;
 
@@ -28,7 +28,7 @@ impl SteadyTime {
 
 fn frequency() -> libc::LARGE_INTEGER {
     static mut FREQUENCY: libc::LARGE_INTEGER = 0;
-    static ONCE: Once = ONCE_INIT;
+    static ONCE: Once = Once::new();
 
     unsafe {
         ONCE.call_once(|| {
index f2435b60d8e2847a01bbb67c5d90e56d7a4e6604..60563340d10210c372210ad6fae89836648b9ce4 100644 (file)
@@ -18,12 +18,7 @@ use cell::UnsafeCell;
 
 // Sure wish we had macro hygiene, no?
 #[doc(hidden)]
-pub mod __impl {
-    pub use super::imp::Key as KeyInner;
-    pub use super::imp::destroy_value;
-    pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER;
-    pub use sys_common::thread_local::StaticKey as OsStaticKey;
-}
+pub use self::imp::Key as __KeyInner;
 
 /// A thread local storage key which owns its contents.
 ///
@@ -76,55 +71,10 @@ pub struct LocalKey<T> {
     //
     // This is trivially devirtualizable by LLVM because we never store anything
     // to this field and rustc can declare the `static` as constant as well.
-    #[doc(hidden)]
-    pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
+    inner: fn() -> &'static __KeyInner<T>,
 
     // initialization routine to invoke to create a value
-    #[doc(hidden)]
-    pub init: fn() -> T,
-}
-
-/// Declare a new thread local storage key of type `std::thread::LocalKey`.
-///
-/// See [LocalKey documentation](thread/struct.LocalKey.html) for more information.
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable]
-macro_rules! thread_local {
-    (static $name:ident: $t:ty = $init:expr) => (
-        static $name: ::std::thread::LocalKey<$t> = {
-            use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread::__local::KeyInner as __KeyInner;
-            use std::option::Option as __Option;
-            use std::option::Option::None as __None;
-
-            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
-                __UnsafeCell { value: __None }
-            });
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
-                &__KEY
-            }
-            ::std::thread::LocalKey { inner: __getit, init: __init }
-        };
-    );
-    (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: ::std::thread::LocalKey<$t> = {
-            use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread::__local::KeyInner as __KeyInner;
-            use std::option::Option as __Option;
-            use std::option::Option::None as __None;
-
-            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
-                __UnsafeCell { value: __None }
-            });
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
-                &__KEY
-            }
-            ::std::thread::LocalKey { inner: __getit, init: __init }
-        };
-    );
+    init: fn() -> T,
 }
 
 // Macro pain #4586:
@@ -147,86 +97,64 @@ macro_rules! thread_local {
 // To get around this, we're forced to inject the #[cfg] logic into the macro
 // itself. Woohoo.
 
+/// Declare a new thread local storage key of type `std::thread::LocalKey`.
+///
+/// See [LocalKey documentation](thread/struct.LocalKey.html) for more
+/// information.
 #[macro_export]
-#[doc(hidden)]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
 #[cfg(not(no_elf_tls))]
-macro_rules! __thread_local_inner {
+macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
-        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                       not(target_arch = "aarch64")),
-                   thread_local)]
-        static $name: ::std::thread::__local::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
+        static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init,
+                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                               not(target_arch = "aarch64")),
+                           thread_local)]);
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
-        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                       not(target_arch = "aarch64")),
-                   thread_local)]
-        pub static $name: ::std::thread::__local::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
+        pub static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init,
+                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                               not(target_arch = "aarch64")),
+                           thread_local)]);
     );
-    ($init:expr, $t:ty) => ({
-        #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
-        const _INIT: ::std::thread::__local::KeyInner<$t> = {
-            ::std::thread::__local::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                dtor_registered: ::std::cell::UnsafeCell { value: false },
-                dtor_running: ::std::cell::UnsafeCell { value: false },
-            }
-        };
-
-        #[allow(trivial_casts)]
-        #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
-        const _INIT: ::std::thread::__local::KeyInner<$t> = {
-            ::std::thread::__local::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                os: ::std::thread::__local::OsStaticKey {
-                    inner: ::std::thread::__local::OS_INIT_INNER,
-                    dtor: ::std::option::Option::Some(
-                        ::std::thread::__local::destroy_value::<$t>
-                    ),
-                },
-            }
-        };
-
-        _INIT
-    });
 }
 
 #[macro_export]
-#[doc(hidden)]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
 #[cfg(no_elf_tls)]
-macro_rules! __thread_local_inner {
+macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
-        static $name: ::std::thread::__local::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
+        static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init, #[]);
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: ::std::thread::__local::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
+        pub static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init, #[]);
     );
-    ($init:expr, $t:ty) => ({
-        #[allow(trivial_casts)]
-        const _INIT: ::std::thread::__local::KeyInner<$t> = {
-            ::std::thread::__local::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                os: ::std::thread::__local::OsStaticKey {
-                    inner: ::std::thread::__local::OS_INIT_INNER,
-                    dtor: ::std::option::Option::Some(
-                        ::std::thread::__local::destroy_value::<$t>
-                    ),
-                },
-            }
-        };
+}
 
-        _INIT
-    });
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
+#[macro_export]
+#[allow_internal_unstable]
+macro_rules! __thread_local_inner {
+    ($t:ty, $init:expr, #[$($attr:meta),*]) => {{
+        $(#[$attr])*
+        static __KEY: ::std::thread::__LocalKeyInner<$t> =
+            ::std::thread::__LocalKeyInner::new();
+        fn __init() -> $t { $init }
+        fn __getit() -> &'static ::std::thread::__LocalKeyInner<$t> { &__KEY }
+        ::std::thread::LocalKey::new(__getit, __init)
+    }}
 }
 
 /// Indicator of the state of a thread local storage key.
-#[unstable(feature = "std_misc",
+#[unstable(feature = "thread_local_state",
            reason = "state querying was recently added")]
 #[derive(Eq, PartialEq, Copy, Clone)]
 pub enum LocalKeyState {
@@ -257,6 +185,17 @@ pub enum LocalKeyState {
 }
 
 impl<T: 'static> LocalKey<T> {
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals",
+               reason = "recently added to create a key")]
+    pub const fn new(inner: fn() -> &'static __KeyInner<T>,
+                     init: fn() -> T) -> LocalKey<T> {
+        LocalKey {
+            inner: inner,
+            init: init
+        }
+    }
+
     /// Acquires a reference to the value in this TLS key.
     ///
     /// This will lazily initialize the value if this thread has not referenced
@@ -310,7 +249,7 @@ impl<T: 'static> LocalKey<T> {
     /// initialization does not panic. Keys in the `Valid` state are guaranteed
     /// to be able to be accessed. Keys in the `Destroyed` state will panic on
     /// any call to `with`.
-    #[unstable(feature = "std_misc",
+    #[unstable(feature = "thread_local_state",
                reason = "state querying was recently added")]
     pub fn state(&'static self) -> LocalKeyState {
         unsafe {
@@ -334,44 +273,45 @@ impl<T: 'static> LocalKey<T> {
 mod imp {
     use prelude::v1::*;
 
-    use cell::UnsafeCell;
+    use cell::{Cell, UnsafeCell};
     use intrinsics;
-    use ptr;
 
     pub struct Key<T> {
-        // Place the inner bits in an `UnsafeCell` to currently get around the
-        // "only Sync statics" restriction. This allows any type to be placed in
-        // the cell.
-        //
-        // Note that all access requires `T: 'static` so it can't be a type with
-        // any borrowed pointers still.
-        pub inner: UnsafeCell<T>,
+        inner: UnsafeCell<Option<T>>,
 
         // Metadata to keep track of the state of the destructor. Remember that
         // these variables are thread-local, not global.
-        pub dtor_registered: UnsafeCell<bool>, // should be Cell
-        pub dtor_running: UnsafeCell<bool>, // should be Cell
+        dtor_registered: Cell<bool>,
+        dtor_running: Cell<bool>,
     }
 
     unsafe impl<T> ::marker::Sync for Key<T> { }
 
     impl<T> Key<T> {
-        pub unsafe fn get(&'static self) -> Option<&'static T> {
-            if intrinsics::needs_drop::<T>() && *self.dtor_running.get() {
+        pub const fn new() -> Key<T> {
+            Key {
+                inner: UnsafeCell::new(None),
+                dtor_registered: Cell::new(false),
+                dtor_running: Cell::new(false)
+            }
+        }
+
+        pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
+            if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
                 return None
             }
             self.register_dtor();
-            Some(&*self.inner.get())
+            Some(&self.inner)
         }
 
         unsafe fn register_dtor(&self) {
-            if !intrinsics::needs_drop::<T>() || *self.dtor_registered.get() {
+            if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
                 return
             }
 
             register_dtor(self as *const _ as *mut u8,
                           destroy_value::<T>);
-            *self.dtor_registered.get() = true;
+            self.dtor_registered.set(true);
         }
     }
 
@@ -386,8 +326,8 @@ mod imp {
     // Due to rust-lang/rust#18804, make sure this is not generic!
     #[cfg(target_os = "linux")]
     unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
-        use boxed;
         use mem;
+        use ptr;
         use libc;
         use sys_common::thread_local as os;
 
@@ -415,14 +355,11 @@ mod imp {
         // *should* be the case that this loop always terminates because we
         // provide the guarantee that a TLS key cannot be set after it is
         // flagged for destruction.
-        static DTORS: os::StaticKey = os::StaticKey {
-            inner: os::INIT_INNER,
-            dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)),
-        };
+        static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
         type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
         if DTORS.get().is_null() {
             let v: Box<List> = box Vec::new();
-            DTORS.set(boxed::into_raw(v) as *mut u8);
+            DTORS.set(Box::into_raw(v) as *mut u8);
         }
         let list: &mut List = &mut *(DTORS.get() as *mut List);
         list.push((t, dtor));
@@ -430,7 +367,7 @@ mod imp {
         unsafe extern fn run_dtors(mut ptr: *mut u8) {
             while !ptr.is_null() {
                 let list: Box<List> = Box::from_raw(ptr as *mut List);
-                for &(ptr, dtor) in &*list {
+                for &(ptr, dtor) in list.iter() {
                     dtor(ptr);
                 }
                 ptr = DTORS.get();
@@ -456,8 +393,8 @@ mod imp {
         // Right before we run the user destructor be sure to flag the
         // destructor as running for this thread so calls to `get` will return
         // `None`.
-        *(*ptr).dtor_running.get() = true;
-        ptr::read((*ptr).inner.get());
+        (*ptr).dtor_running.set(true);
+        intrinsics::drop_in_place((*ptr).inner.get());
     }
 }
 
@@ -468,55 +405,50 @@ mod imp {
 mod imp {
     use prelude::v1::*;
 
-    use alloc::boxed;
-    use cell::UnsafeCell;
-    use mem;
+    use cell::{Cell, UnsafeCell};
+    use marker;
     use ptr;
     use sys_common::thread_local::StaticKey as OsStaticKey;
 
     pub struct Key<T> {
-        // Statically allocated initialization expression, using an `UnsafeCell`
-        // for the same reasons as above.
-        pub inner: UnsafeCell<T>,
-
         // OS-TLS key that we'll use to key off.
-        pub os: OsStaticKey,
+        os: OsStaticKey,
+        marker: marker::PhantomData<Cell<T>>,
     }
 
     unsafe impl<T> ::marker::Sync for Key<T> { }
 
     struct Value<T: 'static> {
         key: &'static Key<T>,
-        value: T,
+        value: UnsafeCell<Option<T>>,
     }
 
-    impl<T> Key<T> {
-        pub unsafe fn get(&'static self) -> Option<&'static T> {
-            self.ptr().map(|p| &*p)
+    impl<T: 'static> Key<T> {
+        pub const fn new() -> Key<T> {
+            Key {
+                os: OsStaticKey::new(Some(destroy_value::<T>)),
+                marker: marker::PhantomData
+            }
         }
 
-        unsafe fn ptr(&'static self) -> Option<*mut T> {
+        pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
             let ptr = self.os.get() as *mut Value<T>;
             if !ptr.is_null() {
                 if ptr as usize == 1 {
                     return None
                 }
-                return Some(&mut (*ptr).value as *mut T);
+                return Some(&(*ptr).value);
             }
 
             // If the lookup returned null, we haven't initialized our own local
             // copy, so do that now.
-            //
-            // Also note that this transmute_copy should be ok because the value
-            // `inner` is already validated to be a valid `static` value, so we
-            // should be able to freely copy the bits.
             let ptr: Box<Value<T>> = box Value {
                 key: self,
-                value: mem::transmute_copy(&self.inner),
+                value: UnsafeCell::new(None),
             };
-            let ptr = boxed::into_raw(ptr);
+            let ptr = Box::into_raw(ptr);
             self.os.set(ptr as *mut u8);
-            Some(&mut (*ptr).value as *mut T)
+            Some(&(*ptr).value)
         }
     }
 
@@ -541,7 +473,7 @@ mod tests {
     use prelude::v1::*;
 
     use sync::mpsc::{channel, Sender};
-    use cell::UnsafeCell;
+    use cell::{Cell, UnsafeCell};
     use super::LocalKeyState;
     use thread;
 
@@ -556,23 +488,23 @@ mod tests {
 
     #[test]
     fn smoke_no_dtor() {
-        thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
+        thread_local!(static FOO: Cell<i32> = Cell::new(1));
 
-        FOO.with(|f| unsafe {
-            assert_eq!(*f.get(), 1);
-            *f.get() = 2;
+        FOO.with(|f| {
+            assert_eq!(f.get(), 1);
+            f.set(2);
         });
         let (tx, rx) = channel();
         let _t = thread::spawn(move|| {
-            FOO.with(|f| unsafe {
-                assert_eq!(*f.get(), 1);
+            FOO.with(|f| {
+                assert_eq!(f.get(), 1);
             });
             tx.send(()).unwrap();
         });
         rx.recv().unwrap();
 
-        FOO.with(|f| unsafe {
-            assert_eq!(*f.get(), 2);
+        FOO.with(|f| {
+            assert_eq!(f.get(), 2);
         });
     }
 
@@ -601,9 +533,7 @@ mod tests {
 
     #[test]
     fn smoke_dtor() {
-        thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell {
-            value: None
-        });
+        thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
 
         let (tx, rx) = channel();
         let _t = thread::spawn(move|| unsafe {
@@ -619,12 +549,8 @@ mod tests {
     fn circular() {
         struct S1;
         struct S2;
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
-        thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
-            value: None
-        });
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
+        thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell::new(None));
         static mut HITS: u32 = 0;
 
         impl Drop for S1 {
@@ -662,9 +588,7 @@ mod tests {
     #[test]
     fn self_referential() {
         struct S1;
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
 
         impl Drop for S1 {
             fn drop(&mut self) {
@@ -680,12 +604,8 @@ mod tests {
     #[test]
     fn dtors_in_dtors_in_dtors() {
         struct S1(Sender<()>);
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
-        thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell {
-            value: None
-        });
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
+        thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
 
         impl Drop for S1 {
             fn drop(&mut self) {
index 7c8cb5b01c1088bfe9f176a6f738d812f5cf1e73..dbb7d3233bc39a95086ee4f5048461123af725d1 100644 (file)
@@ -216,8 +216,8 @@ pub use self::local::{LocalKey, LocalKeyState};
                       consider stabilizing its interface")]
 pub use self::scoped_tls::ScopedKey;
 
-#[doc(hidden)] pub use self::local::__impl as __local;
-#[doc(hidden)] pub use self::scoped_tls::__impl as __scoped;
+#[doc(hidden)] pub use self::local::__KeyInner as __LocalKeyInner;
+#[doc(hidden)] pub use self::scoped_tls::__KeyInner as __ScopedKeyInner;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
@@ -297,6 +297,9 @@ impl Builder {
     /// the OS level.
     #[unstable(feature = "scoped",
                reason = "memory unsafe if destructor is avoided, see #24292")]
+    #[deprecated(since = "1.2.0",
+                 reason = "this unsafe API is unlikely to ever be stabilized \
+                           in this form")]
     pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
         T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
     {
@@ -398,6 +401,10 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
 /// to recover from such errors.
 #[unstable(feature = "scoped",
            reason = "memory unsafe if destructor is avoided, see #24292")]
+#[deprecated(since = "1.2.0",
+             reason = "this unsafe API is unlikely to ever be stabilized \
+                       in this form")]
+#[allow(deprecated)]
 pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
     T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
 {
index bde8caaec8dff479bfd1b5344d4525e111fa6fa5..679902ec7abdb0fdaad47b0deb44b4de3e7c1a13 100644 (file)
 
 use prelude::v1::*;
 
-// macro hygiene sure would be nice, wouldn't it?
 #[doc(hidden)]
-pub mod __impl {
-    pub use super::imp::KeyInner;
-    pub use sys_common::thread_local::INIT as OS_INIT;
-}
+pub use self::imp::KeyInner as __KeyInner;
 
 /// Type representing a thread local storage key corresponding to a reference
 /// to the type parameter `T`.
@@ -60,7 +56,7 @@ pub mod __impl {
 #[unstable(feature = "scoped_tls",
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface")]
-pub struct ScopedKey<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
+pub struct ScopedKey<T> { inner: fn() -> &'static imp::KeyInner<T> }
 
 /// Declare a new scoped thread local storage key.
 ///
@@ -71,88 +67,62 @@ pub struct ScopedKey<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
 /// information.
 #[macro_export]
 #[allow_internal_unstable]
-#[cfg(not(no_elf_tls))]
 macro_rules! scoped_thread_local {
     (static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(static $name: $t);
+        static $name: ::std::thread::ScopedKey<$t> =
+            __scoped_thread_local_inner!($t);
     );
     (pub static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(pub static $name: $t);
+        pub static $name: ::std::thread::ScopedKey<$t> =
+            __scoped_thread_local_inner!($t);
     );
 }
 
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
 #[macro_export]
+#[allow_internal_unstable]
+#[cfg(no_elf_tls)]
+macro_rules! __scoped_thread_local_inner {
+    ($t:ty) => {{
+        static _KEY: ::std::thread::__ScopedKeyInner<$t> =
+            ::std::thread::__ScopedKeyInner::new();
+        fn _getit() -> &'static ::std::thread::__ScopedKeyInner<$t> { &_KEY }
+        ::std::thread::ScopedKey::new(_getit)
+    }}
+}
+
 #[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
+#[macro_export]
 #[allow_internal_unstable]
+#[cfg(not(no_elf_tls))]
 macro_rules! __scoped_thread_local_inner {
-    (static $name:ident: $t:ty) => (
+    ($t:ty) => {{
         #[cfg_attr(not(any(windows,
                            target_os = "android",
                            target_os = "ios",
                            target_os = "openbsd",
                            target_arch = "aarch64")),
                    thread_local)]
-        static $name: ::std::thread::ScopedKey<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-    (pub static $name:ident: $t:ty) => (
-        #[cfg_attr(not(any(windows,
-                           target_os = "android",
-                           target_os = "ios",
-                           target_os = "openbsd",
-                           target_arch = "aarch64")),
-                   thread_local)]
-        pub static $name: ::std::thread::ScopedKey<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-    ($t:ty) => ({
-        use std::thread::ScopedKey as __Key;
-
-        #[cfg(not(any(windows,
-                      target_os = "android",
-                      target_os = "ios",
-                      target_os = "openbsd",
-                      target_arch = "aarch64")))]
-        const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread::__scoped::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
-            }
-        };
-
-        #[cfg(any(windows,
-                  target_os = "android",
-                  target_os = "ios",
-                  target_os = "openbsd",
-                  target_arch = "aarch64"))]
-        const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread::__scoped::KeyInner {
-                inner: ::std::thread::__scoped::OS_INIT,
-                marker: ::std::marker::PhantomData::<::std::cell::Cell<$t>>,
-            }
-        };
-
-        _INIT
-    })
-}
-
-#[macro_export]
-#[allow_internal_unstable]
-#[cfg(no_elf_tls)]
-macro_rules! scoped_thread_local {
-    (static $name:ident: $t:ty) => (
-        static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
-    );
-    (pub static $name:ident: $t:ty) => (
-        pub static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
-    );
+        static _KEY: ::std::thread::__ScopedKeyInner<$t> =
+            ::std::thread::__ScopedKeyInner::new();
+        fn _getit() -> &'static ::std::thread::__ScopedKeyInner<$t> { &_KEY }
+        ::std::thread::ScopedKey::new(_getit)
+    }}
 }
 
 #[unstable(feature = "scoped_tls",
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface")]
 impl<T> ScopedKey<T> {
+    #[doc(hidden)]
+    pub const fn new(inner: fn() -> &'static imp::KeyInner<T>) -> ScopedKey<T> {
+        ScopedKey { inner: inner }
+    }
+
     /// Inserts a value into this scoped thread local storage slot for a
     /// duration of a closure.
     ///
@@ -186,7 +156,7 @@ impl<T> ScopedKey<T> {
         F: FnOnce() -> R,
     {
         struct Reset<'a, T: 'a> {
-            key: &'a __impl::KeyInner<T>,
+            key: &'a imp::KeyInner<T>,
             val: *mut T,
         }
                 impl<'a, T> Drop for Reset<'a, T> {
@@ -195,13 +165,14 @@ impl<T> ScopedKey<T> {
             }
         }
 
+        let inner = (self.inner)();
         let prev = unsafe {
-            let prev = self.inner.get();
-            self.inner.set(t as *const T as *mut T);
+            let prev = inner.get();
+            inner.set(t as *const T as *mut T);
             prev
         };
 
-        let _reset = Reset { key: &self.inner, val: prev };
+        let _reset = Reset { key: inner, val: prev };
         cb()
     }
 
@@ -228,7 +199,7 @@ impl<T> ScopedKey<T> {
         F: FnOnce(&T) -> R
     {
         unsafe {
-            let ptr = self.inner.get();
+            let ptr = (self.inner)().get();
             assert!(!ptr.is_null(), "cannot access a scoped thread local \
                                      variable without calling `set` first");
             cb(&*ptr)
@@ -237,7 +208,7 @@ impl<T> ScopedKey<T> {
 
     /// Test whether this TLS key has been `set` for the current thread.
     pub fn is_set(&'static self) -> bool {
-        unsafe { !self.inner.get().is_null() }
+        unsafe { !(self.inner)().get().is_null() }
     }
 }
 
@@ -247,20 +218,20 @@ impl<T> ScopedKey<T> {
               target_os = "openbsd",
               target_arch = "aarch64",
               no_elf_tls)))]
+#[doc(hidden)]
 mod imp {
-    use std::cell::UnsafeCell;
+    use std::cell::Cell;
 
-    #[doc(hidden)]
-    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
+    pub struct KeyInner<T> { inner: Cell<*mut T> }
 
     unsafe impl<T> ::marker::Sync for KeyInner<T> { }
 
-    #[doc(hidden)]
     impl<T> KeyInner<T> {
-        #[doc(hidden)]
-        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
-        #[doc(hidden)]
-        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
+        pub const fn new() -> KeyInner<T> {
+            KeyInner { inner: Cell::new(0 as *mut _) }
+        }
+        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr); }
+        pub unsafe fn get(&self) -> *mut T { self.inner.get() }
     }
 }
 
@@ -270,24 +241,29 @@ mod imp {
           target_os = "openbsd",
           target_arch = "aarch64",
           no_elf_tls))]
+#[doc(hidden)]
 mod imp {
+    use prelude::v1::*;
+
+    use cell::Cell;
     use marker;
-    use std::cell::Cell;
     use sys_common::thread_local::StaticKey as OsStaticKey;
 
-    #[doc(hidden)]
     pub struct KeyInner<T> {
         pub inner: OsStaticKey,
         pub marker: marker::PhantomData<Cell<T>>,
     }
 
-    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
+    unsafe impl<T> marker::Sync for KeyInner<T> { }
 
-    #[doc(hidden)]
     impl<T> KeyInner<T> {
-        #[doc(hidden)]
+        pub const fn new() -> KeyInner<T> {
+            KeyInner {
+                inner: OsStaticKey::new(None),
+                marker: marker::PhantomData
+            }
+        }
         pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
-        #[doc(hidden)]
         pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
     }
 }
index 6091794ed428660162d848512845e186a1b075a9..f1dc91f135fe5a60060faeaa116504c2100ec58a 100644 (file)
@@ -10,7 +10,8 @@
 
 // Because this module is temporary...
 #![allow(missing_docs)]
-#![unstable(feature = "std_misc")]
+#![unstable(feature = "thunk")]
+#![deprecated(since = "1.2.0", reason = "use FnBox instead")]
 
 use alloc::boxed::{Box, FnBox};
 use core::marker::Send;
index e00cb82649b7b6bb538948623d1f1215eafbcd6e..e844b206cc0a0c0937802d45fda711c9b98dbb47 100644 (file)
@@ -63,8 +63,10 @@ use owned_slice::OwnedSlice;
 use parse::token::{InternedString, str_to_ident};
 use parse::token;
 use parse::lexer;
+use print::pprust;
 use ptr::P;
 
+use std::cell::Cell;
 use std::fmt;
 use std::rc::Rc;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
@@ -200,14 +202,19 @@ impl Decodable for Ident {
 /// Function name (not all functions have names)
 pub type FnIdent = Option<Ident>;
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,
-           Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Lifetime {
     pub id: NodeId,
     pub span: Span,
     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))
+    }
+}
+
 /// A lifetime definition, eg `'a: 'b+'c+'d`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct LifetimeDef {
@@ -218,7 +225,7 @@ pub struct LifetimeDef {
 /// A "Path" is essentially Rust's notion of a name; for instance:
 /// std::cmp::PartialEq  .  It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Path {
     pub span: Span,
     /// A `::foo` path, is relative to the crate root rather than current
@@ -228,6 +235,18 @@ pub struct Path {
     pub segments: Vec<PathSegment>,
 }
 
+impl fmt::Debug for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "path({})", pprust::path_to_string(self))
+    }
+}
+
+impl fmt::Display for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", pprust::path_to_string(self))
+    }
+}
+
 /// A segment of a path: an identifier, an optional lifetime, and a set of
 /// types.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -358,12 +377,25 @@ pub type CrateNum = u32;
 pub type NodeId = u32;
 
 #[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
-           RustcDecodable, Hash, Debug, Copy)]
+           RustcDecodable, Hash, Copy)]
 pub struct DefId {
     pub krate: CrateNum,
     pub node: NodeId,
 }
 
+fn default_def_id_debug(_: DefId, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) }
+
+thread_local!(pub static DEF_ID_DEBUG: Cell<fn(DefId, &mut fmt::Formatter) -> fmt::Result> =
+                Cell::new(default_def_id_debug));
+
+impl fmt::Debug for DefId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "DefId {{ krate: {}, node: {} }}",
+                    self.krate, self.node));
+        DEF_ID_DEBUG.with(|def_id_debug| def_id_debug.get()(*self, f))
+    }
+}
+
 impl DefId {
     /// Read the node id, asserting that this def-id is krate-local.
     pub fn local_id(&self) -> NodeId {
@@ -539,13 +571,19 @@ pub struct Block {
     pub span: Span,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Pat {
     pub id: NodeId,
     pub node: Pat_,
     pub span: Span,
 }
 
+impl fmt::Debug for Pat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self))
+    }
+}
+
 /// A single field in a struct pattern
 ///
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
@@ -682,7 +720,16 @@ pub enum UnOp {
 /// A statement
 pub type Stmt = Spanned<Stmt_>;
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+impl fmt::Debug for Stmt {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "stmt({}: {})",
+               ast_util::stmt_id(self),
+               pprust::stmt_to_string(self))
+    }
+}
+
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub enum Stmt_ {
     /// Could be an item or a local (let) binding:
     StmtDecl(P<Decl>, NodeId),
@@ -695,7 +742,6 @@ pub enum Stmt_ {
 
     StmtMac(P<Mac>, MacStmtStyle),
 }
-
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum MacStmtStyle {
     /// The macro statement had a trailing semicolon, e.g. `foo! { ... };`
@@ -772,13 +818,19 @@ pub enum UnsafeSource {
 }
 
 /// An expression
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
 pub struct Expr {
     pub id: NodeId,
     pub node: Expr_,
     pub span: Span,
 }
 
+impl fmt::Debug for Expr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self))
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Expr_ {
     /// First expr is the place; second expr is the value.
@@ -1215,6 +1267,7 @@ pub struct TypeField {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MethodSig {
     pub unsafety: Unsafety,
+    pub constness: Constness,
     pub abi: Abi,
     pub decl: P<FnDecl>,
     pub generics: Generics,
@@ -1356,13 +1409,19 @@ pub struct TypeBinding {
 
 
 // NB PartialEq method appears below.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Ty {
     pub id: NodeId,
     pub node: Ty_,
     pub span: Span,
 }
 
+impl fmt::Debug for Ty {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "type({})", pprust::ty_to_string(self))
+    }
+}
+
 /// Not represented directly in the AST, referred to by name through a ty_path.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum PrimTy {
@@ -1475,6 +1534,12 @@ pub enum Unsafety {
     Normal,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Constness {
+    Const,
+    NotConst,
+}
+
 impl fmt::Display for Unsafety {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(match *self {
@@ -1761,7 +1826,7 @@ pub enum Item_ {
     /// A `const` item
     ItemConst(P<Ty>, P<Expr>),
     /// A function declaration
-    ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>),
+    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
     /// A module
     ItemMod(Mod),
     /// An external module
diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs
deleted file mode 100644 (file)
index 36a7f3a..0000000
+++ /dev/null
@@ -1,238 +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.
-
-//! This module provides a simplified abstraction for working with
-//! code blocks identified by their integer node-id.  In particular,
-//! it captures a common set of attributes that all "function-like
-//! things" (represented by `FnLike` instances) share.  For example,
-//! all `FnLike` instances have a type signature (be it explicit or
-//! inferred).  And all `FnLike` instances have a body, i.e. the code
-//! that is run when the function-like thing it represents is invoked.
-//!
-//! With the above abstraction in place, one can treat the program
-//! text as a collection of blocks of code (and most such blocks are
-//! nested within a uniquely determined `FnLike`), and users can ask
-//! for the `Code` associated with a particular NodeId.
-
-pub use self::Code::*;
-
-use abi;
-use ast::{Block, FnDecl, NodeId};
-use ast;
-use ast_map::Node;
-use ast_map;
-use codemap::Span;
-use visit;
-
-/// An FnLikeNode is a Node that is like a fn, in that it has a decl
-/// and a body (as well as a NodeId, a span, etc).
-///
-/// More specifically, it is one of either:
-///   - A function item,
-///   - A closure expr (i.e. an ExprClosure), or
-///   - The default implementation for a trait method.
-///
-/// To construct one, use the `Code::from_node` function.
-#[derive(Copy, Clone)]
-pub struct FnLikeNode<'a> { node: ast_map::Node<'a> }
-
-/// MaybeFnLike wraps a method that indicates if an object
-/// corresponds to some FnLikeNode.
-pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
-
-/// Components shared by fn-like things (fn items, methods, closures).
-pub struct FnParts<'a> {
-    pub decl: &'a FnDecl,
-    pub body: &'a Block,
-    pub kind: visit::FnKind<'a>,
-    pub span: Span,
-    pub id:   NodeId,
-}
-
-impl MaybeFnLike for ast::Item {
-    fn is_fn_like(&self) -> bool {
-        match self.node { ast::ItemFn(..) => true, _ => false, }
-    }
-}
-
-impl MaybeFnLike for ast::TraitItem {
-    fn is_fn_like(&self) -> bool {
-        match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, }
-    }
-}
-
-impl MaybeFnLike for ast::Expr {
-    fn is_fn_like(&self) -> bool {
-        match self.node {
-            ast::ExprClosure(..) => true,
-            _ => false,
-        }
-    }
-}
-
-/// Carries either an FnLikeNode or a Block, as these are the two
-/// constructs that correspond to "code" (as in, something from which
-/// we can construct a control-flow graph).
-#[derive(Copy, Clone)]
-pub enum Code<'a> {
-    FnLikeCode(FnLikeNode<'a>),
-    BlockCode(&'a Block),
-}
-
-impl<'a> Code<'a> {
-    pub fn id(&self) -> ast::NodeId {
-        match *self {
-            FnLikeCode(node) => node.id(),
-            BlockCode(block) => block.id,
-        }
-    }
-
-    /// Attempts to construct a Code from presumed FnLike or Block node input.
-    pub fn from_node(node: Node) -> Option<Code> {
-        fn new(node: Node) -> FnLikeNode { FnLikeNode { node: node } }
-        match node {
-            ast_map::NodeItem(item) if item.is_fn_like() =>
-                Some(FnLikeCode(new(node))),
-            ast_map::NodeTraitItem(tm) if tm.is_fn_like() =>
-                Some(FnLikeCode(new(node))),
-            ast_map::NodeImplItem(_) =>
-                Some(FnLikeCode(new(node))),
-            ast_map::NodeExpr(e) if e.is_fn_like() =>
-                Some(FnLikeCode(new(node))),
-            ast_map::NodeBlock(block) =>
-                Some(BlockCode(block)),
-            _ =>
-                None,
-        }
-    }
-}
-
-/// These are all the components one can extract from a fn item for
-/// use when implementing FnLikeNode operations.
-struct ItemFnParts<'a> {
-    ident:    ast::Ident,
-    decl:     &'a ast::FnDecl,
-    unsafety: ast::Unsafety,
-    abi:      abi::Abi,
-    vis:      ast::Visibility,
-    generics: &'a ast::Generics,
-    body:     &'a Block,
-    id:       ast::NodeId,
-    span:     Span
-}
-
-/// These are all the components one can extract from a closure expr
-/// for use when implementing FnLikeNode operations.
-struct ClosureParts<'a> {
-    decl: &'a FnDecl,
-    body: &'a Block,
-    id: NodeId,
-    span: Span
-}
-
-impl<'a> ClosureParts<'a> {
-    fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> {
-        ClosureParts { decl: d, body: b, id: id, span: s }
-    }
-}
-
-impl<'a> FnLikeNode<'a> {
-    pub fn to_fn_parts(self) -> FnParts<'a> {
-        FnParts {
-            decl: self.decl(),
-            body: self.body(),
-            kind: self.kind(),
-            span: self.span(),
-            id:   self.id(),
-        }
-    }
-
-    pub fn body(self) -> &'a Block {
-        self.handle(|i: ItemFnParts<'a>|  &*i.body,
-                    |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _|  body,
-                    |c: ClosureParts<'a>| c.body)
-    }
-
-    pub fn decl(self) -> &'a FnDecl {
-        self.handle(|i: ItemFnParts<'a>|  &*i.decl,
-                    |_, _, sig: &'a ast::MethodSig, _, _, _|  &sig.decl,
-                    |c: ClosureParts<'a>| c.decl)
-    }
-
-    pub fn span(self) -> Span {
-        self.handle(|i: ItemFnParts|     i.span,
-                    |_, _, _: &'a ast::MethodSig, _, _, span| span,
-                    |c: ClosureParts|    c.span)
-    }
-
-    pub fn id(self) -> NodeId {
-        self.handle(|i: ItemFnParts|     i.id,
-                    |id, _, _: &'a ast::MethodSig, _, _, _| id,
-                    |c: ClosureParts|    c.id)
-    }
-
-    pub fn kind(self) -> visit::FnKind<'a> {
-        let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> {
-            visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi, p.vis)
-        };
-        let closure = |_: ClosureParts| {
-            visit::FkFnBlock
-        };
-        let method = |_, ident, sig: &'a ast::MethodSig, vis, _, _| {
-            visit::FkMethod(ident, sig, vis)
-        };
-        self.handle(item, method, closure)
-    }
-
-    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
-        I: FnOnce(ItemFnParts<'a>) -> A,
-        M: FnOnce(NodeId,
-                  ast::Ident,
-                  &'a ast::MethodSig,
-                  Option<ast::Visibility>,
-                  &'a ast::Block,
-                  Span)
-                  -> A,
-        C: FnOnce(ClosureParts<'a>) -> A,
-    {
-        match self.node {
-            ast_map::NodeItem(i) => match i.node {
-                ast::ItemFn(ref decl, unsafety, abi, ref generics, ref block) =>
-                    item_fn(ItemFnParts{
-                        ident: i.ident, decl: &**decl, unsafety: unsafety, body: &**block,
-                        generics: generics, abi: abi, vis: i.vis, id: i.id, span: i.span
-                    }),
-                _ => panic!("item FnLikeNode that is not fn-like"),
-            },
-            ast_map::NodeTraitItem(ti) => match ti.node {
-                ast::MethodTraitItem(ref sig, Some(ref body)) => {
-                    method(ti.id, ti.ident, sig, None, body, ti.span)
-                }
-                _ => panic!("trait method FnLikeNode that is not fn-like"),
-            },
-            ast_map::NodeImplItem(ii) => {
-                match ii.node {
-                    ast::MethodImplItem(ref sig, ref body) => {
-                        method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
-                    }
-                    _ => {
-                        panic!("impl method FnLikeNode that is not fn-like")
-                    }
-                }
-            }
-            ast_map::NodeExpr(e) => match e.node {
-                ast::ExprClosure(_, ref decl, ref block) =>
-                    closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
-                _ => panic!("expr FnLikeNode that is not fn-like"),
-            },
-            _ => panic!("other FnLikeNode that is not fn-like"),
-        }
-    }
-}
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
deleted file mode 100644 (file)
index 795391d..0000000
+++ /dev/null
@@ -1,1013 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub use self::Node::*;
-pub use self::PathElem::*;
-use self::MapEntry::*;
-
-use abi;
-use ast::*;
-use ast_util;
-use codemap::{DUMMY_SP, Span, Spanned};
-use fold::Folder;
-use parse::token;
-use print::pprust;
-use visit::{self, Visitor};
-
-use arena::TypedArena;
-use std::cell::RefCell;
-use std::fmt;
-use std::io;
-use std::iter::{self, repeat};
-use std::mem;
-use std::slice;
-
-pub mod blocks;
-
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub enum PathElem {
-    PathMod(Name),
-    PathName(Name)
-}
-
-impl PathElem {
-    pub fn name(&self) -> Name {
-        match *self {
-            PathMod(name) | PathName(name) => name
-        }
-    }
-}
-
-impl fmt::Display for PathElem {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let slot = token::get_name(self.name());
-        write!(f, "{}", slot)
-    }
-}
-
-#[derive(Clone)]
-pub struct LinkedPathNode<'a> {
-    node: PathElem,
-    next: LinkedPath<'a>,
-}
-
-#[derive(Copy, Clone)]
-pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>);
-
-impl<'a> LinkedPath<'a> {
-    pub fn empty() -> LinkedPath<'a> {
-        LinkedPath(None)
-    }
-
-    pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> {
-        LinkedPath(Some(node))
-    }
-}
-
-impl<'a> Iterator for LinkedPath<'a> {
-    type Item = PathElem;
-
-    fn next(&mut self) -> Option<PathElem> {
-        match self.0 {
-            Some(node) => {
-                *self = node.next;
-                Some(node.node)
-            }
-            None => None
-        }
-    }
-}
-
-/// The type of the iterator used by with_path.
-pub type PathElems<'a, 'b> = iter::Chain<iter::Cloned<slice::Iter<'a, PathElem>>, LinkedPath<'b>>;
-
-pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
-    let itr = token::get_ident_interner();
-
-    path.fold(String::new(), |mut s, e| {
-        let e = itr.get(e.name());
-        if !s.is_empty() {
-            s.push_str("::");
-        }
-        s.push_str(&e[..]);
-        s
-    })
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum Node<'ast> {
-    NodeItem(&'ast Item),
-    NodeForeignItem(&'ast ForeignItem),
-    NodeTraitItem(&'ast TraitItem),
-    NodeImplItem(&'ast ImplItem),
-    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),
-
-    NodeLifetime(&'ast Lifetime),
-}
-
-/// Represents an entry and its parent Node ID
-/// The odd layout is to bring down the total size.
-#[derive(Copy, Debug)]
-enum MapEntry<'ast> {
-    /// Placeholder for holes in the map.
-    NotPresent,
-
-    /// All the node types, with a parent ID.
-    EntryItem(NodeId, &'ast Item),
-    EntryForeignItem(NodeId, &'ast ForeignItem),
-    EntryTraitItem(NodeId, &'ast TraitItem),
-    EntryImplItem(NodeId, &'ast ImplItem),
-    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),
-    EntryLifetime(NodeId, &'ast Lifetime),
-
-    /// Roots for node trees.
-    RootCrate,
-    RootInlinedParent(&'ast InlinedParent)
-}
-
-impl<'ast> Clone for MapEntry<'ast> {
-    fn clone(&self) -> MapEntry<'ast> {
-        *self
-    }
-}
-
-#[derive(Debug)]
-struct InlinedParent {
-    path: Vec<PathElem>,
-    ii: InlinedItem
-}
-
-impl<'ast> MapEntry<'ast> {
-    fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
-        match node {
-            NodeItem(n) => EntryItem(p, n),
-            NodeForeignItem(n) => EntryForeignItem(p, n),
-            NodeTraitItem(n) => EntryTraitItem(p, n),
-            NodeImplItem(n) => EntryImplItem(p, n),
-            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),
-            NodeStructCtor(n) => EntryStructCtor(p, n),
-            NodeLifetime(n) => EntryLifetime(p, n)
-        }
-    }
-
-    fn parent(self) -> Option<NodeId> {
-        Some(match self {
-            EntryItem(id, _) => id,
-            EntryForeignItem(id, _) => id,
-            EntryTraitItem(id, _) => id,
-            EntryImplItem(id, _) => id,
-            EntryVariant(id, _) => id,
-            EntryExpr(id, _) => id,
-            EntryStmt(id, _) => id,
-            EntryArg(id, _) => id,
-            EntryLocal(id, _) => id,
-            EntryPat(id, _) => id,
-            EntryBlock(id, _) => id,
-            EntryStructCtor(id, _) => id,
-            EntryLifetime(id, _) => id,
-            _ => return None
-        })
-    }
-
-    fn to_node(self) -> Option<Node<'ast>> {
-        Some(match self {
-            EntryItem(_, n) => NodeItem(n),
-            EntryForeignItem(_, n) => NodeForeignItem(n),
-            EntryTraitItem(_, n) => NodeTraitItem(n),
-            EntryImplItem(_, n) => NodeImplItem(n),
-            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),
-            EntryStructCtor(_, n) => NodeStructCtor(n),
-            EntryLifetime(_, n) => NodeLifetime(n),
-            _ => return None
-        })
-    }
-}
-
-/// Stores a crate and any number of inlined items from other crates.
-pub struct Forest {
-    krate: Crate,
-    inlined_items: TypedArena<InlinedParent>
-}
-
-impl Forest {
-    pub fn new(krate: Crate) -> Forest {
-        Forest {
-            krate: krate,
-            inlined_items: TypedArena::new()
-        }
-    }
-
-    pub fn krate<'ast>(&'ast self) -> &'ast Crate {
-        &self.krate
-    }
-}
-
-/// Represents a mapping from Node IDs to AST elements and their parent
-/// Node IDs
-pub struct Map<'ast> {
-    /// The backing storage for all the AST nodes.
-    forest: &'ast Forest,
-
-    /// NodeIds are sequential integers from 0, so we can be
-    /// super-compact by storing them in a vector. Not everything with
-    /// a NodeId is in the map, but empirically the occupancy is about
-    /// 75-80%, so there's not too much overhead (certainly less than
-    /// a hashmap, since they (at the time of writing) have a maximum
-    /// of 75% occupancy).
-    ///
-    /// Also, indexing is pretty quick when you've got a vector and
-    /// plain old integers.
-    map: RefCell<Vec<MapEntry<'ast>>>
-}
-
-impl<'ast> Map<'ast> {
-    fn entry_count(&self) -> usize {
-        self.map.borrow().len()
-    }
-
-    fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
-        self.map.borrow().get(id as usize).cloned()
-    }
-
-    pub fn krate(&self) -> &'ast Crate {
-        &self.forest.krate
-    }
-
-    /// Retrieve the Node corresponding to `id`, panicking if it cannot
-    /// be found.
-    pub fn get(&self, id: NodeId) -> Node<'ast> {
-        match self.find(id) {
-            Some(node) => node,
-            None => panic!("couldn't find node id {} in the AST map", id)
-        }
-    }
-
-    /// Retrieve the Node corresponding to `id`, returning None if
-    /// cannot be found.
-    pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
-        self.find_entry(id).and_then(|x| x.to_node())
-    }
-
-    /// Retrieve the parent NodeId for `id`, or `id` itself if no
-    /// parent is registered in this map.
-    pub fn get_parent(&self, id: NodeId) -> NodeId {
-        self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
-    }
-
-    pub fn get_parent_did(&self, id: NodeId) -> DefId {
-        let parent = self.get_parent(id);
-        match self.find_entry(parent) {
-            Some(RootInlinedParent(&InlinedParent {ii: IITraitItem(did, _), ..})) => did,
-            Some(RootInlinedParent(&InlinedParent {ii: IIImplItem(did, _), ..})) => did,
-            _ => ast_util::local_def(parent)
-        }
-    }
-
-    pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi {
-        let parent = self.get_parent(id);
-        let abi = match self.find_entry(parent) {
-            Some(EntryItem(_, i)) => {
-                match i.node {
-                    ItemForeignMod(ref nm) => Some(nm.abi),
-                    _ => None
-                }
-            }
-            /// Wrong but OK, because the only inlined foreign items are intrinsics.
-            Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic),
-            _ => None
-        };
-        match abi {
-            Some(abi) => abi,
-            None => panic!("expected foreign mod or inlined parent, found {}",
-                          self.node_to_string(parent))
-        }
-    }
-
-    pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
-        let vis = self.expect_foreign_item(id).vis;
-        match self.find(self.get_parent(id)) {
-            Some(NodeItem(i)) => vis.inherit_from(i.vis),
-            _ => vis
-        }
-    }
-
-    pub fn expect_item(&self, id: NodeId) -> &'ast Item {
-        match self.find(id) {
-            Some(NodeItem(item)) => item,
-            _ => panic!("expected item, found {}", self.node_to_string(id))
-        }
-    }
-
-    pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
-        match self.find(id) {
-            Some(NodeItem(i)) => {
-                match i.node {
-                    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"),
-                }
-            }
-            _ => panic!(format!("expected struct, found {}", self.node_to_string(id))),
-        }
-    }
-
-    pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
-        match self.find(id) {
-            Some(NodeVariant(variant)) => variant,
-            _ => panic!(format!("expected variant, found {}", self.node_to_string(id))),
-        }
-    }
-
-    pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem {
-        match self.find(id) {
-            Some(NodeForeignItem(item)) => item,
-            _ => panic!("expected foreign item, found {}", self.node_to_string(id))
-        }
-    }
-
-    pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
-        match self.find(id) {
-            Some(NodeExpr(expr)) => expr,
-            _ => panic!("expected expr, found {}", self.node_to_string(id))
-        }
-    }
-
-    /// returns the name associated with the given NodeId's AST
-    pub fn get_path_elem(&self, id: NodeId) -> PathElem {
-        let node = self.get(id);
-        match node {
-            NodeItem(item) => {
-                match item.node {
-                    ItemMod(_) | ItemForeignMod(_) => {
-                        PathMod(item.ident.name)
-                    }
-                    _ => PathName(item.ident.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),
-            _ => panic!("no path elem for {:?}", node)
-        }
-    }
-
-    pub fn with_path<T, F>(&self, id: NodeId, f: F) -> T where
-        F: FnOnce(PathElems) -> T,
-    {
-        self.with_path_next(id, LinkedPath::empty(), f)
-    }
-
-    pub fn path_to_string(&self, id: NodeId) -> String {
-        self.with_path(id, |path| path_to_string(path))
-    }
-
-    fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String {
-        self.with_path(id, |path| {
-            path_to_string(path.chain(Some(PathName(i.name)).into_iter()))
-        })
-    }
-
-    fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
-        F: FnOnce(PathElems) -> T,
-    {
-        let parent = self.get_parent(id);
-        let parent = match self.find_entry(id) {
-            Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => {
-                // Anonymous extern items, enum variants and struct ctors
-                // go in the parent scope.
-                self.get_parent(parent)
-            }
-            // But tuple struct ctors don't have names, so use the path of its
-            // parent, the struct item. Similarly with closure expressions.
-            Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
-                return self.with_path_next(parent, next, f);
-            }
-            _ => parent
-        };
-        if parent == id {
-            match self.find_entry(id) {
-                Some(RootInlinedParent(data)) => {
-                    f(data.path.iter().cloned().chain(next))
-                }
-                _ => f([].iter().cloned().chain(next))
-            }
-        } else {
-            self.with_path_next(parent, LinkedPath::from(&LinkedPathNode {
-                node: self.get_path_elem(id),
-                next: next
-            }), f)
-        }
-    }
-
-    /// Given a node ID, get a list of of attributes associated with the AST
-    /// corresponding to the Node ID
-    pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] {
-        let attrs = match self.find(id) {
-            Some(NodeItem(i)) => Some(&i.attrs[..]),
-            Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
-            Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
-            Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
-            Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
-            // unit/tuple structs take the attributes straight from
-            // the struct definition.
-            Some(NodeStructCtor(_)) => {
-                return self.attrs(self.get_parent(id));
-            }
-            _ => None
-        };
-        attrs.unwrap_or(&[])
-    }
-
-    /// Returns an iterator that yields the node id's with paths that
-    /// match `parts`.  (Requires `parts` is non-empty.)
-    ///
-    /// For example, if given `parts` equal to `["bar", "quux"]`, then
-    /// the iterator will produce node id's for items with paths
-    /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
-    /// any other such items it can find in the map.
-    pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
-                                 -> NodesMatchingSuffix<'a, 'ast> {
-        NodesMatchingSuffix {
-            map: self,
-            item_name: parts.last().unwrap(),
-            in_which: &parts[..parts.len() - 1],
-            idx: 0,
-        }
-    }
-
-    pub fn opt_span(&self, id: NodeId) -> Option<Span> {
-        let sp = match self.find(id) {
-            Some(NodeItem(item)) => item.span,
-            Some(NodeForeignItem(foreign_item)) => foreign_item.span,
-            Some(NodeTraitItem(trait_method)) => trait_method.span,
-            Some(NodeImplItem(ref impl_item)) => impl_item.span,
-            Some(NodeVariant(variant)) => variant.span,
-            Some(NodeExpr(expr)) => expr.span,
-            Some(NodeStmt(stmt)) => stmt.span,
-            Some(NodeArg(pat)) | 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,
-            _ => return None,
-        };
-        Some(sp)
-    }
-
-    pub fn span(&self, id: NodeId) -> Span {
-        self.opt_span(id)
-            .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
-    }
-
-    pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
-        if def_id.krate == LOCAL_CRATE {
-            self.opt_span(def_id.node).unwrap_or(fallback)
-        } else {
-            fallback
-        }
-    }
-
-    pub fn node_to_string(&self, id: NodeId) -> String {
-        node_id_to_string(self, id, true)
-    }
-
-    pub fn node_to_user_string(&self, id: NodeId) -> String {
-        node_id_to_string(self, id, false)
-    }
-}
-
-pub struct NodesMatchingSuffix<'a, 'ast:'a> {
-    map: &'a Map<'ast>,
-    item_name: &'a String,
-    in_which: &'a [String],
-    idx: NodeId,
-}
-
-impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> {
-    /// Returns true only if some suffix of the module path for parent
-    /// matches `self.in_which`.
-    ///
-    /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
-    /// returns true if parent's path ends with the suffix
-    /// `x_0::x_1::...::x_k`.
-    fn suffix_matches(&self, parent: NodeId) -> bool {
-        let mut cursor = parent;
-        for part in self.in_which.iter().rev() {
-            let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
-                None => return false,
-                Some((node_id, name)) => (node_id, name),
-            };
-            if &part[..] != mod_name.as_str() {
-                return false;
-            }
-            cursor = self.map.get_parent(mod_id);
-        }
-        return true;
-
-        // Finds the first mod in parent chain for `id`, along with
-        // that mod's name.
-        //
-        // If `id` itself is a mod named `m` with parent `p`, then
-        // returns `Some(id, m, p)`.  If `id` has no mod in its parent
-        // chain, then returns `None`.
-        fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> {
-            loop {
-                match map.find(id) {
-                    None => return None,
-                    Some(NodeItem(item)) if item_is_mod(&*item) =>
-                        return Some((id, item.ident.name)),
-                    _ => {}
-                }
-                let parent = map.get_parent(id);
-                if parent == id { return None }
-                id = parent;
-            }
-
-            fn item_is_mod(item: &Item) -> bool {
-                match item.node {
-                    ItemMod(_) => true,
-                    _ => false,
-                }
-            }
-        }
-    }
-
-    // We are looking at some node `n` with a given name and parent
-    // id; do their names match what I am seeking?
-    fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool {
-        name.as_str() == &self.item_name[..] &&
-            self.suffix_matches(parent_of_n)
-    }
-}
-
-impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
-    type Item = NodeId;
-
-    fn next(&mut self) -> Option<NodeId> {
-        loop {
-            let idx = self.idx;
-            if idx as usize >= self.map.entry_count() {
-                return None;
-            }
-            self.idx += 1;
-            let (p, name) = match self.map.find_entry(idx) {
-                Some(EntryItem(p, n))       => (p, n.name()),
-                Some(EntryForeignItem(p, n))=> (p, n.name()),
-                Some(EntryTraitItem(p, n))  => (p, n.name()),
-                Some(EntryImplItem(p, n))   => (p, n.name()),
-                Some(EntryVariant(p, n))    => (p, n.name()),
-                _ => continue,
-            };
-            if self.matches_names(p, name) {
-                return Some(idx)
-            }
-        }
-    }
-}
-
-trait Named {
-    fn name(&self) -> Name;
-}
-
-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 } }
-
-pub trait FoldOps {
-    fn new_id(&self, id: NodeId) -> NodeId {
-        id
-    }
-    fn new_def_id(&self, def_id: DefId) -> DefId {
-        def_id
-    }
-    fn new_span(&self, span: Span) -> Span {
-        span
-    }
-}
-
-/// A Folder that updates IDs and Span's according to fold_ops.
-struct IdAndSpanUpdater<F> {
-    fold_ops: F
-}
-
-impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
-    fn new_id(&mut self, id: NodeId) -> NodeId {
-        self.fold_ops.new_id(id)
-    }
-
-    fn new_span(&mut self, span: Span) -> Span {
-        self.fold_ops.new_span(span)
-    }
-}
-
-/// A Visitor that walks over an AST and collects Node's into an AST Map.
-struct NodeCollector<'ast> {
-    map: Vec<MapEntry<'ast>>,
-    /// The node in which we are currently mapping (an item or a method).
-    parent: 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);
-        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 = self.parent;
-        self.parent = 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 {
-                    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));
-                }
-            }
-            _ => {}
-        }
-        visit::walk_item(self, i);
-        self.parent = parent;
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let parent = self.parent;
-        self.parent = ti.id;
-        visit::walk_trait_item(self, ti);
-        self.parent = parent;
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let parent = self.parent;
-        self.parent = ii.id;
-        visit::walk_impl_item(self, ii);
-        self.parent = parent;
-    }
-
-    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)
-        });
-        visit::walk_pat(self, pat);
-    }
-
-    fn visit_expr(&mut self, expr: &'ast Expr) {
-        self.insert(expr.id, NodeExpr(expr));
-        visit::walk_expr(self, expr);
-    }
-
-    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
-        visit::walk_stmt(self, stmt);
-    }
-
-    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: &'ast Block, s: Span, _: NodeId) {
-        self.visit_fn_decl(fd);
-        visit::walk_fn(self, fk, fd, b, s);
-    }
-
-    fn visit_ty(&mut self, ty: &'ast Ty) {
-        match ty.node {
-            TyBareFn(ref fd) => {
-                self.visit_fn_decl(&*fd.decl);
-            }
-            _ => {}
-        }
-        visit::walk_ty(self, ty);
-    }
-
-    fn visit_block(&mut self, block: &'ast Block) {
-        self.insert(block.id, NodeBlock(block));
-        visit::walk_block(self, block);
-    }
-
-    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, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map<'ast> {
-    // Replace the crate with an empty one to take it out.
-    let krate = mem::replace(&mut forest.krate, Crate {
-        module: Mod {
-            inner: DUMMY_SP,
-            items: vec![],
-        },
-        attrs: vec![],
-        config: vec![],
-        exported_macros: vec![],
-        span: DUMMY_SP
-    });
-    forest.krate = IdAndSpanUpdater { fold_ops: fold_ops }.fold_crate(krate);
-
-    let mut collector = NodeCollector {
-        map: vec![],
-        parent: CRATE_NODE_ID
-    };
-    collector.insert_entry(CRATE_NODE_ID, RootCrate);
-    visit::walk_crate(&mut collector, &forest.krate);
-    let map = collector.map;
-
-    if log_enabled!(::log::DEBUG) {
-        // This only makes sense for ordered stores; note the
-        // enumerate to count the number of entries.
-        let (entries_less_1, _) = map.iter().filter(|&x| {
-            match *x {
-                NotPresent => false,
-                _ => true
-            }
-        }).enumerate().last().expect("AST map was empty after folding?");
-
-        let entries = entries_less_1 + 1;
-        let vector_length = map.len();
-        debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
-              entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
-    }
-
-    Map {
-        forest: forest,
-        map: RefCell::new(map)
-    }
-}
-
-/// Used for items loaded from external crate that are being inlined into this
-/// crate.  The `path` should be the path to the item but should not include
-/// the item itself.
-pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
-                                          path: Vec<PathElem>,
-                                          ii: InlinedItem,
-                                          fold_ops: F)
-                                          -> &'ast InlinedItem {
-    let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
-    let ii = match ii {
-        IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")),
-        IITraitItem(d, ti) => {
-            IITraitItem(fld.fold_ops.new_def_id(d),
-                        fld.fold_trait_item(ti).expect_one("expected one trait item"))
-        }
-        IIImplItem(d, ii) => {
-            IIImplItem(fld.fold_ops.new_def_id(d),
-                       fld.fold_impl_item(ii).expect_one("expected one impl item"))
-        }
-        IIForeign(i) => IIForeign(fld.fold_foreign_item(i))
-    };
-
-    let ii_parent = map.forest.inlined_items.alloc(InlinedParent {
-        path: path,
-        ii: ii
-    });
-
-    let mut collector = NodeCollector {
-        map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
-        parent: fld.new_id(DUMMY_NODE_ID)
-    };
-    let ii_parent_id = collector.parent;
-    collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
-    visit::walk_inlined_item(&mut collector, &ii_parent.ii);
-
-    // 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 {
-        IIItem(_) => {}
-        IITraitItem(_, ref ti) => {
-            collector.insert(ti.id, NodeTraitItem(ti));
-        }
-        IIImplItem(_, ref ii) => {
-            collector.insert(ii.id, NodeImplItem(ii));
-        }
-        IIForeign(ref i) => {
-            collector.insert(i.id, NodeForeignItem(i));
-        }
-    }
-    *map.map.borrow_mut() = collector.map;
-    &ii_parent.ii
-}
-
-pub trait NodePrinter {
-    fn print_node(&mut self, node: &Node) -> io::Result<()>;
-}
-
-impl<'a> NodePrinter for pprust::State<'a> {
-    fn print_node(&mut self, node: &Node) -> io::Result<()> {
-        match *node {
-            NodeItem(a)        => self.print_item(&*a),
-            NodeForeignItem(a) => self.print_foreign_item(&*a),
-            NodeTraitItem(a)   => self.print_trait_item(a),
-            NodeImplItem(a)    => self.print_impl_item(a),
-            NodeVariant(a)     => self.print_variant(&*a),
-            NodeExpr(a)        => self.print_expr(&*a),
-            NodeStmt(a)        => self.print_stmt(&*a),
-            NodePat(a)         => self.print_pat(&*a),
-            NodeBlock(a)       => self.print_block(&*a),
-            NodeLifetime(a)    => self.print_lifetime(&*a),
-
-            // these cases do not carry enough information in the
-            // 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"),
-        }
-    }
-}
-
-fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
-    let id_str = format!(" (id={})", id);
-    let id_str = if include_id { &id_str[..] } else { "" };
-
-    match map.find(id) {
-        Some(NodeItem(item)) => {
-            let path_str = map.path_to_str_with_ident(id, item.ident);
-            let item_str = match item.node {
-                ItemExternCrate(..) => "extern crate",
-                ItemUse(..) => "use",
-                ItemStatic(..) => "static",
-                ItemConst(..) => "const",
-                ItemFn(..) => "fn",
-                ItemMod(..) => "mod",
-                ItemForeignMod(..) => "foreign mod",
-                ItemTy(..) => "ty",
-                ItemEnum(..) => "enum",
-                ItemStruct(..) => "struct",
-                ItemTrait(..) => "trait",
-                ItemImpl(..) => "impl",
-                ItemDefaultImpl(..) => "default impl",
-                ItemMac(..) => "macro"
-            };
-            format!("{} {}{}", item_str, path_str, id_str)
-        }
-        Some(NodeForeignItem(item)) => {
-            let path_str = map.path_to_str_with_ident(id, item.ident);
-            format!("foreign item {}{}", path_str, id_str)
-        }
-        Some(NodeImplItem(ii)) => {
-            match ii.node {
-                ConstImplItem(..) => {
-                    format!("assoc const {} in {}{}",
-                            token::get_ident(ii.ident),
-                            map.path_to_string(id),
-                            id_str)
-                }
-                MethodImplItem(..) => {
-                    format!("method {} in {}{}",
-                            token::get_ident(ii.ident),
-                            map.path_to_string(id), id_str)
-                }
-                TypeImplItem(_) => {
-                    format!("assoc type {} in {}{}",
-                            token::get_ident(ii.ident),
-                            map.path_to_string(id),
-                            id_str)
-                }
-                MacImplItem(ref mac) => {
-                    format!("method macro {}{}",
-                            pprust::mac_to_string(mac), id_str)
-                }
-            }
-        }
-        Some(NodeTraitItem(ti)) => {
-            let kind = match ti.node {
-                ConstTraitItem(..) => "assoc constant",
-                MethodTraitItem(..) => "trait method",
-                TypeTraitItem(..) => "assoc type",
-            };
-
-            format!("{} {} in {}{}",
-                    kind,
-                    token::get_ident(ti.ident),
-                    map.path_to_string(id),
-                    id_str)
-        }
-        Some(NodeVariant(ref variant)) => {
-            format!("variant {} in {}{}",
-                    token::get_ident(variant.node.name),
-                    map.path_to_string(id), id_str)
-        }
-        Some(NodeExpr(ref expr)) => {
-            format!("expr {}{}", pprust::expr_to_string(&**expr), id_str)
-        }
-        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)
-        }
-        Some(NodePat(ref pat)) => {
-            format!("pat {}{}", pprust::pat_to_string(&**pat), id_str)
-        }
-        Some(NodeBlock(ref block)) => {
-            format!("block {}{}", pprust::block_to_string(&**block), id_str)
-        }
-        Some(NodeStructCtor(_)) => {
-            format!("struct_ctor {}{}", map.path_to_string(id), id_str)
-        }
-        Some(NodeLifetime(ref l)) => {
-            format!("lifetime {}{}",
-                    pprust::lifetime_to_string(&**l), id_str)
-        }
-        None => {
-            format!("unknown node{}", id_str)
-        }
-    }
-}
index 8471fef3487e62f53af6d48d68eaab0fa040d444..7d7ea371ba5339e52e6de84dd70e849d89c4b50d 100644 (file)
@@ -330,7 +330,7 @@ pub struct IdVisitor<'a, O:'a> {
 
 impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
     fn visit_generics_helper(&mut self, generics: &Generics) {
-        for type_parameter in &*generics.ty_params {
+        for type_parameter in generics.ty_params.iter() {
             self.operation.visit_id(type_parameter.id)
         }
         for lifetime in &generics.lifetimes {
@@ -440,7 +440,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
         self.operation.visit_id(node_id);
 
         match function_kind {
-            visit::FkItemFn(_, generics, _, _, _) => {
+            visit::FkItemFn(_, generics, _, _, _, _) => {
                 self.visit_generics_helper(generics)
             }
             visit::FkMethod(_, sig, _) => {
@@ -615,7 +615,7 @@ pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool {
 // are two arrays of segments equal when compared unhygienically?
 pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> bool {
     a.len() == b.len() &&
-    a.iter().zip(b.iter()).all(|(s, t)| {
+    a.iter().zip(b).all(|(s, t)| {
         s.identifier.name == t.identifier.name &&
         // FIXME #7743: ident -> name problems in lifetime comparison?
         // can types contain idents?
index 755dd3bb4586fd72dae9b893a04d04ce8b09234e..aa3ec03ee942b73f8c9bf552b5396317ead8511b 100644 (file)
@@ -366,7 +366,7 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me
 }
 
 /// Represents the #[deprecated] and friends attributes.
-#[derive(RustcEncodable,RustcDecodable,Clone,Debug)]
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: InternedString,
@@ -378,7 +378,7 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Debug,Copy)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
 pub enum StabilityLevel {
     Unstable,
     Stable,
@@ -414,7 +414,7 @@ fn find_stability_generic<'a,
                 let mut feature = None;
                 let mut since = None;
                 let mut reason = None;
-                for meta in metas.iter() {
+                for meta in metas {
                     if meta.name() == "feature" {
                         match meta.value_str() {
                             Some(v) => feature = Some(v),
index ef9b14739a5ed188f15fc05f97d77faf1ebd61ef..5ddcfaef9ea286e5261faa12f21e045eef7e72b8 100644 (file)
 
 pub use self::ExpnFormat::*;
 
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
 use std::ops::{Add, Sub};
+use std::path::Path;
 use std::rc::Rc;
 
-use std::fmt;
+use std::{fmt, fs};
+use std::io::{self, Read};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -113,7 +115,7 @@ impl Sub for CharPos {
 /// are *absolute* positions from the beginning of the codemap, not positions
 /// relative to FileMaps. Methods on the CodeMap can be used to relate spans back
 /// to the original source.
-#[derive(Clone, Copy, Debug, Hash)]
+#[derive(Clone, Copy, Hash)]
 pub struct Span {
     pub lo: BytePos,
     pub hi: BytePos,
@@ -162,6 +164,20 @@ impl Decodable for Span {
     }
 }
 
+fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result {
+    write!(f, "Span {{ lo: {:?}, hi: {:?}, expn_id: {:?} }}",
+           span.lo, span.hi, span.expn_id)
+}
+
+thread_local!(pub static SPAN_DEBUG: Cell<fn(Span, &mut fmt::Formatter) -> fmt::Result> =
+                Cell::new(default_span_debug));
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        SPAN_DEBUG.with(|span_debug| span_debug.get()(*self, f))
+    }
+}
+
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> Spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
@@ -522,6 +538,29 @@ impl FileMap {
     }
 }
 
+/// An abstraction over the fs operations used by the Parser.
+pub trait FileLoader {
+    /// Query the existence of a file.
+    fn file_exists(&self, path: &Path) -> bool;
+
+    /// Read the contents of an UTF-8 file into memory.
+    fn read_file(&self, path: &Path) -> io::Result<String>;
+}
+
+/// A FileLoader that uses std::fs to load real files.
+pub struct RealFileLoader;
+
+impl FileLoader for RealFileLoader {
+    fn file_exists(&self, path: &Path) -> bool {
+        fs::metadata(path).is_ok()
+    }
+
+    fn read_file(&self, path: &Path) -> io::Result<String> {
+        let mut src = String::new();
+        try!(try!(fs::File::open(path)).read_to_string(&mut src));
+        Ok(src)
+    }
+}
 
 // _____________________________________________________________________________
 // CodeMap
@@ -529,7 +568,8 @@ impl FileMap {
 
 pub struct CodeMap {
     pub files: RefCell<Vec<Rc<FileMap>>>,
-    expansions: RefCell<Vec<ExpnInfo>>
+    expansions: RefCell<Vec<ExpnInfo>>,
+    file_loader: Box<FileLoader>
 }
 
 impl CodeMap {
@@ -537,9 +577,27 @@ impl CodeMap {
         CodeMap {
             files: RefCell::new(Vec::new()),
             expansions: RefCell::new(Vec::new()),
+            file_loader: Box::new(RealFileLoader)
+        }
+    }
+
+    pub fn with_file_loader(file_loader: Box<FileLoader>) -> CodeMap {
+        CodeMap {
+            files: RefCell::new(Vec::new()),
+            expansions: RefCell::new(Vec::new()),
+            file_loader: file_loader
         }
     }
 
+    pub fn file_exists(&self, path: &Path) -> bool {
+        self.file_loader.file_exists(path)
+    }
+
+    pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
+        let src = try!(self.file_loader.read_file(path));
+        Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
+    }
+
     pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
         let mut files = self.files.borrow_mut();
         let start_pos = match files.last() {
@@ -779,7 +837,7 @@ impl CodeMap {
     }
 
     pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> {
-        for fm in &*self.files.borrow() {
+        for fm in self.files.borrow().iter() {
             if filename == fm.name {
                 return fm.clone();
             }
@@ -804,7 +862,7 @@ impl CodeMap {
         // The number of extra bytes due to multibyte chars in the FileMap
         let mut total_extra_bytes = 0;
 
-        for mbc in &*map.multibyte_chars.borrow() {
+        for mbc in map.multibyte_chars.borrow().iter() {
             debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
             if mbc.pos < bpos {
                 // every character is at least one byte, so we only
index 0097bab2fea4d444593c38d366eafb8967cf7fbd..14dd9978b876af891ab2bb5bf4886365b7933eba 100644 (file)
@@ -122,6 +122,12 @@ pub struct SpanHandler {
 }
 
 impl SpanHandler {
+    pub fn new(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
+        SpanHandler {
+            handler: handler,
+            cm: cm,
+        }
+    }
     pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
         self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
         return FatalError;
@@ -187,6 +193,19 @@ pub struct Handler {
 }
 
 impl Handler {
+    pub fn new(color_config: ColorConfig,
+               registry: Option<diagnostics::registry::Registry>,
+               can_emit_warnings: bool) -> Handler {
+        let emitter = Box::new(EmitterWriter::stderr(color_config, registry));
+        Handler::with_emitter(can_emit_warnings, emitter)
+    }
+    pub fn with_emitter(can_emit_warnings: bool, e: Box<Emitter + Send>) -> Handler {
+        Handler {
+            err_count: Cell::new(0),
+            emit: RefCell::new(e),
+            can_emit_warnings: can_emit_warnings
+        }
+    }
     pub fn fatal(&self, msg: &str) -> ! {
         self.emit.borrow_mut().emit(None, msg, None, Fatal);
         panic!(FatalError);
@@ -254,27 +273,6 @@ impl Handler {
     }
 }
 
-pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
-    SpanHandler {
-        handler: handler,
-        cm: cm,
-    }
-}
-
-pub fn default_handler(color_config: ColorConfig,
-                       registry: Option<diagnostics::registry::Registry>,
-                       can_emit_warnings: bool) -> Handler {
-    mk_handler(can_emit_warnings, Box::new(EmitterWriter::stderr(color_config, registry)))
-}
-
-pub fn mk_handler(can_emit_warnings: bool, e: Box<Emitter + Send>) -> Handler {
-    Handler {
-        err_count: Cell::new(0),
-        emit: RefCell::new(e),
-        can_emit_warnings: can_emit_warnings
-    }
-}
-
 #[derive(Copy, PartialEq, Clone, Debug)]
 pub enum Level {
     Bug,
@@ -597,7 +595,7 @@ fn highlight_lines(err: &mut EmitterWriter,
     let display_line_strings = &line_strings[..display_lines];
 
     // Print the offending lines
-    for (line_info, line) in display_line_infos.iter().zip(display_line_strings.iter()) {
+    for (line_info, line) in display_line_infos.iter().zip(display_line_strings) {
         try!(write!(&mut err.dst, "{}:{} {}\n",
                     fm.name,
                     line_info.line_index + 1,
index 6cb4f70b8607aceb3867e108f1277c6553778cfb..e988b74cb3d1d3ceedbefc4f179d87718a564069 100644 (file)
 //! currently always a crate name.
 
 use std::collections::BTreeMap;
-use std::env;
 use std::path::PathBuf;
-use std::fs::{read_dir, create_dir_all, OpenOptions, File};
-use std::io::{Read, Write};
+use std::fs::{remove_file, create_dir_all, File};
+use std::io::Write;
 use std::error::Error;
-use rustc_serialize::json::{self, as_json};
+use rustc_serialize::json::as_json;
 
 use codemap::Span;
 use ext::base::ExtCtxt;
 use diagnostics::plugin::{ErrorMap, ErrorInfo};
 
-pub use self::Uniqueness::*;
-
 // Default metadata directory to use for extended error JSON.
-const ERROR_METADATA_DIR_DEFAULT: &'static str = "tmp/extended-errors";
-
-// The name of the environment variable that sets the metadata dir.
-const ERROR_METADATA_VAR: &'static str = "ERROR_METADATA_DIR";
+const ERROR_METADATA_PREFIX: &'static str = "tmp/extended-errors";
 
 /// JSON encodable/decodable version of `ErrorInfo`.
 #[derive(PartialEq, RustcDecodable, RustcEncodable)]
@@ -61,84 +55,32 @@ impl ErrorLocation {
     }
 }
 
-/// Type for describing the uniqueness of a set of error codes, as returned by `check_uniqueness`.
-pub enum Uniqueness {
-    /// All errors in the set checked are unique according to the metadata files checked.
-    Unique,
-    /// One or more errors in the set occur in another metadata file.
-    /// This variant contains the first duplicate error code followed by the name
-    /// of the metadata file where the duplicate appears.
-    Duplicate(String, String)
-}
-
-/// Get the directory where metadata files should be stored.
-pub fn get_metadata_dir() -> PathBuf {
-    match env::var(ERROR_METADATA_VAR) {
-        Ok(v) => From::from(v),
-        Err(_) => From::from(ERROR_METADATA_DIR_DEFAULT)
-    }
-}
-
-/// Get the path where error metadata for the set named by `name` should be stored.
-fn get_metadata_path(name: &str) -> PathBuf {
-    get_metadata_dir().join(format!("{}.json", name))
+/// Get the directory where metadata for a given `prefix` should be stored.
+///
+/// See `output_metadata`.
+pub fn get_metadata_dir(prefix: &str) -> PathBuf {
+    PathBuf::from(ERROR_METADATA_PREFIX).join(prefix)
 }
 
-/// Check that the errors in `err_map` aren't present in any metadata files in the
-/// metadata directory except the metadata file corresponding to `name`.
-pub fn check_uniqueness(name: &str, err_map: &ErrorMap) -> Result<Uniqueness, Box<Error>> {
-    let metadata_dir = get_metadata_dir();
-    let metadata_path = get_metadata_path(name);
-
-    // Create the error directory if it does not exist.
-    try!(create_dir_all(&metadata_dir));
-
-    // Check each file in the metadata directory.
-    for entry in try!(read_dir(&metadata_dir)) {
-        let path = try!(entry).path();
-
-        // Skip any existing file for this set.
-        if path == metadata_path {
-            continue;
-        }
-
-        // Read the metadata file into a string.
-        let mut metadata_str = String::new();
-        try!(
-            File::open(&path).and_then(|mut f|
-            f.read_to_string(&mut metadata_str))
-        );
-
-        // Parse the JSON contents.
-        let metadata: ErrorMetadataMap = try!(json::decode(&metadata_str));
-
-        // Check for duplicates.
-        for err in err_map.keys() {
-            let err_code = err.as_str();
-            if metadata.contains_key(err_code) {
-                return Ok(Duplicate(
-                    err_code.to_string(),
-                    path.to_string_lossy().into_owned()
-                ));
-            }
-        }
-    }
-
-    Ok(Unique)
+/// Map `name` to a path in the given directory: <directory>/<name>.json
+fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf {
+    directory.join(format!("{}.json", name))
 }
 
-/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `name`.
-pub fn output_metadata(ecx: &ExtCtxt, name: &str, err_map: &ErrorMap)
+/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`.
+///
+/// For our current purposes the prefix is the target architecture and the name is a crate name.
+/// If an error occurs steps will be taken to ensure that no file is created.
+pub fn output_metadata(ecx: &ExtCtxt, prefix: &str, name: &str, err_map: &ErrorMap)
     -> Result<(), Box<Error>>
 {
-    let metadata_path = get_metadata_path(name);
+    // Create the directory to place the file in.
+    let metadata_dir = get_metadata_dir(prefix);
+    try!(create_dir_all(&metadata_dir));
 
-    // Open the dump file.
-    let mut dump_file = try!(OpenOptions::new()
-        .write(true)
-        .create(true)
-        .open(&metadata_path)
-    );
+    // Open the metadata file.
+    let metadata_path = get_metadata_path(metadata_dir, name);
+    let mut metadata_file = try!(File::create(&metadata_path));
 
     // Construct a serializable map.
     let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| {
@@ -150,6 +92,10 @@ pub fn output_metadata(ecx: &ExtCtxt, name: &str, err_map: &ErrorMap)
         (key, value)
     }).collect::<ErrorMetadataMap>();
 
-    try!(write!(&mut dump_file, "{}", as_json(&json_map)));
-    Ok(())
+    // Write the data to the file, deleting it if the write fails.
+    let result = write!(&mut metadata_file, "{}", as_json(&json_map));
+    if result.is_err() {
+        try!(remove_file(&metadata_path));
+    }
+    Ok(try!(result))
 }
index 16841bd90398147b9919e1711c9f72c223deb53f..aee066807f49a5fef9f6b21071428bf599f2c990 100644 (file)
 
 use std::cell::RefCell;
 use std::collections::BTreeMap;
+use std::env;
 
 use ast;
 use ast::{Ident, Name, TokenTree};
 use codemap::Span;
-use diagnostics::metadata::{check_uniqueness, output_metadata, Duplicate};
 use ext::base::{ExtCtxt, MacEager, MacResult};
 use ext::build::AstBuilder;
 use parse::token;
 use ptr::P;
 use util::small_vector::SmallVector;
 
+use diagnostics::metadata::output_metadata;
+
 // Maximum width of any line in an extended error description (inclusive).
 const MAX_DESCRIPTION_WIDTH: usize = 80;
 
@@ -100,6 +102,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
         }
         _ => unreachable!()
     };
+
     // Check that the description starts and ends with a newline and doesn't
     // overflow the maximum line width.
     description.map(|raw_msg| {
@@ -110,9 +113,15 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
                 token::get_ident(*code)
             ));
         }
-        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH) {
+
+        // URLs can be unavoidably longer than the line limit, so we allow them.
+        // Allowed format is: `[name]: http://rust-lang.org/`
+        let is_url = |l: &str| l.starts_with('[') && l.contains("]:") && l.contains("http");
+
+        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) {
             ecx.span_err(span, &format!(
-                "description for error code {} contains a line longer than {} characters",
+                "description for error code {} contains a line longer than {} characters.\n\
+                 if you're inserting a long URL use the footnote style to bypass this check.",
                 token::get_ident(*code), MAX_DESCRIPTION_WIDTH
             ));
         }
@@ -158,20 +167,17 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
         _ => unreachable!()
     };
 
-    // Check uniqueness of errors and output metadata.
+    // Output error metadata to `tmp/extended-errors/<target arch>/<crate name>.json`
+    let target_triple = env::var("CFG_COMPILER_HOST_TRIPLE")
+        .ok().expect("unable to determine target arch from $CFG_COMPILER_HOST_TRIPLE");
+
     with_registered_diagnostics(|diagnostics| {
-        match check_uniqueness(crate_name, &*diagnostics) {
-            Ok(Duplicate(err, location)) => {
-                ecx.span_err(span, &format!(
-                    "error {} from `{}' also found in `{}'",
-                    err, crate_name, location
-                ));
-            },
-            Ok(_) => (),
-            Err(e) => panic!("{}", e.description())
+        if let Err(e) = output_metadata(ecx, &target_triple, crate_name, &diagnostics) {
+            ecx.span_bug(span, &format!(
+                "error writing metadata for triple `{}` and crate `{}`, error: {}, cause: {:?}",
+                target_triple, crate_name, e.description(), e.cause()
+            ));
         }
-
-        output_metadata(&*ecx, crate_name, &*diagnostics).ok().expect("metadata output error");
     });
 
     // Construct the output expression.
@@ -213,9 +219,8 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
             ident: name.clone(),
             attrs: Vec::new(),
             id: ast::DUMMY_NODE_ID,
-            node: ast::ItemStatic(
+            node: ast::ItemConst(
                 ty,
-                ast::MutImmutable,
                 expr,
             ),
             vis: ast::Public,
index 9f3abfcb08b58701157368d368ca794f4cc93099..499562edc0cc9e153b62837126396f14b252d564 100644 (file)
@@ -154,18 +154,18 @@ pub trait MultiItemDecorator {
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
-              item: Annotatable,
+              item: &Annotatable,
               push: &mut FnMut(Annotatable));
 }
 
 impl<F> MultiItemDecorator for F
-    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable, &mut FnMut(Annotatable))
+    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut FnMut(Annotatable))
 {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
-              item: Annotatable,
+              item: &Annotatable,
               push: &mut FnMut(Annotatable)) {
         (*self)(ecx, sp, meta_item, item, push)
     }
@@ -648,7 +648,7 @@ impl<'a> ExtCtxt<'a> {
         parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg())
     }
 
-    pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
+    pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
     pub fn call_site(&self) -> Span {
index 354a0bff74998bbcc3c21d93f7d379d0db0f41d3..8a80e291a538405f38c11e9911be3d3421fa855c 100644 (file)
@@ -1034,6 +1034,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                   Vec::new(),
                   ast::ItemFn(self.fn_decl(inputs, output),
                               ast::Unsafety::Normal,
+                              ast::Constness::NotConst,
                               abi::Rust,
                               generics,
                               body))
index 0593de6db07a74545d3ac664cb7e3ba68b866323..689a4e96aec80bd40c01604b55132a0218fa78a7 100644 (file)
@@ -17,7 +17,7 @@ use ext::deriving::generic::ty::*;
 pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
                                     span: Span,
                                     _: &MetaItem,
-                                    _: Annotatable,
+                                    _: &Annotatable,
                                     _: &mut FnMut(Annotatable))
 {
     cx.span_err(span, "this unsafe trait should be implemented explicitly");
@@ -26,7 +26,7 @@ pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
 pub fn expand_deriving_copy(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: Annotatable,
+                            item: &Annotatable,
                             push: &mut FnMut(Annotatable))
 {
     let path = Path::new(vec![
@@ -45,5 +45,5 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push);
+    trait_def.expand(cx, mitem, item, push);
 }
index 0d8fb471429377e3878a9fd52b038b0a5d9ae462..a9c05339894d270f1215f603796b2499c49d511a 100644 (file)
@@ -20,7 +20,7 @@ use ptr::P;
 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                              span: Span,
                              mitem: &MetaItem,
-                             item: Annotatable,
+                             item: &Annotatable,
                              push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -39,6 +39,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self_,
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|c, s, sub| {
                     cs_clone("Clone", c, s, sub)
                 })),
@@ -47,7 +48,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 fn cs_clone(
index bd7c7d85a375f41bf6cec262201bbab88ac874af..b370757e8fb4b12dfaa623b9a2f5b564be691316 100644 (file)
@@ -20,7 +20,7 @@ use ptr::P;
 pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                           span: Span,
                           mitem: &MetaItem,
-                          item: Annotatable,
+                          item: &Annotatable,
                           push: &mut FnMut(Annotatable))
 {
     fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
@@ -59,6 +59,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                 args: vec!(),
                 ret_ty: nil_ty(),
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     cs_total_eq_assert(a, b, c)
                 }))
@@ -66,5 +67,5 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
         ),
         associated_types: Vec::new(),
     };
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
index b4caf0ec26e277de9a25ec9abc371167446422b5..d605e0286f525138baa8eb2675cf743b2b8131e5 100644 (file)
@@ -21,7 +21,7 @@ use ptr::P;
 pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
-                           item: Annotatable,
+                           item: &Annotatable,
                            push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -40,6 +40,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     cs_cmp(a, b, c)
                 })),
@@ -48,7 +49,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 
index 5d744334745d32e9c17bb6394a15df3d19b33623..e5d6408ca1b6dfd0d166693f97e598e388bf9770 100644 (file)
@@ -20,7 +20,7 @@ use ptr::P;
 pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
                                   span: Span,
                                   mitem: &MetaItem,
-                                  item: Annotatable,
+                                  item: &Annotatable,
                                   push: &mut FnMut(Annotatable))
 {
     // structures are equal if all fields are equal, and non equal, if
@@ -71,6 +71,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     $f(a, b, c)
                 }))
@@ -90,5 +91,5 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
         ),
         associated_types: Vec::new(),
     };
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
index 3ef73f6556e3015e767e331807708bd1e6180a5e..4eb95343a49a75d5c4f5c5b2e464c353588fbc8c 100644 (file)
@@ -23,7 +23,7 @@ use ptr::P;
 pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
                                    span: Span,
                                    mitem: &MetaItem,
-                                   item: Annotatable,
+                                   item: &Annotatable,
                                    push: &mut FnMut(Annotatable))
 {
     macro_rules! md {
@@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
                     cs_op($op, $equal, cx, span, substr)
                 }))
@@ -60,6 +61,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
         args: vec![borrowed_self()],
         ret_ty: ret_ty,
         attributes: attrs,
+        is_unsafe: false,
         combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
             cs_partial_cmp(cx, span, substr)
         }))
@@ -80,7 +82,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
         ],
         associated_types: Vec::new(),
     };
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 #[derive(Copy, Clone)]
index 75c9bc42ea2bfc6e261af3c138620bb9af5a6c35..99f217a419af84c0a7bb51a1cc2062f2cb8f8796 100644 (file)
@@ -24,7 +24,7 @@ use ptr::P;
 pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
-                                       item: Annotatable,
+                                       item: &Annotatable,
                                        push: &mut FnMut(Annotatable))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
@@ -33,7 +33,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
 pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: Annotatable,
+                                 item: &Annotatable,
                                  push: &mut FnMut(Annotatable))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
@@ -42,7 +42,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
 fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: Annotatable,
+                                 item: &Annotatable,
                                  push: &mut FnMut(Annotatable),
                                  krate: &'static str)
 {
@@ -79,6 +79,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                     true
                 )),
                 attributes: Vec::new(),
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     decodable_substructure(a, b, c, krate)
                 })),
@@ -87,7 +88,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
index e9984c84e322fad9b5587f576819428b7b7919a7..ab22b7107003b08ab5283bff83ef8c1c7c068d5e 100644 (file)
@@ -20,7 +20,7 @@ use ptr::P;
 pub fn expand_deriving_default(cx: &mut ExtCtxt,
                                span: Span,
                                mitem: &MetaItem,
-                               item: Annotatable,
+                               item: &Annotatable,
                                push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -39,6 +39,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self_,
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     default_substructure(a, b, c)
                 }))
@@ -46,7 +47,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
         ),
         associated_types: Vec::new(),
     };
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
index 4430c58700af365be6da580d708e478814911f43..0ef23705f95ac0b78272b7996652d104707e8b11 100644 (file)
@@ -100,7 +100,7 @@ use ptr::P;
 pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
-                                       item: Annotatable,
+                                       item: &Annotatable,
                                        push: &mut FnMut(Annotatable))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
@@ -109,7 +109,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
 pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: Annotatable,
+                                 item: &Annotatable,
                                  push: &mut FnMut(Annotatable))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
@@ -118,7 +118,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
 fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: Annotatable,
+                                 item: &Annotatable,
                                  push: &mut FnMut(Annotatable),
                                  krate: &'static str)
 {
@@ -155,6 +155,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                     true
                 )),
                 attributes: Vec::new(),
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     encodable_substructure(a, b, c)
                 })),
@@ -163,7 +164,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
index 1525f1a822bec5436160b91abb9f9f078383b179..e7d242ab70364300b8a08f4b29ba1023d795d3c6 100644 (file)
@@ -253,6 +253,9 @@ pub struct MethodDef<'a> {
 
     pub attributes: Vec<ast::Attribute>,
 
+    // Is it an `unsafe fn`?
+    pub is_unsafe: bool,
+
     pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
 }
 
@@ -502,7 +505,7 @@ impl<'a> TraitDef<'a> {
             bounds.push(cx.typarambound(trait_path.clone()));
 
             // also add in any bounds from the declaration
-            for declared_bound in &*ty_param.bounds {
+            for declared_bound in ty_param.bounds.iter() {
                 bounds.push((*declared_bound).clone());
             }
 
@@ -546,10 +549,10 @@ impl<'a> TraitDef<'a> {
                 .map(|ty_param| ty_param.ident.name)
                 .collect();
 
-            for field_ty in field_tys.into_iter() {
+            for field_ty in field_tys {
                 let tys = find_type_parameters(&*field_ty, &ty_param_names);
 
-                for ty in tys.into_iter() {
+                for ty in tys {
                     let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| {
                         cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
                     }).collect();
@@ -669,7 +672,7 @@ impl<'a> TraitDef<'a> {
                        generics: &Generics) -> P<ast::Item> {
         let mut field_tys = Vec::new();
 
-        for variant in enum_def.variants.iter() {
+        for variant in &enum_def.variants {
             match variant.node.kind {
                 ast::VariantKind::TupleVariantKind(ref args) => {
                     field_tys.extend(args.iter()
@@ -859,6 +862,12 @@ impl<'a> MethodDef<'a> {
         let fn_decl = cx.fn_decl(args, ret_type);
         let body_block = cx.block_expr(body);
 
+        let unsafety = if self.is_unsafe {
+            ast::Unsafety::Unsafe
+        } else {
+            ast::Unsafety::Normal
+        };
+
         // Create the method.
         P(ast::ImplItem {
             id: ast::DUMMY_NODE_ID,
@@ -870,7 +879,8 @@ impl<'a> MethodDef<'a> {
                 generics: fn_generics,
                 abi: abi,
                 explicit_self: explicit_self,
-                unsafety: ast::Unsafety::Normal,
+                unsafety: unsafety,
+                constness: ast::Constness::NotConst,
                 decl: fn_decl
             }, body_block)
         })
@@ -957,7 +967,7 @@ impl<'a> MethodDef<'a> {
         // make a series of nested matches, to destructure the
         // structs. This is actually right-to-left, but it shouldn't
         // matter.
-        for (arg_expr, pat) in self_args.iter().zip(patterns.iter()) {
+        for (arg_expr, pat) in self_args.iter().zip(patterns) {
             body = cx.expr_match(trait_.span, arg_expr.clone(),
                                      vec!( cx.arm(trait_.span, vec!(pat.clone()), body) ))
         }
@@ -1032,21 +1042,31 @@ impl<'a> MethodDef<'a> {
     /// variants where all of the variants match, and one catch-all for
     /// when one does not match.
 
+    /// As an optimization we generate code which checks whether all variants
+    /// match first which makes llvm see that C-like enums can be compiled into
+    /// a simple equality check (for PartialEq).
+
     /// The catch-all handler is provided access the variant index values
-    /// for each of the self-args, carried in precomputed variables. (Nota
-    /// bene: the variant index values are not necessarily the
-    /// discriminant values.  See issue #15523.)
+    /// for each of the self-args, carried in precomputed variables.
 
     /// ```{.text}
-    /// match (this, that, ...) {
-    ///   (Variant1, Variant1, Variant1) => ... // delegate Matching on Variant1
-    ///   (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2
-    ///   ...
-    ///   _ => {
-    ///     let __this_vi = match this { Variant1 => 0, Variant2 => 1, ... };
-    ///     let __that_vi = match that { Variant1 => 0, Variant2 => 1, ... };
+    /// let __self0_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&self) } as i32;
+    /// let __self1_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&__arg1) } as i32;
+    /// let __self2_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&__arg2) } as i32;
+    ///
+    /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
+    ///     match (...) {
+    ///         (Variant1, Variant1, ...) => Body1
+    ///         (Variant2, Variant2, ...) => Body2,
+    ///         ...
+    ///         _ => ::core::intrinsics::unreachable()
+    ///     }
+    /// }
+    /// else {
     ///     ... // catch-all remainder can inspect above variant index values.
-    ///   }
     /// }
     /// ```
     fn build_enum_match_tuple<'b>(
@@ -1177,7 +1197,6 @@ impl<'a> MethodDef<'a> {
 
                 cx.arm(sp, vec![single_pat], arm_expr)
             }).collect();
-
         // We will usually need the catch-all after matching the
         // tuples `(VariantK, VariantK, ...)` for each VariantK of the
         // enum.  But:
@@ -1213,10 +1232,15 @@ impl<'a> MethodDef<'a> {
             // ```
             let mut index_let_stmts: Vec<P<ast::Stmt>> = Vec::new();
 
+            //We also build an expression which checks whether all discriminants are equal
+            // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
+            let mut discriminant_test = cx.expr_bool(sp, true);
+
             let target_type_name =
                 find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
 
-            for (&ident, self_arg) in vi_idents.iter().zip(self_args.iter()) {
+            let mut first_ident = None;
+            for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
                 let path = vec![cx.ident_of_std("core"),
                                 cx.ident_of("intrinsics"),
                                 cx.ident_of("discriminant_value")];
@@ -1233,32 +1257,64 @@ impl<'a> MethodDef<'a> {
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
                 index_let_stmts.push(let_stmt);
+
+                match first_ident {
+                    Some(first) => {
+                        let first_expr = cx.expr_ident(sp, first);
+                        let id = cx.expr_ident(sp, ident);
+                        let test = cx.expr_binary(sp, ast::BiEq, first_expr, id);
+                        discriminant_test = cx.expr_binary(sp, ast::BiAnd, discriminant_test, test)
+                    }
+                    None => {
+                        first_ident = Some(ident);
+                    }
+                }
             }
 
             let arm_expr = self.call_substructure_method(
                 cx, trait_, type_ident, &self_args[..], nonself_args,
                 &catch_all_substructure);
 
-            // Builds the expression:
-            // {
-            //   let __self0_vi = ...;
-            //   let __self1_vi = ...;
-            //   ...
-            //   <delegated expression referring to __self0_vi, et al.>
-            // }
-            let arm_expr = cx.expr_block(
-                cx.block_all(sp, index_let_stmts, Some(arm_expr)));
-
-            // Builds arm:
-            // _ => { let __self0_vi = ...;
-            //        let __self1_vi = ...;
-            //        ...
-            //        <delegated expression as above> }
-            let catch_all_match_arm =
-                cx.arm(sp, vec![cx.pat_wild(sp)], arm_expr);
-
-            match_arms.push(catch_all_match_arm);
-
+            //Since we know that all the arguments will match if we reach the match expression we
+            //add the unreachable intrinsics as the result of the catch all which should help llvm
+            //in optimizing it
+            let path = vec![cx.ident_of_std("core"),
+                            cx.ident_of("intrinsics"),
+                            cx.ident_of("unreachable")];
+            let call = cx.expr_call_global(
+                sp, path, vec![]);
+            let unreachable = cx.expr_block(P(ast::Block {
+                stmts: vec![],
+                expr: Some(call),
+                id: ast::DUMMY_NODE_ID,
+                rules: ast::UnsafeBlock(ast::CompilerGenerated),
+                span: sp }));
+            match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], unreachable));
+
+            // Final wrinkle: the self_args are expressions that deref
+            // down to desired l-values, but we cannot actually deref
+            // them when they are fed as r-values into a tuple
+            // expression; here add a layer of borrowing, turning
+            // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
+            let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
+            let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
+
+            //Lastly we create an expression which branches on all discriminants being equal
+            //  if discriminant_test {
+            //      match (...) {
+            //          (Variant1, Variant1, ...) => Body1
+            //          (Variant2, Variant2, ...) => Body2,
+            //          ...
+            //          _ => ::core::intrinsics::unreachable()
+            //      }
+            //  }
+            //  else {
+            //      <delegated expression referring to __self0_vi, et al.>
+            //  }
+            let all_match = cx.expr_match(sp, match_arg, match_arms);
+            let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr));
+            cx.expr_block(
+                cx.block_all(sp, index_let_stmts, Some(arm_expr)))
         } else if variants.is_empty() {
             // As an additional wrinkle, For a zero-variant enum A,
             // currently the compiler
@@ -1309,17 +1365,19 @@ impl<'a> MethodDef<'a> {
             // derive Debug on such a type could here generate code
             // that needs the feature gate enabled.)
 
-            return cx.expr_unreachable(sp);
+            cx.expr_unreachable(sp)
+        }
+        else {
+
+            // Final wrinkle: the self_args are expressions that deref
+            // down to desired l-values, but we cannot actually deref
+            // them when they are fed as r-values into a tuple
+            // expression; here add a layer of borrowing, turning
+            // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
+            let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
+            let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
+            cx.expr_match(sp, match_arg, match_arms)
         }
-
-        // Final wrinkle: the self_args are expressions that deref
-        // down to desired l-values, but we cannot actually deref
-        // them when they are fed as r-values into a tuple
-        // expression; here add a layer of borrowing, turning
-        // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
-        let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
-        let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
-        cx.expr_match(sp, match_arg, match_arms)
     }
 
     fn expand_static_enum_method_body(&self,
@@ -1455,7 +1513,7 @@ impl<'a> TraitDef<'a> {
         // struct_type is definitely not Unknown, since struct_def.fields
         // must be nonempty to reach here
         let pattern = if struct_type == Record {
-            let field_pats = subpats.into_iter().zip(ident_expr.iter())
+            let field_pats = subpats.into_iter().zip(&ident_expr)
                                     .map(|(pat, &(_, id, _, _))| {
                 // id is guaranteed to be Some
                 codemap::Spanned {
index 698e788d65f00d8827cea539f72d2cf453376877..cdb378a34d487c427801dad1efc1666208579bda 100644 (file)
@@ -19,7 +19,7 @@ use ptr::P;
 pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: Annotatable,
+                            item: &Annotatable,
                             push: &mut FnMut(Annotatable))
 {
 
@@ -44,6 +44,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                 args: vec!(Ptr(Box::new(Literal(arg)), Borrowed(None, MutMutable))),
                 ret_ty: nil_ty(),
                 attributes: vec![],
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
                     hash_substructure(a, b, c)
                 }))
@@ -52,7 +53,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    hash_trait_def.expand(cx, mitem, &item, push);
+    hash_trait_def.expand(cx, mitem, item, push);
 }
 
 fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
index 61848cca059ce3c0c02f7093933ad91872f71d45..344515b875f0a91929565c112e5c7f1e6ae664d9 100644 (file)
@@ -134,7 +134,7 @@ macro_rules! derive_traits {
                               ecx: &mut ExtCtxt,
                               sp: Span,
                               mitem: &MetaItem,
-                              annotatable: Annotatable,
+                              annotatable: &Annotatable,
                               push: &mut FnMut(Annotatable)) {
                         warn_if_deprecated(ecx, sp, $name);
                         $func(ecx, sp, mitem, annotatable, push);
index 4fe9aefa1a4dfe51a5080b51e47a7bb76a266379..5eb98d3aa15988d91685be9ef412d30d1c57b125 100644 (file)
@@ -21,7 +21,7 @@ use ptr::P;
 pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                       span: Span,
                                       mitem: &MetaItem,
-                                      item: Annotatable,
+                                      item: &Annotatable,
                                       push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -44,6 +44,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs.clone(),
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|c, s, sub| {
                     cs_from("i64", c, s, sub)
                 })),
@@ -59,6 +60,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs,
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(|c, s, sub| {
                     cs_from("u64", c, s, sub)
                 })),
@@ -67,7 +69,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
index dc634df2073a48b031be43f86dda072d8f2473b5..dbde963bda988110886aa9ed79ec09021ee0b4c5 100644 (file)
@@ -21,7 +21,7 @@ use ptr::P;
 pub fn expand_deriving_show(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: Annotatable,
+                            item: &Annotatable,
                             push: &mut FnMut(Annotatable))
 {
     // &mut ::std::fmt::Formatter
@@ -42,6 +42,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
                 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)
                 }))
@@ -49,7 +50,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
         ],
         associated_types: Vec::new(),
     };
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 /// We use the debug builders to do the heavy lifting here
@@ -74,6 +75,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
 
     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,
@@ -82,11 +84,14 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
                                            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![cx.expr_addr_of(field.span,
-                                                                    field.self_.clone())]);
+                                               vec![field]);
                 }
             } else {
                 // normal struct/struct variant
@@ -99,12 +104,14 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
                     let name = cx.expr_lit(field.span, ast::Lit_::LitStr(
                             token::get_ident(field.name.clone().unwrap()),
                             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,
-                                                    cx.expr_addr_of(field.span,
-                                                                    field.self_.clone())]);
+                                               vec![name, field]);
                 }
             }
         }
index fae0b56ce3d0b5d0b441c51b223348073bf589a7..4aa313f3e660ff4165a0434439101740332ca546 100644 (file)
@@ -183,7 +183,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
 
             let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
             arms.push(pat_arm);
-            arms.extend(else_if_arms.into_iter());
+            arms.extend(else_if_arms);
             arms.push(else_arm);
 
             let match_expr = fld.cx.expr(span,
@@ -513,11 +513,12 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
 /// Expand item_underscore
 fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ {
     match item {
-        ast::ItemFn(decl, fn_style, abi, generics, body) => {
+        ast::ItemFn(decl, unsafety, constness, abi, generics, body) => {
             let (rewritten_fn_decl, rewritten_body)
                 = expand_and_rename_fn_decl_and_block(decl, body, fld);
             let expanded_generics = fold::noop_fold_generics(generics,fld);
-            ast::ItemFn(rewritten_fn_decl, fn_style, abi, expanded_generics, rewritten_body)
+            ast::ItemFn(rewritten_fn_decl, unsafety, constness, abi,
+                        expanded_generics, rewritten_body)
         }
         _ => noop_fold_item_underscore(item, fld)
     }
@@ -778,7 +779,7 @@ fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroE
                     };
                     // add them to the existing pending renames:
                     fld.cx.syntax_env.info().pending_renames
-                          .extend(new_pending_renames.into_iter());
+                          .extend(new_pending_renames);
                     Local {
                         id: id,
                         ty: expanded_ty,
@@ -1212,7 +1213,7 @@ fn expand_decorators(a: Annotatable,
                     dec.expand(fld.cx,
                                attr.span,
                                &attr.node.value,
-                               a.clone(),
+                               &a,
                                &mut |ann| items.push(ann));
                     decorator_items.extend(items.into_iter()
                         .flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
@@ -1395,6 +1396,7 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
         abi: sig.abi,
         explicit_self: fld.fold_explicit_self(sig.explicit_self),
         unsafety: sig.unsafety,
+        constness: sig.constness,
         decl: rewritten_fn_decl
     }, rewritten_body)
 }
@@ -1684,7 +1686,7 @@ mod tests {
     #[test] fn macros_cant_escape_fns_test () {
         let src = "fn bogus() {macro_rules! z (() => (3+4));}\
                    fn inty() -> i32 { z!() }".to_string();
-        let sess = parse::new_parse_sess();
+        let sess = parse::ParseSess::new();
         let crate_ast = parse::parse_crate_from_source_str(
             "<test>".to_string(),
             src,
@@ -1698,7 +1700,7 @@ mod tests {
     #[test] fn macros_cant_escape_mods_test () {
         let src = "mod foo {macro_rules! z (() => (3+4));}\
                    fn inty() -> i32 { z!() }".to_string();
-        let sess = parse::new_parse_sess();
+        let sess = parse::ParseSess::new();
         let crate_ast = parse::parse_crate_from_source_str(
             "<test>".to_string(),
             src,
@@ -1710,7 +1712,7 @@ mod tests {
     #[test] fn macros_can_escape_flattened_mods_test () {
         let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\
                    fn inty() -> i32 { z!() }".to_string();
-        let sess = parse::new_parse_sess();
+        let sess = parse::ParseSess::new();
         let crate_ast = parse::parse_crate_from_source_str(
             "<test>".to_string(),
             src,
@@ -1719,7 +1721,7 @@ mod tests {
     }
 
     fn expand_crate_str(crate_str: String) -> ast::Crate {
-        let ps = parse::new_parse_sess();
+        let ps = parse::ParseSess::new();
         let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
         // the cfg argument actually does matter, here...
         expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast)
index 4fe5ab1554500877aa1e2f99e00b62d93d65ebab..86e72d4ef03de4350d46ac4f95e49a01fcf65aaf 100644 (file)
@@ -452,6 +452,7 @@ impl<'a, 'b> Context<'a, 'b> {
             Some(ecx.lifetime(sp, special_idents::static_lifetime.name)),
             ast::MutImmutable);
         let slice = ecx.expr_vec_slice(sp, pieces);
+        // static instead of const to speed up codegen by not requiring this to be inlined
         let st = ast::ItemStatic(ty, ast::MutImmutable, slice);
 
         let name = ecx.ident_of(name);
index e0753b2f6f6eebe9c2bda077d6ed6522b92963c3..82c249d2585adf699a35b63774f440eb5eec3668 100644 (file)
@@ -49,7 +49,7 @@ pub mod rt {
 
     impl<T: ToTokens> ToTokens for Vec<T> {
         fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-            self.iter().flat_map(|t| t.to_tokens(cx).into_iter()).collect()
+            self.iter().flat_map(|t| t.to_tokens(cx)).collect()
         }
     }
 
@@ -387,7 +387,7 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt,
                             -> Box<base::MacResult+'static> {
     let (cx_expr, tts) = parse_arguments_to_quote(cx, tts);
     let mut vector = mk_stmts_let(cx, sp);
-    vector.extend(statements_mk_tts(cx, &tts[..], true).into_iter());
+    vector.extend(statements_mk_tts(cx, &tts[..], true));
     let block = cx.expr_block(
         cx.block_all(sp,
                      vector,
@@ -593,7 +593,7 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
 fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<ast::Stmt>> {
     match *tt {
         ast::TtToken(sp, SubstNt(ident, _)) => {
-            // tt.extend($ident.to_tokens(ext_cx).into_iter())
+            // tt.extend($ident.to_tokens(ext_cx))
 
             let e_to_toks =
                 cx.expr_method_call(sp,
@@ -633,8 +633,8 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<a
         ast::TtDelimited(_, ref delimed) => {
             statements_mk_tt(cx, &delimed.open_tt(), matcher).into_iter()
                 .chain(delimed.tts.iter()
-                                  .flat_map(|tt| statements_mk_tt(cx, tt, matcher).into_iter()))
-                .chain(statements_mk_tt(cx, &delimed.close_tt(), matcher).into_iter())
+                                  .flat_map(|tt| statements_mk_tt(cx, tt, matcher)))
+                .chain(statements_mk_tt(cx, &delimed.close_tt(), matcher))
                 .collect()
         },
         ast::TtSequence(sp, ref seq) => {
@@ -646,7 +646,7 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<a
 
             let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp));
             let mut tts_stmts = vec![stmt_let_tt];
-            tts_stmts.extend(statements_mk_tts(cx, &seq.tts[..], matcher).into_iter());
+            tts_stmts.extend(statements_mk_tts(cx, &seq.tts[..], matcher));
             let e_tts = cx.expr_block(cx.block(sp, tts_stmts,
                                                    Some(cx.expr_ident(sp, id_ext("tt")))));
             let e_separator = match seq.separator {
@@ -748,7 +748,7 @@ fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec<P<ast::Stmt>> {
 fn statements_mk_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], matcher: bool) -> Vec<P<ast::Stmt>> {
     let mut ss = Vec::new();
     for tt in tts {
-        ss.extend(statements_mk_tt(cx, tt, matcher).into_iter());
+        ss.extend(statements_mk_tt(cx, tt, matcher));
     }
     ss
 }
@@ -758,7 +758,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     let (cx_expr, tts) = parse_arguments_to_quote(cx, tts);
 
     let mut vector = mk_stmts_let(cx, sp);
-    vector.extend(statements_mk_tts(cx, &tts[..], false).into_iter());
+    vector.extend(statements_mk_tts(cx, &tts[..], false));
     let block = cx.expr_block(
         cx.block_all(sp,
                      vector,
@@ -780,7 +780,7 @@ fn expand_wrapper(cx: &ExtCtxt,
         // make item: `use ...;`
         let path = path.iter().map(|s| s.to_string()).collect();
         cx.stmt_item(sp, cx.item_use_glob(sp, ast::Inherited, ids_ext(path)))
-    }).chain(Some(stmt_let_ext_cx).into_iter()).collect();
+    }).chain(Some(stmt_let_ext_cx)).collect();
 
     cx.expr_block(cx.block_all(sp, stmts, Some(expr)))
 }
index 27a00290ee01ea81e8502b256102eca808ec7f17..03d4e21a941bffdba4a63f649eea93e308ffb9ed 100644 (file)
@@ -325,42 +325,55 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
         last = match *token {
             TtToken(sp, MatchNt(ref name, ref frag_spec, _, _)) => {
                 // ii. If T is a simple NT, look ahead to the next token T' in
-                // M.
-                let next_token = match tokens.peek() {
-                    // If T' closes a complex NT, replace T' with F
-                    Some(&&TtToken(_, CloseDelim(_))) => follow.clone(),
-                    Some(&&TtToken(_, ref tok)) => tok.clone(),
-                    Some(&&TtSequence(sp, _)) => {
-                        cx.span_err(sp,
-                                    &format!("`${0}:{1}` is followed by a \
-                                              sequence repetition, which is not \
-                                              allowed for `{1}` fragments",
-                                             name.as_str(), frag_spec.as_str())
+                // M. If T' is in the set FOLLOW(NT), continue. Else; reject.
+                if can_be_followed_by_any(frag_spec.as_str()) {
+                    continue
+                } else {
+                    let next_token = match tokens.peek() {
+                        // If T' closes a complex NT, replace T' with F
+                        Some(&&TtToken(_, CloseDelim(_))) => follow.clone(),
+                        Some(&&TtToken(_, ref tok)) => tok.clone(),
+                        Some(&&TtSequence(sp, _)) => {
+                            // Be conservative around sequences: to be
+                            // more specific, we would need to
+                            // consider FIRST sets, but also the
+                            // possibility that the sequence occurred
+                            // zero times (in which case we need to
+                            // look at the token that follows the
+                            // sequence, which may itself a sequence,
+                            // and so on).
+                            cx.span_err(sp,
+                                        &format!("`${0}:{1}` is followed by a \
+                                                  sequence repetition, which is not \
+                                                  allowed for `{1}` fragments",
+                                                 name.as_str(), frag_spec.as_str())
                                         );
-                        Eof
-                    },
-                    // die next iteration
-                    Some(&&TtDelimited(_, ref delim)) => delim.close_token(),
-                    // else, we're at the end of the macro or sequence
-                    None => follow.clone()
-                };
-
-                let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
-                // If T' is in the set FOLLOW(NT), continue. Else, reject.
-                match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) {
-                    (_, Err(msg)) => {
-                        cx.span_err(sp, &msg);
-                        continue
+                            Eof
+                        },
+                        // die next iteration
+                        Some(&&TtDelimited(_, ref delim)) => delim.close_token(),
+                        // else, we're at the end of the macro or sequence
+                        None => follow.clone()
+                    };
+
+                    let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
+
+                    // If T' is in the set FOLLOW(NT), continue. Else, reject.
+                    match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) {
+                        (_, Err(msg)) => {
+                            cx.span_err(sp, &msg);
+                            continue
+                        }
+                        (&Eof, _) => return Some((sp, tok.clone())),
+                        (_, Ok(true)) => continue,
+                        (next, Ok(false)) => {
+                            cx.span_err(sp, &format!("`${0}:{1}` is followed by `{2}`, which \
+                                                      is not allowed for `{1}` fragments",
+                                                     name.as_str(), frag_spec.as_str(),
+                                                     token_to_string(next)));
+                            continue
+                        },
                     }
-                    (&Eof, _) => return Some((sp, tok.clone())),
-                    (_, Ok(true)) => continue,
-                    (next, Ok(false)) => {
-                        cx.span_err(sp, &format!("`${0}:{1}` is followed by `{2}`, which \
-                                                  is not allowed for `{1}` fragments",
-                                                 name.as_str(), frag_spec.as_str(),
-                                                 token_to_string(next)));
-                        continue
-                    },
                 }
             },
             TtSequence(sp, ref seq) => {
@@ -427,8 +440,39 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
     last
 }
 
+/// True if a fragment of type `frag` can be followed by any sort of
+/// token.  We use this (among other things) as a useful approximation
+/// for when `frag` can be followed by a repetition like `$(...)*` or
+/// `$(...)+`. In general, these can be a bit tricky to reason about,
+/// so we adopt a conservative position that says that any fragment
+/// specifier which consumes at most one token tree can be followed by
+/// a fragment specifier (indeed, these fragments can be followed by
+/// ANYTHING without fear of future compatibility hazards).
+fn can_be_followed_by_any(frag: &str) -> bool {
+    match frag {
+        "item" |  // always terminated by `}` or `;`
+        "block" | // exactly one token tree
+        "ident" | // exactly one token tree
+        "meta" |  // exactly one token tree
+        "tt" =>    // exactly one token tree
+            true,
+
+        _ =>
+            false,
+    }
+}
+
+/// True if `frag` can legally be followed by the token `tok`. For
+/// fragments that can consume an unbounded numbe of tokens, `tok`
+/// must be within a well-defined follow set. This is intended to
+/// guarantee future compatibility: for example, without this rule, if
+/// we expanded `expr` to include a new binary operator, we might
+/// break macros that were relying on that binary operator as a
+/// separator.
 fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
     if let &CloseDelim(_) = tok {
+        // closing a token tree can never be matched by any fragment;
+        // iow, we always require that `(` and `)` match, etc.
         Ok(true)
     } else {
         match frag {
@@ -451,6 +495,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
             "pat" => {
                 match *tok {
                     FatArrow | Comma | Eq => Ok(true),
+                    Ident(i, _) if i.as_str() == "if" || i.as_str() == "in" => Ok(true),
                     _ => Ok(false)
                 }
             },
index 28deb4eec3fac2ec14584ffb42e8c96a38742cab..e695be48d38be47ae3702a31cffe75627b035290 100644 (file)
@@ -137,9 +137,6 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
     // Allows the use of rustc_* attributes; RFC 572
     ("rustc_attrs", "1.0.0", Active),
 
-    // Allows the use of `static_assert`
-    ("static_assert", "1.0.0", Active),
-
     // Allows the use of #[allow_internal_unstable]. This is an
     // attribute on macro_rules! and can't use the attribute handling
     // below (it has to be checked before expansion possibly makes
@@ -155,6 +152,12 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
     // Allows the definition of associated constants in `trait` or `impl`
     // blocks.
     ("associated_consts", "1.0.0", Active),
+
+    // Allows the definition of `const fn` functions.
+    ("const_fn", "1.2.0", Active),
+
+    // Allows associated type defaults
+    ("associated_type_defaults", "1.2.0", Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -258,9 +261,6 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
     ("no_builtins", Whitelisted),
     ("no_mangle", Whitelisted),
     ("no_stack_check", Whitelisted),
-    ("packed", Whitelisted),
-    ("static_assert", Gated("static_assert",
-                            "`#[static_assert]` is an experimental feature, and has a poor API")),
     ("no_debug", Whitelisted),
     ("omit_gdb_pretty_printer_section", Whitelisted),
     ("unsafe_no_drop_flag", Gated("unsafe_no_drop_flag",
@@ -330,7 +330,8 @@ pub struct Features {
     /// spans of #![feature] attrs for stable language features. for error reporting
     pub declared_stable_lang_features: Vec<Span>,
     /// #![feature] attrs for non-language (library) features
-    pub declared_lib_features: Vec<(InternedString, Span)>
+    pub declared_lib_features: Vec<(InternedString, Span)>,
+    pub const_fn: bool,
 }
 
 impl Features {
@@ -350,7 +351,8 @@ impl Features {
             unmarked_api: false,
             negate_unsigned: false,
             declared_stable_lang_features: Vec::new(),
-            declared_lib_features: Vec::new()
+            declared_lib_features: Vec::new(),
+            const_fn: false,
         }
     }
 }
@@ -359,6 +361,7 @@ struct Context<'a> {
     features: Vec<&'static str>,
     span_handler: &'a SpanHandler,
     cm: &'a CodeMap,
+    plugin_attributes: &'a [(String, AttributeType)],
 }
 
 impl<'a> Context<'a> {
@@ -373,7 +376,7 @@ impl<'a> Context<'a> {
         self.features.iter().any(|&n| n == feature)
     }
 
-    fn check_attribute(&self, attr: &ast::Attribute) {
+    fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
         let name = &*attr.name();
         for &(n, ty) in KNOWN_ATTRIBUTES {
@@ -385,6 +388,15 @@ impl<'a> Context<'a> {
                 return;
             }
         }
+        for &(ref n, ref ty) in self.plugin_attributes {
+            if &*n == name {
+                // Plugins can't gate attributes, so we don't check for it
+                // unlike the code above; we only use this loop to
+                // short-circuit to avoid the checks below
+                debug!("check_attribute: {:?} is registered by a plugin, {:?}", name, ty);
+                return;
+            }
+        }
         if name.starts_with("rustc_") {
             self.gate_feature("rustc_attrs", attr.span,
                               "unless otherwise specified, attributes \
@@ -395,12 +407,18 @@ impl<'a> Context<'a> {
                               "attributes of the form `#[derive_*]` are reserved \
                                for the compiler");
         } else {
-            self.gate_feature("custom_attribute", attr.span,
-                       &format!("The attribute `{}` is currently \
-                                unknown to the compiler and \
-                                may have meaning \
-                                added to it in the future",
-                                name));
+            // Only run the custom attribute lint during regular
+            // feature gate checking. Macro gating runs
+            // before the plugin attributes are registered
+            // so we skip this then
+            if !is_macro {
+                self.gate_feature("custom_attribute", attr.span,
+                           &format!("The attribute `{}` is currently \
+                                    unknown to the compiler and \
+                                    may have meaning \
+                                    added to it in the future",
+                                    name));
+            }
         }
     }
 }
@@ -415,18 +433,6 @@ pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain:
                                   feature));
 }
 
-pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
-    diag.span_warn(span, explain);
-
-    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
-    if diag.handler.can_emit_warnings {
-        diag.fileline_help(span, &format!("add #![feature({})] to the \
-                                       crate attributes to silence this warning",
-                                      feature));
-    }
-}
-
 pub const EXPLAIN_ASM: &'static str =
     "inline assembly is not stable enough for use and is subject to change";
 
@@ -479,7 +485,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        self.context.check_attribute(attr);
+        self.context.check_attribute(attr, true);
     }
 }
 
@@ -498,7 +504,7 @@ impl<'a> PostExpansionVisitor<'a> {
 impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         if !self.context.cm.span_allows_unstable(attr.span) {
-            self.context.check_attribute(attr);
+            self.context.check_attribute(attr, false);
         }
     }
 
@@ -641,13 +647,26 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                 block: &'v ast::Block,
                 span: Span,
                 _node_id: NodeId) {
+        // check for const fn declarations
+        match fn_kind {
+            visit::FkItemFn(_, _, _, ast::Constness::Const, _, _) => {
+                self.gate_feature("const_fn", span, "const fn is unstable");
+            }
+            _ => {
+                // stability of const fn methods are covered in
+                // visit_trait_item and visit_impl_item below; this is
+                // because default methods don't pass through this
+                // point.
+            }
+        }
+
         match fn_kind {
-            visit::FkItemFn(_, _, _, abi, _) if abi == Abi::RustIntrinsic => {
+            visit::FkItemFn(_, _, _, _, abi, _) if abi == Abi::RustIntrinsic => {
                 self.gate_feature("intrinsics",
                                   span,
                                   "intrinsics are subject to change")
             }
-            visit::FkItemFn(_, _, _, abi, _) |
+            visit::FkItemFn(_, _, _, _, abi, _) |
             visit::FkMethod(_, &ast::MethodSig { abi, .. }, _) if abi == Abi::RustCall => {
                 self.gate_feature("unboxed_closures",
                                   span,
@@ -665,6 +684,15 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                                   ti.span,
                                   "associated constants are experimental")
             }
+            ast::MethodTraitItem(ref sig, _) => {
+                if sig.constness == ast::Constness::Const {
+                    self.gate_feature("const_fn", ti.span, "const fn is unstable");
+                }
+            }
+            ast::TypeTraitItem(_, Some(_)) => {
+                self.gate_feature("associated_type_defaults", ti.span,
+                                  "associated type defaults are unstable");
+            }
             _ => {}
         }
         visit::walk_trait_item(self, ti);
@@ -677,6 +705,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                                   ii.span,
                                   "associated constants are experimental")
             }
+            ast::MethodImplItem(ref sig, _) => {
+                if sig.constness == ast::Constness::Const {
+                    self.gate_feature("const_fn", ii.span, "const fn is unstable");
+                }
+            }
             _ => {}
         }
         visit::walk_impl_item(self, ii);
@@ -685,6 +718,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
 
 fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
                         krate: &ast::Crate,
+                        plugin_attributes: &[(String, AttributeType)],
                         check: F)
                        -> Features
     where F: FnOnce(&mut Context, &ast::Crate)
@@ -693,6 +727,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         features: Vec::new(),
         span_handler: span_handler,
         cm: cm,
+        plugin_attributes: plugin_attributes,
     };
 
     let mut accepted_features = Vec::new();
@@ -759,20 +794,58 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         unmarked_api: cx.has_feature("unmarked_api"),
         negate_unsigned: cx.has_feature("negate_unsigned"),
         declared_stable_lang_features: accepted_features,
-        declared_lib_features: unknown_features
+        declared_lib_features: unknown_features,
+        const_fn: cx.has_feature("const_fn"),
     }
 }
 
 pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
 -> Features {
-    check_crate_inner(cm, span_handler, krate,
+    check_crate_inner(cm, span_handler, krate, &[] as &'static [_],
                       |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
 }
 
-pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
-                   -> Features
+pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
+                   plugin_attributes: &[(String, AttributeType)],
+                   unstable: UnstableFeatures) -> Features
 {
-    check_crate_inner(cm, span_handler, krate,
+    maybe_stage_features(span_handler, krate, unstable);
+
+    check_crate_inner(cm, span_handler, krate, plugin_attributes,
                       |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
                                                      krate))
 }
+
+#[derive(Clone, Copy)]
+pub enum UnstableFeatures {
+    /// Hard errors for unstable features are active, as on
+    /// beta/stable channels.
+    Disallow,
+    /// Allow features to me activated, as on nightly.
+    Allow,
+    /// 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.
+    Cheat
+}
+
+fn maybe_stage_features(span_handler: &SpanHandler, krate: &ast::Crate,
+                        unstable: UnstableFeatures) {
+    let allow_features = match unstable {
+        UnstableFeatures::Allow => true,
+        UnstableFeatures::Disallow => false,
+        UnstableFeatures::Cheat => true
+    };
+    if !allow_features {
+        for attr in &krate.attrs {
+            if attr.check_name("feature") {
+                let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
+                let ref msg = format!("#[feature] may not be used on the {} release channel",
+                                      release_channel);
+                span_handler.span_err(attr.span, msg);
+            }
+        }
+    }
+}
index 4bf15f509a048e1f34b833228ba10da97cd43fa2..14742d2e74c9518b7d003563802e2c01237f0815 100644 (file)
@@ -353,7 +353,7 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
 }
 
 pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
-    attrs.into_iter().flat_map(|x| fld.fold_attribute(x).into_iter()).collect()
+    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 {
@@ -917,10 +917,11 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
         ItemConst(t, e) => {
             ItemConst(folder.fold_ty(t), folder.fold_expr(e))
         }
-        ItemFn(decl, unsafety, abi, generics, body) => {
+        ItemFn(decl, unsafety, constness, abi, generics, body) => {
             ItemFn(
                 folder.fold_fn_decl(decl),
                 unsafety,
+                constness,
                 abi,
                 folder.fold_generics(generics),
                 folder.fold_block(body)
@@ -1124,6 +1125,7 @@ pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> Method
         abi: sig.abi,
         explicit_self: folder.fold_explicit_self(sig.explicit_self),
         unsafety: sig.unsafety,
+        constness: sig.constness,
         decl: folder.fold_fn_decl(sig.decl)
     }
 }
index 330fe86deeb37e43d3e4ef10f1d39c574223c1a0..7333265bdd41246bc0ea2afbe2385814d2e081a2 100644 (file)
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(associated_consts)]
-#![feature(collections)]
-#![feature(collections_drain)]
-#![feature(core)]
+#![feature(bitset)]
+#![feature(drain)]
+#![feature(filling_drop)]
 #![feature(libc)]
+#![feature(ref_slice)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_char)]
+#![feature(str_escape)]
 #![feature(unicode)]
+#![feature(vec_push_all)]
 
-extern crate arena;
 extern crate fmt_macros;
 extern crate serialize;
 extern crate term;
@@ -82,7 +84,6 @@ pub mod syntax {
 
 pub mod abi;
 pub mod ast;
-pub mod ast_map;
 pub mod ast_util;
 pub mod attr;
 pub mod codemap;
index 6b0674c9a41b420fe948a24a588b7bfbb4dbb3e2..b6b5ac5c01eee1f48f591f67bb1dc7aa0128b382 100644 (file)
@@ -403,45 +403,51 @@ impl<'a> StringReader<'a> {
                 Some('/') => {
                     self.bump();
                     self.bump();
+
                     // line comments starting with "///" or "//!" are doc-comments
-                    if self.curr_is('/') || self.curr_is('!') {
-                        let start_bpos = self.pos - BytePos(3);
-                        while !self.is_eof() {
-                            match self.curr.unwrap() {
-                                '\n' => break,
-                                '\r' => {
-                                    if self.nextch_is('\n') {
-                                        // CRLF
-                                        break
-                                    } else {
-                                        self.err_span_(self.last_pos, self.pos,
-                                                       "bare CR not allowed in doc-comment");
-                                    }
+                    let doc_comment = self.curr_is('/') || self.curr_is('!');
+                    let start_bpos = if doc_comment {
+                        self.pos - BytePos(3)
+                    } else {
+                        self.last_pos - BytePos(2)
+                    };
+
+                    while !self.is_eof() {
+                        match self.curr.unwrap() {
+                            '\n' => break,
+                            '\r' => {
+                                if self.nextch_is('\n') {
+                                    // CRLF
+                                    break
+                                } else if doc_comment {
+                                    self.err_span_(self.last_pos, self.pos,
+                                                   "bare CR not allowed in doc-comment");
                                 }
-                                _ => ()
                             }
-                            self.bump();
+                            _ => ()
                         }
-                        return self.with_str_from(start_bpos, |string| {
-                            // but comments with only more "/"s are not
+                        self.bump();
+                    }
+
+                    return if doc_comment {
+                        self.with_str_from(start_bpos, |string| {
+                            // comments with only more "/"s are not doc comments
                             let tok = if is_doc_comment(string) {
                                 token::DocComment(token::intern(string))
                             } else {
                                 token::Comment
                             };
 
-                            return Some(TokenAndSpan{
+                            Some(TokenAndSpan {
                                 tok: tok,
                                 sp: codemap::mk_sp(start_bpos, self.last_pos)
-                            });
-                        });
+                            })
+                        })
                     } else {
-                        let start_bpos = self.last_pos - BytePos(2);
-                        while !self.curr_is('\n') && !self.is_eof() { self.bump(); }
-                        return Some(TokenAndSpan {
+                        Some(TokenAndSpan {
                             tok: token::Comment,
                             sp: codemap::mk_sp(start_bpos, self.last_pos)
-                        });
+                        })
                     }
                 }
                 Some('*') => {
@@ -723,18 +729,18 @@ impl<'a> StringReader<'a> {
                             'n' | 'r' | 't' | '\\' | '\'' | '"' | '0' => true,
                             'x' => self.scan_byte_escape(delim, !ascii_only),
                             'u' if self.curr_is('{') => {
-                            let valid = self.scan_unicode_escape(delim);
-                            if valid && ascii_only {
-                                self.err_span_(
-                                    escaped_pos,
-                                    self.last_pos,
-                                    "unicode escape sequences cannot be used as a byte or in \
-                                    a byte string"
-                                );
-                                false
-                            } else {
-                               valid
-                            }
+                                let valid = self.scan_unicode_escape(delim);
+                                if valid && ascii_only {
+                                    self.err_span_(
+                                        escaped_pos,
+                                        self.last_pos,
+                                        "unicode escape sequences cannot be used as a byte or in \
+                                        a byte string"
+                                    );
+                                    false
+                                } else {
+                                   valid
+                                }
                             }
                             '\n' if delim == '"' => {
                                 self.consume_whitespace();
@@ -846,7 +852,7 @@ impl<'a> StringReader<'a> {
 
         if valid && (char::from_u32(accum_int).is_none() || count == 0) {
             self.err_span_(start_bpos, self.last_pos, "illegal unicode character escape");
-            valid= false;
+            valid = false;
         }
 
 
@@ -1406,8 +1412,8 @@ mod tests {
     fn mk_sh() -> diagnostic::SpanHandler {
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         let emitter = diagnostic::EmitterWriter::new(Box::new(io::sink()), None);
-        let handler = diagnostic::mk_handler(true, Box::new(emitter));
-        diagnostic::mk_span_handler(handler, CodeMap::new())
+        let handler = diagnostic::Handler::with_emitter(true, Box::new(emitter));
+        diagnostic::SpanHandler::new(handler, CodeMap::new())
     }
 
     // open a string reader for the given string
@@ -1563,4 +1569,13 @@ mod tests {
         assert_eq!(lexer.next_token().tok, token::Literal(token::Char(token::intern("a")), None));
     }
 
+    #[test] fn crlf_comments() {
+        let sh = mk_sh();
+        let mut lexer = setup(&sh, "// test\r\n/// test\r\n".to_string());
+        let comment = lexer.next_token();
+        assert_eq!(comment.tok, token::Comment);
+        assert_eq!(comment.sp, ::codemap::mk_sp(BytePos(0), BytePos(7)));
+        assert_eq!(lexer.next_token().tok, token::Whitespace);
+        assert_eq!(lexer.next_token().tok, token::DocComment(token::intern("/// test")));
+    }
 }
index 8c9ce5f78d482c4f9df632a17e2bc242a51f0f9e..d6c28d414479206c6ffadda2634647082fbd8b48 100644 (file)
 
 use ast;
 use codemap::{Span, CodeMap, FileMap};
-use diagnostic::{SpanHandler, mk_span_handler, default_handler, Auto, FatalError};
+use diagnostic::{SpanHandler, Handler, Auto, FatalError};
 use parse::attr::ParserAttr;
 use parse::parser::Parser;
 use ptr::P;
 use str::char_at;
 
-use std::cell::{Cell, RefCell};
-use std::fs::File;
+use std::cell::RefCell;
 use std::io::Read;
 use std::iter;
 use std::path::{Path, PathBuf};
@@ -44,38 +43,23 @@ pub struct ParseSess {
     pub span_diagnostic: SpanHandler, // better be the same as the one in the reader!
     /// Used to determine and report recursive mod inclusions
     included_mod_stack: RefCell<Vec<PathBuf>>,
-    pub node_id: Cell<ast::NodeId>,
-}
-
-pub fn new_parse_sess() -> ParseSess {
-    ParseSess {
-        span_diagnostic: mk_span_handler(default_handler(Auto, None, true), CodeMap::new()),
-        included_mod_stack: RefCell::new(Vec::new()),
-        node_id: Cell::new(1),
-    }
-}
-
-pub fn new_parse_sess_special_handler(sh: SpanHandler) -> ParseSess {
-    ParseSess {
-        span_diagnostic: sh,
-        included_mod_stack: RefCell::new(Vec::new()),
-        node_id: Cell::new(1),
-    }
 }
 
 impl ParseSess {
-    pub fn next_node_id(&self) -> ast::NodeId {
-        self.reserve_node_ids(1)
+    pub fn new() -> ParseSess {
+        let handler = SpanHandler::new(Handler::new(Auto, None, true), CodeMap::new());
+        ParseSess::with_span_handler(handler)
     }
-    pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
-        let v = self.node_id.get();
 
-        match v.checked_add(count) {
-            Some(next) => { self.node_id.set(next); }
-            None => panic!("Input too large, ran out of node ids!")
+    pub fn with_span_handler(sh: SpanHandler) -> ParseSess {
+        ParseSess {
+            span_diagnostic: sh,
+            included_mod_stack: RefCell::new(vec![])
         }
+    }
 
-        v
+    pub fn codemap(&self) -> &CodeMap {
+        &self.span_diagnostic.cm
     }
 }
 
@@ -189,7 +173,7 @@ pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
                                       name: String,
                                       source: String)
                                       -> Parser<'a> {
-    filemap_to_parser(sess, string_to_filemap(sess, source, name), cfg)
+    filemap_to_parser(sess, sess.codemap().new_filemap(name, source), cfg)
 }
 
 /// Create a new parser, handling errors as appropriate
@@ -235,41 +219,20 @@ pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
 
 /// Given a session and a path and an optional span (for error reporting),
 /// add the path to the session's codemap and return the new filemap.
-pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
-    -> Rc<FileMap> {
-    let err = |msg: &str| {
-        match spanopt {
-            Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, msg)),
-            None => sess.span_diagnostic.handler().fatal(msg),
-        }
-    };
-    let mut bytes = Vec::new();
-    match File::open(path).and_then(|mut f| f.read_to_end(&mut bytes)) {
-        Ok(..) => {}
+fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
+                   -> Rc<FileMap> {
+    match sess.codemap().load_file(path) {
+        Ok(filemap) => filemap,
         Err(e) => {
-            err(&format!("couldn't read {:?}: {}", path.display(), e));
-            unreachable!();
-        }
-    };
-    match str::from_utf8(&bytes[..]).ok() {
-        Some(s) => {
-            string_to_filemap(sess, s.to_string(),
-                              path.to_str().unwrap().to_string())
-        }
-        None => {
-            err(&format!("{:?} is not UTF-8 encoded", path.display()));
-            unreachable!();
+            let msg = format!("couldn't read {:?}: {}", path.display(), e);
+            match spanopt {
+                Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
+                None => sess.span_diagnostic.handler().fatal(&msg)
+            }
         }
     }
 }
 
-/// Given a session and a string, add the string to
-/// the session's codemap and return the new filemap
-pub fn string_to_filemap(sess: &ParseSess, source: String, path: String)
-                         -> Rc<FileMap> {
-    sess.span_diagnostic.cm.new_filemap(path, source)
-}
-
 /// Given a filemap, produce a sequence of token-trees
 pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
     -> Vec<ast::TokenTree> {
@@ -905,7 +868,7 @@ mod tests {
     }
 
     #[test] fn parse_ident_pat () {
-        let sess = new_parse_sess();
+        let sess = ParseSess::new();
         let mut parser = string_to_parser(&sess, "b".to_string());
         assert!(panictry!(parser.parse_pat_nopanic())
                 == P(ast::Pat{
@@ -960,6 +923,7 @@ mod tests {
                                 variadic: false
                             }),
                                     ast::Unsafety::Normal,
+                                    ast::Constness::NotConst,
                                     abi::Rust,
                                     ast::Generics{ // no idea on either of these:
                                         lifetimes: Vec::new(),
@@ -1086,7 +1050,7 @@ mod tests {
     }
 
     #[test] fn crlf_doc_comments() {
-        let sess = new_parse_sess();
+        let sess = ParseSess::new();
 
         let name = "<source>".to_string();
         let source = "/// doc comment\r\nfn foo() {}".to_string();
@@ -1109,7 +1073,7 @@ mod tests {
 
     #[test]
     fn ttdelim_span() {
-        let sess = parse::new_parse_sess();
+        let sess = ParseSess::new();
         let expr = parse::parse_expr_from_source_str("foo".to_string(),
             "foo!( fn main() { body } )".to_string(), vec![], &sess);
 
@@ -1123,7 +1087,7 @@ mod tests {
 
         let span = tts.iter().rev().next().unwrap().get_span();
 
-        match sess.span_diagnostic.cm.span_to_snippet(span) {
+        match sess.codemap().span_to_snippet(span) {
             Ok(s) => assert_eq!(&s[..], "{ body }"),
             Err(_) => panic!("could not get snippet"),
         }
index 9bf6fa88ba5531d48e61fce29a2fb34548a9f8c9..03c788aee584b7638f93d312182cb331d1b9c23d 100644 (file)
@@ -17,7 +17,7 @@ use ast::{Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block};
 use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
-use ast::{ConstImplItem, ConstTraitItem, Crate, CrateConfig};
+use ast::{Constness, ConstImplItem, ConstTraitItem, Crate, CrateConfig};
 use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn};
 use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
@@ -79,7 +79,6 @@ use parse::PResult;
 use diagnostic::FatalError;
 
 use std::collections::HashSet;
-use std::fs;
 use std::io::prelude::*;
 use std::mem;
 use std::path::{Path, PathBuf};
@@ -1061,7 +1060,7 @@ impl<'a> Parser<'a> {
             };
             let all_bounds =
                 Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
-                .chain(other_bounds.into_vec().into_iter())
+                .chain(other_bounds.into_vec())
                 .collect();
             Ok(ast::TyPolyTraitRef(all_bounds))
         }
@@ -1161,7 +1160,8 @@ impl<'a> Parser<'a> {
                 let TyParam {ident, bounds, default, ..} = try!(p.parse_ty_param());
                 try!(p.expect(&token::Semi));
                 (ident, TypeTraitItem(bounds, default))
-            } else if try!(p.eat_keyword(keywords::Const)) {
+            } else if p.is_const_item() {
+                try!(p.expect_keyword(keywords::Const));
                 let ident = try!(p.parse_ident());
                 try!(p.expect(&token::Colon));
                 let ty = try!(p.parse_ty_sum());
@@ -1176,13 +1176,7 @@ impl<'a> Parser<'a> {
                 };
                 (ident, ConstTraitItem(ty, default))
             } else {
-                let style = try!(p.parse_unsafety());
-                let abi = if try!(p.eat_keyword(keywords::Extern)) {
-                    try!(p.parse_opt_abi()).unwrap_or(abi::C)
-                } else {
-                    abi::Rust
-                };
-                try!(p.expect_keyword(keywords::Fn));
+                let (constness, unsafety, abi) = try!(p.parse_fn_front_matter());
 
                 let ident = try!(p.parse_ident());
                 let mut generics = try!(p.parse_generics());
@@ -1196,7 +1190,8 @@ impl<'a> Parser<'a> {
 
                 generics.where_clause = try!(p.parse_where_clause());
                 let sig = ast::MethodSig {
-                    unsafety: style,
+                    unsafety: unsafety,
+                    constness: constness,
                     decl: d,
                     generics: generics,
                     abi: abi,
@@ -2026,7 +2021,8 @@ impl<'a> Parser<'a> {
                 return self.parse_block_expr(lo, DefaultBlock);
             },
             token::BinOp(token::Or) |  token::OrOr => {
-                return self.parse_lambda_expr(CaptureByRef);
+                let lo = self.span.lo;
+                return self.parse_lambda_expr(lo, CaptureByRef);
             },
             token::Ident(id @ ast::Ident {
                             name: token::SELF_KEYWORD_NAME,
@@ -2062,7 +2058,7 @@ impl<'a> Parser<'a> {
                             |p| Ok(try!(p.parse_expr_nopanic()))
                                 ));
                         let mut exprs = vec!(first_expr);
-                        exprs.extend(remaining_exprs.into_iter());
+                        exprs.extend(remaining_exprs);
                         ex = ExprVec(exprs);
                     } else {
                         // Vector with one element.
@@ -2074,14 +2070,14 @@ impl<'a> Parser<'a> {
             }
             _ => {
                 if try!(self.eat_lt()){
-
                     let (qself, path) =
                         try!(self.parse_qualified_path(LifetimeAndTypesWithColons));
-
+                    hi = path.span.hi;
                     return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path)));
                 }
                 if try!(self.eat_keyword(keywords::Move) ){
-                    return self.parse_lambda_expr(CaptureByValue);
+                    let lo = self.last_span.lo;
+                    return self.parse_lambda_expr(lo, CaptureByValue);
                 }
                 if try!(self.eat_keyword(keywords::If)) {
                     return self.parse_if_expr();
@@ -2840,10 +2836,9 @@ impl<'a> Parser<'a> {
     }
 
     // `|args| expr`
-    pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
+    pub fn parse_lambda_expr(&mut self, lo: BytePos, capture_clause: CaptureClause)
                              -> PResult<P<Expr>>
     {
-        let lo = self.span.lo;
         let decl = try!(self.parse_fn_block_decl());
         let body = match decl.output {
             DefaultReturn(_) => {
@@ -3399,7 +3394,10 @@ impl<'a> Parser<'a> {
     /// Parse a structure field
     fn parse_name_and_ty(&mut self, pr: Visibility,
                          attrs: Vec<Attribute> ) -> PResult<StructField> {
-        let lo = self.span.lo;
+        let lo = match pr {
+            Inherited => self.span.lo,
+            Public => self.last_span.lo,
+        };
         if !self.token.is_plain_ident() {
             return Err(self.fatal("expected ident"));
         }
@@ -4217,7 +4215,7 @@ impl<'a> Parser<'a> {
                 };
                 if self.is_self_ident() {
                     let span = self.span;
-                    self.span_err(span, "cannot pass self by unsafe pointer");
+                    self.span_err(span, "cannot pass self by raw pointer");
                     try!(self.bump());
                 }
                 // error case, making bogus self ident:
@@ -4359,12 +4357,46 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse an item-position function declaration.
-    fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> PResult<ItemInfo> {
+    fn parse_item_fn(&mut self,
+                     unsafety: Unsafety,
+                     constness: Constness,
+                     abi: abi::Abi)
+                     -> PResult<ItemInfo> {
         let (ident, mut generics) = try!(self.parse_fn_header());
         let decl = try!(self.parse_fn_decl(false));
         generics.where_clause = try!(self.parse_where_clause());
         let (inner_attrs, body) = try!(self.parse_inner_attrs_and_block());
-        Ok((ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs)))
+        Ok((ident, ItemFn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs)))
+    }
+
+    /// 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))
+    }
+
+    /// parses all the "front matter" for a `fn` declaration, up to
+    /// and including the `fn` keyword:
+    ///
+    /// - `const fn`
+    /// - `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 (constness, unsafety, abi) = if is_const_fn {
+            (Constness::Const, Unsafety::Normal, 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 {
+                abi::Rust
+            };
+            (Constness::NotConst, unsafety, abi)
+        };
+        try!(self.expect_keyword(keywords::Fn));
+        Ok((constness, unsafety, abi))
     }
 
     /// Parse an impl item.
@@ -4380,7 +4412,8 @@ impl<'a> Parser<'a> {
             let typ = try!(self.parse_ty_sum());
             try!(self.expect(&token::Semi));
             (name, TypeImplItem(typ))
-        } else if try!(self.eat_keyword(keywords::Const)) {
+        } else if self.is_const_item() {
+            try!(self.expect_keyword(keywords::Const));
             let name = try!(self.parse_ident());
             try!(self.expect(&token::Colon));
             let typ = try!(self.parse_ty_sum());
@@ -4390,7 +4423,7 @@ impl<'a> Parser<'a> {
             (name, ConstImplItem(typ, expr))
         } else {
             let (name, inner_attrs, node) = try!(self.parse_impl_method(vis));
-            attrs.extend(inner_attrs.into_iter());
+            attrs.extend(inner_attrs);
             (name, node)
         };
 
@@ -4445,13 +4478,7 @@ impl<'a> Parser<'a> {
             }
             Ok((token::special_idents::invalid, vec![], ast::MacImplItem(m)))
         } 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 {
-                abi::Rust
-            };
-            try!(self.expect_keyword(keywords::Fn));
+            let (constness, unsafety, abi) = try!(self.parse_fn_front_matter());
             let ident = try!(self.parse_ident());
             let mut generics = try!(self.parse_generics());
             let (explicit_self, decl) = try!(self.parse_fn_decl_with_self(|p| {
@@ -4464,6 +4491,7 @@ impl<'a> Parser<'a> {
                 abi: abi,
                 explicit_self: explicit_self,
                 unsafety: unsafety,
+                constness: constness,
                 decl: decl
              }, body)))
         }
@@ -4538,7 +4566,7 @@ impl<'a> Parser<'a> {
         if try!(self.eat(&token::DotDot) ){
             if generics.is_parameterized() {
                 self.span_err(impl_span, "default trait implementations are not \
-                                          allowed to have genercis");
+                                          allowed to have generics");
             }
 
             try!(self.expect(&token::OpenDelim(token::Brace)));
@@ -4839,8 +4867,7 @@ impl<'a> Parser<'a> {
                     outer_attrs: &[ast::Attribute],
                     id_sp: Span)
                     -> PResult<(ast::Item_, Vec<ast::Attribute> )> {
-        let mut prefix = PathBuf::from(&self.sess.span_diagnostic.cm
-                                            .span_to_filename(self.span));
+        let mut prefix = PathBuf::from(&self.sess.codemap().span_to_filename(self.span));
         prefix.pop();
         let mut dir_path = prefix;
         for part in &self.mod_path_stack {
@@ -4856,8 +4883,8 @@ impl<'a> Parser<'a> {
                 let secondary_path_str = format!("{}/mod.rs", mod_name);
                 let default_path = dir_path.join(&default_path_str[..]);
                 let secondary_path = dir_path.join(&secondary_path_str[..]);
-                let default_exists = fs::metadata(&default_path).is_ok();
-                let secondary_exists = fs::metadata(&secondary_path).is_ok();
+                let default_exists = self.sess.codemap().file_exists(&default_path);
+                let secondary_exists = self.sess.codemap().file_exists(&secondary_path);
 
                 if !self.owns_directory {
                     self.span_err(id_sp,
@@ -5041,7 +5068,7 @@ impl<'a> Parser<'a> {
 
         let abi = opt_abi.unwrap_or(abi::C);
 
-        attrs.extend(self.parse_inner_attributes().into_iter());
+        attrs.extend(self.parse_inner_attributes());
 
         let mut foreign_items = vec![];
         while let Some(item) = try!(self.parse_foreign_item()) {
@@ -5217,7 +5244,7 @@ impl<'a> Parser<'a> {
                 try!(self.bump());
                 let mut attrs = attrs;
                 mem::swap(&mut item.attrs, &mut attrs);
-                item.attrs.extend(attrs.into_iter());
+                item.attrs.extend(attrs);
                 return Ok(Some(P(item)));
             }
             None => {}
@@ -5253,7 +5280,7 @@ impl<'a> Parser<'a> {
                 // EXTERN FUNCTION ITEM
                 let abi = opt_abi.unwrap_or(abi::C);
                 let (ident, item_, extra_attrs) =
-                    try!(self.parse_item_fn(Unsafety::Normal, abi));
+                    try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi));
                 let last_span = self.last_span;
                 let item = self.mk_item(lo,
                                         last_span.hi,
@@ -5266,11 +5293,7 @@ impl<'a> Parser<'a> {
                 return Ok(Some(try!(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs))));
             }
 
-            let span = self.span;
-            let token_str = self.this_token_to_string();
-            return Err(self.span_fatal(span,
-                            &format!("expected `{}` or `fn`, found `{}`", "{",
-                                    token_str)))
+            try!(self.expect_one_of(&[], &[]));
         }
 
         if try!(self.eat_keyword_noexpect(keywords::Virtual) ){
@@ -5292,6 +5315,21 @@ impl<'a> Parser<'a> {
             return Ok(Some(item));
         }
         if try!(self.eat_keyword(keywords::Const) ){
+            if self.check_keyword(keywords::Fn) {
+                // CONST FUNCTION ITEM
+                try!(self.bump());
+                let (ident, item_, extra_attrs) =
+                    try!(self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust));
+                let last_span = self.last_span;
+                let item = self.mk_item(lo,
+                                        last_span.hi,
+                                        ident,
+                                        item_,
+                                        visibility,
+                                        maybe_append(attrs, extra_attrs));
+                return Ok(Some(item));
+            }
+
             // CONST ITEM
             if try!(self.eat_keyword(keywords::Mut) ){
                 let last_span = self.last_span;
@@ -5345,7 +5383,7 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             try!(self.bump());
             let (ident, item_, extra_attrs) =
-                try!(self.parse_item_fn(Unsafety::Normal, abi::Rust));
+                try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi::Rust));
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5366,7 +5404,7 @@ impl<'a> Parser<'a> {
             };
             try!(self.expect_keyword(keywords::Fn));
             let (ident, item_, extra_attrs) =
-                try!(self.parse_item_fn(Unsafety::Unsafe, abi));
+                try!(self.parse_item_fn(Unsafety::Unsafe, Constness::NotConst, abi));
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
index b71d65a8fb0c5dcafdd173deefdf6e847ac6dd6c..3adb73cfa5d6f1793306b721b5f022f366041096 100644 (file)
@@ -378,12 +378,16 @@ pub fn ident_to_string(id: &ast::Ident) -> String {
     to_string(|s| s.print_ident(*id))
 }
 
-pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident,
-                  opt_explicit_self: Option<&ast::ExplicitSelf_>,
-                  generics: &ast::Generics) -> String {
+pub fn fun_to_string(decl: &ast::FnDecl,
+                     unsafety: ast::Unsafety,
+                     constness: ast::Constness,
+                     name: ast::Ident,
+                     opt_explicit_self: Option<&ast::ExplicitSelf_>,
+                     generics: &ast::Generics)
+                     -> String {
     to_string(|s| {
         try!(s.head(""));
-        try!(s.print_fn(decl, unsafety, abi::Rust, Some(name),
+        try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name),
                         generics, opt_explicit_self, ast::Inherited));
         try!(s.end()); // Close the head box
         s.end() // Close the outer box
@@ -740,7 +744,8 @@ impl<'a> State<'a> {
         match item.node {
             ast::ForeignItemFn(ref decl, ref generics) => {
                 try!(self.head(""));
-                try!(self.print_fn(&**decl, ast::Unsafety::Normal,
+                try!(self.print_fn(decl, ast::Unsafety::Normal,
+                                   ast::Constness::NotConst,
                                    abi::Rust, Some(item.ident),
                                    generics, None, item.vis));
                 try!(self.end()); // end head-ibox
@@ -866,11 +871,12 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer cbox
             }
-            ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => {
+            ast::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,
@@ -1241,6 +1247,7 @@ impl<'a> State<'a> {
                             -> io::Result<()> {
         self.print_fn(&m.decl,
                       m.unsafety,
+                      m.constness,
                       m.abi,
                       Some(ident),
                       &m.generics,
@@ -2103,7 +2110,7 @@ impl<'a> State<'a> {
                         comma = true;
                 }
 
-                for binding in &*data.bindings {
+                for binding in data.bindings.iter() {
                     if comma {
                         try!(self.word_space(","))
                     }
@@ -2335,12 +2342,13 @@ impl<'a> State<'a> {
     pub fn print_fn(&mut self,
                     decl: &ast::FnDecl,
                     unsafety: ast::Unsafety,
+                    constness: ast::Constness,
                     abi: abi::Abi,
                     name: Option<ast::Ident>,
                     generics: &ast::Generics,
                     opt_explicit_self: Option<&ast::ExplicitSelf_>,
                     vis: ast::Visibility) -> io::Result<()> {
-        try!(self.print_fn_header_info(unsafety, abi, vis));
+        try!(self.print_fn_header_info(unsafety, constness, abi, vis));
 
         if let Some(name) = name {
             try!(self.nbsp());
@@ -2726,8 +2734,13 @@ impl<'a> State<'a> {
                 predicates: Vec::new(),
             },
         };
-        try!(self.print_fn(decl, unsafety, abi, name,
-                           &generics, opt_explicit_self,
+        try!(self.print_fn(decl,
+                           unsafety,
+                           ast::Constness::NotConst,
+                           abi,
+                           name,
+                           &generics,
+                           opt_explicit_self,
                            ast::Inherited));
         self.end()
     }
@@ -2832,7 +2845,7 @@ impl<'a> State<'a> {
             }
             ast::LitBinary(ref v) => {
                 let mut escaped: String = String::new();
-                for &ch in &**v {
+                for &ch in v.iter() {
                     escaped.extend(ascii::escape_default(ch)
                                          .map(|c| c as char));
                 }
@@ -2976,11 +2989,17 @@ impl<'a> State<'a> {
 
     pub fn print_fn_header_info(&mut self,
                                 unsafety: ast::Unsafety,
+                                constness: ast::Constness,
                                 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"))
+        }
+
         if abi != abi::Rust {
             try!(self.word_nbsp("extern"));
             try!(self.word_nbsp(&abi.to_string()));
@@ -3018,8 +3037,10 @@ mod tests {
             variadic: false
         };
         let generics = ast_util::empty_generics();
-        assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, abba_ident,
-                               None, &generics),
+        assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
+                                 ast::Constness::NotConst,
+                                 abba_ident,
+                                 None, &generics),
                    "fn abba()");
     }
 
index a3cfb647853d23f01c0bf910d516182efdb22f60..cbc7b38b1ed29e80adb108bf7fbab5eb9f5d9121 100644 (file)
@@ -123,7 +123,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
 
         let i = if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) {
             match i.node {
-                ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => {
+                ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _, _) => {
                     let diag = self.cx.span_diagnostic;
                     panic!(diag.span_fatal(i.span, "unsafe functions cannot be used for tests"));
                 }
@@ -301,7 +301,7 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
             allow_internal_unstable: true,
         }
     };
-    let expn_id = cx.sess.span_diagnostic.cm.record_expansion(info);
+    let expn_id = cx.sess.codemap().record_expansion(info);
     let mut sp = sp;
     sp.expn_id = expn_id;
     return sp;
@@ -320,7 +320,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
 
     fn has_test_signature(i: &ast::Item) -> HasTestSignature {
         match &i.node {
-          &ast::ItemFn(ref decl, _, _, ref generics, _) => {
+          &ast::ItemFn(ref decl, _, _, _, ref generics, _) => {
             let no_output = match decl.output {
                 ast::DefaultReturn(..) => true,
                 ast::Return(ref t) if t.node == ast::TyTup(vec![]) => true,
@@ -356,7 +356,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
 
     fn has_test_signature(i: &ast::Item) -> bool {
         match i.node {
-            ast::ItemFn(ref decl, _, _, ref generics, _) => {
+            ast::ItemFn(ref decl, _, _, _, ref generics, _) => {
                 let input_cnt = decl.inputs.len();
                 let no_output = match decl.output {
                     ast::DefaultReturn(..) => true,
@@ -469,7 +469,9 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
     let main_ret_ty = ecx.ty(sp, ast::TyTup(vec![]));
     let main_body = ecx.block_all(sp, vec![call_test_main], None);
     let main = ast::ItemFn(ecx.fn_decl(vec![], main_ret_ty),
-                           ast::Unsafety::Normal, ::abi::Rust, empty_generics(), main_body);
+                           ast::Unsafety::Normal,
+                           ast::Constness::NotConst,
+                           ::abi::Rust, empty_generics(), main_body);
     let main = P(ast::Item {
         ident: token::str_to_ident("main"),
         attrs: vec![main_attr],
@@ -656,7 +658,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             diag.handler.bug("expected to find top-level re-export name, but found None");
         }
     };
-    visible_path.extend(path.into_iter());
+    visible_path.extend(path);
 
     let fn_expr = ecx.expr_path(ecx.path_global(span, visible_path));
 
index 929f2a6abd6b8c5adde72337394d39eebcda3702..6e6e2d181b9ef195f3b2f16a85052d062557b40c 100644 (file)
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use ast;
-use parse::new_parse_sess;
-use parse::{ParseSess,string_to_filemap,filemap_to_tts};
+use parse::{ParseSess,filemap_to_tts};
 use parse::new_parser_from_source_str;
 use parse::parser::Parser;
 use parse::token;
@@ -19,9 +18,8 @@ use str::char_at;
 
 /// Map a string to tts, using a made-up filename:
 pub fn string_to_tts(source_str: String) -> Vec<ast::TokenTree> {
-    let ps = new_parse_sess();
-    filemap_to_tts(&ps,
-                   string_to_filemap(&ps, source_str, "bogofile".to_string()))
+    let ps = ParseSess::new();
+    filemap_to_tts(&ps, ps.codemap().new_filemap("bogofile".to_string(), source_str))
 }
 
 /// Map string to parser (via tts)
@@ -35,7 +33,7 @@ pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a>
 fn with_error_checking_parse<T, F>(s: String, f: F) -> T where
     F: FnOnce(&mut Parser) -> T,
 {
-    let ps = new_parse_sess();
+    let ps = ParseSess::new();
     let mut p = string_to_parser(&ps, s);
     let x = f(&mut p);
     p.abort_if_errors();
@@ -75,7 +73,7 @@ pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> {
 pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
     // Binding `sess` and `parser` works around dropck-injected
     // region-inference issues; see #25212, #22323, #22321.
-    let sess = new_parse_sess();
+    let sess = ParseSess::new();
     let mut parser = string_to_parser(&sess, source_str);
     parser.parse_pat()
 }
index 6cf791b10be67612eaa75ad146d630fafb1a5602..710928a00c11d44209bb03f9250bd00edf98b23f 100644 (file)
@@ -35,7 +35,7 @@ use owned_slice::OwnedSlice;
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
-    FkItemFn(Ident, &'a Generics, Unsafety, Abi, Visibility),
+    FkItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, Visibility),
 
     /// fn foo(&self)
     FkMethod(Ident, &'a MethodSig, Option<Visibility>),
@@ -246,8 +246,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_ty(&**typ);
             visitor.visit_expr(&**expr);
         }
-        ItemFn(ref declaration, fn_style, abi, ref generics, ref body) => {
-            visitor.visit_fn(FkItemFn(item.ident, generics, fn_style, abi, item.vis),
+        ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+            visitor.visit_fn(FkItemFn(item.ident, generics, unsafety,
+                                      constness, abi, item.vis),
                              &**declaration,
                              &**body,
                              item.span,
@@ -427,13 +428,13 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 path_parameters: &'v PathParameters) {
     match *path_parameters {
         ast::AngleBracketedParameters(ref data) => {
-            for typ in &*data.types {
+            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 {
+            for binding in data.bindings.iter() {
                 visitor.visit_assoc_type_binding(&**binding);
             }
         }
@@ -530,7 +531,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
 
 pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
                                                        bounds: &'v OwnedSlice<TyParamBound>) {
-    for bound in &**bounds {
+    for bound in bounds.iter() {
         visitor.visit_ty_param_bound(bound)
     }
 }
@@ -548,7 +549,7 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
-    for param in &*generics.ty_params {
+    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);
@@ -604,7 +605,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
     walk_fn_decl(visitor, function_declaration);
 
     match function_kind {
-        FkItemFn(_, generics, _, _, _) => {
+        FkItemFn(_, generics, _, _, _, _) => {
             visitor.visit_generics(generics);
         }
         FkMethod(_, sig, _) => {
index 74ec3406f73bc3a735f640dfdb9375a9566acd25..5131e0b34e380ebf84e378ab443333a397f4ae82 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![deny(missing_docs)]
 
 #![feature(box_syntax)]
-#![feature(collections)]
+#![feature(owned_ascii_ext)]
+#![feature(path_ext)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(std_misc)]
 #![feature(str_char)]
-#![feature(path_ext)]
+#![feature(vec_push_all)]
 #![cfg_attr(windows, feature(libc))]
 
 #[macro_use] extern crate log;
index 2b8c24741ae7ccb0e2c6b94c61f2f628aed8dbad..9af751debc38426228a50e5d02e6c7d5e6e498ce 100644 (file)
@@ -105,7 +105,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
         Number(0), Number(0), Number(0), Number(0), Number(0),
         Number(0), Number(0), Number(0), Number(0),
     ];
-    for (dst, src) in mparams.iter_mut().zip(params.iter()) {
+    for (dst, src) in mparams.iter_mut().zip(params) {
         *dst = (*src).clone();
     }
 
@@ -510,7 +510,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8> ,String> {
                 let mut s_ = Vec::with_capacity(flags.precision);
                 let n = flags.precision - s.len();
                 s_.extend(repeat(b'0').take(n));
-                s_.extend(s.into_iter());
+                s_.extend(s);
                 s = s_;
             }
             assert!(!s.is_empty(), "string conversion produced empty result");
@@ -528,14 +528,14 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8> ,String> {
                 FormatHex => {
                     if flags.alternate {
                         let s_ = replace(&mut s, vec!(b'0', b'x'));
-                        s.extend(s_.into_iter());
+                        s.extend(s_);
                     }
                 }
                 FormatHEX => {
                     s = s.into_ascii_uppercase();
                     if flags.alternate {
                         let s_ = replace(&mut s, vec!(b'0', b'X'));
-                        s.extend(s_.into_iter());
+                        s.extend(s_);
                     }
                 }
                 FormatString => unreachable!()
@@ -565,7 +565,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8> ,String> {
         } else {
             let mut s_ = Vec::with_capacity(flags.width);
             s_.extend(repeat(b' ').take(n));
-            s_.extend(s.into_iter());
+            s_.extend(s);
             s = s_;
         }
     }
index b16154861530dc70a61ddefb7beafc615b098bfc..0a3c350086cdd125e3271d7edf77a132afdcbb9d 100644 (file)
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(asm)]
 #![feature(box_syntax)]
-#![feature(collections)]
-#![feature(core)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
-#![feature(std_misc)]
-#![feature(libc)]
-#![feature(set_stdio)]
 #![feature(duration)]
 #![feature(duration_span)]
+#![feature(fnbox)]
+#![feature(iter_cmp)]
+#![feature(libc)]
+#![feature(rt)]
+#![feature(rustc_private)]
+#![feature(set_stdio)]
+#![feature(slice_extras)]
+#![feature(staged_api)]
 
 extern crate getopts;
 extern crate serialize;
@@ -80,7 +81,6 @@ use std::path::PathBuf;
 use std::sync::mpsc::{channel, Sender};
 use std::sync::{Arc, Mutex};
 use std::thread;
-use std::thunk::Thunk;
 use std::time::Duration;
 
 // to be used by rustc to compile tests in libtest
@@ -127,7 +127,7 @@ enum NamePadding {
 
 impl TestDesc {
     fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
-        let mut name = String::from_str(self.name.as_slice());
+        let mut name = String::from(self.name.as_slice());
         let fill = column_count.saturating_sub(name.len());
         let pad = repeat(" ").take(fill).collect::<String>();
         match align {
@@ -153,7 +153,7 @@ pub enum TestFn {
     StaticTestFn(fn()),
     StaticBenchFn(fn(&mut Bencher)),
     StaticMetricFn(fn(&mut MetricMap)),
-    DynTestFn(Thunk<'static>),
+    DynTestFn(Box<FnBox() + Send>),
     DynMetricFn(Box<FnBox(&mut MetricMap)+Send>),
     DynBenchFn(Box<TDynBenchFn+'static>)
 }
@@ -625,17 +625,44 @@ impl<T: Write> ConsoleTestState<T> {
     }
 }
 
+// Format a number with thousands separators
+fn fmt_thousands_sep(mut n: usize, sep: char) -> String {
+    use std::fmt::Write;
+    let mut output = String::new();
+    let mut trailing = false;
+    for &pow in &[9, 6, 3, 0] {
+        let base = 10_usize.pow(pow);
+        if pow == 0 || trailing || n / base != 0 {
+            if !trailing {
+                output.write_fmt(format_args!("{}", n / base)).unwrap();
+            } else {
+                output.write_fmt(format_args!("{:03}", n / base)).unwrap();
+            }
+            if pow != 0 {
+                output.push(sep);
+            }
+            trailing = true;
+        }
+        n %= base;
+    }
+
+    output
+}
+
 pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
+    use std::fmt::Write;
+    let mut output = String::new();
+
+    let median = bs.ns_iter_summ.median as usize;
+    let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
+
+    output.write_fmt(format_args!("{:>11} ns/iter (+/- {})",
+                     fmt_thousands_sep(median, ','),
+                     fmt_thousands_sep(deviation, ','))).unwrap();
     if bs.mb_s != 0 {
-        format!("{:>9} ns/iter (+/- {}) = {} MB/s",
-             bs.ns_iter_summ.median as usize,
-             (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize,
-             bs.mb_s)
-    } else {
-        format!("{:>9} ns/iter (+/- {})",
-             bs.ns_iter_summ.median as usize,
-             (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize)
+        output.write_fmt(format_args!(" = {} MB/s", bs.mb_s)).unwrap();
     }
+    output
 }
 
 // A simple console test runner
@@ -740,7 +767,7 @@ fn should_sort_failures_before_printing_them() {
 
 fn use_color(opts: &TestOpts) -> bool {
     match opts.color {
-        AutoColor => get_concurrency() == 1 && stdout_isatty(),
+        AutoColor => !opts.nocapture && stdout_isatty(),
         AlwaysColor => true,
         NeverColor => false,
     }
@@ -932,7 +959,7 @@ pub fn run_test(opts: &TestOpts,
     fn run_test_inner(desc: TestDesc,
                       monitor_ch: Sender<MonitorMsg>,
                       nocapture: bool,
-                      testfn: Thunk<'static>) {
+                      testfn: Box<FnBox() + Send>) {
         struct Sink(Arc<Mutex<Vec<u8>>>);
         impl Write for Sink {
             fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@@ -1200,7 +1227,6 @@ mod tests {
                TestDesc, TestDescAndFn, TestOpts, run_test,
                MetricMap,
                StaticTestName, DynTestName, DynTestFn, ShouldPanic};
-    use std::thunk::Thunk;
     use std::sync::mpsc::channel;
 
     #[test]
@@ -1396,7 +1422,7 @@ mod tests {
                  "test::parse_ignored_flag".to_string(),
                  "test::sort_tests".to_string());
 
-        for (a, b) in expected.iter().zip(filtered.iter()) {
+        for (a, b) in expected.iter().zip(filtered) {
             assert!(*a == b.desc.name.to_string());
         }
     }
index 2f03251e54ae5e8a26f878c42beb31d0803ac85b..98fdfdf3402efdf0735f244076843e3a582fead6 100644 (file)
@@ -75,7 +75,7 @@
 #else
 #if defined(__linux__) || defined(__FreeBSD__)
 #define MORESTACK               __morestack
-#define EXHAUSTED               rust_stack_exhausted
+#define EXHAUSTED               rust_stack_exhausted@plt
 #else
 #define MORESTACK               ___morestack
 #define EXHAUSTED               _rust_stack_exhausted
@@ -83,7 +83,6 @@
 #endif
 
 .globl MORESTACK
-.globl EXHAUSTED
 
 // FIXME: What about __WIN32__?
 #if defined(__linux__) || defined(__FreeBSD__)
@@ -138,7 +137,7 @@ MORESTACK:
 
         // re-align the stack
         subl $12,%esp
-        calll EXHAUSTED
+        call EXHAUSTED
         // the exhaustion function guarantees that it can't return
 
        .cfi_endproc
index 362439c146912dae5f05ebcd51de749e8d90e22d..1a2917a1dd67f9c8d0251fff51b1d8b0cbc425b4 100644 (file)
@@ -14,7 +14,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#if !defined(__WIN32__)
+
+#if !defined(_WIN32)
 #include <dirent.h>
 #include <pthread.h>
 #include <signal.h>
 
 /* Foreign builtins. */
 //include valgrind.h after stdint.h so that uintptr_t is defined for msys2 w64
+#ifndef _WIN32
 #include "valgrind/valgrind.h"
+#endif
+
+#if defined(_MSC_VER)
+# define RUST_BUILTIN_API __declspec(dllexport)
+#else
+# define RUST_BUILTIN_API
+#endif
 
 #ifndef _WIN32
 char*
@@ -50,7 +59,7 @@ rust_list_dir_val(struct dirent* entry_ptr) {
 
 int
 rust_dir_get_mode(struct dirent* entry_ptr) {
-#if defined(_DIRENT_HAVE_D_TYPE)
+#if defined(_DIRENT_HAVE_D_TYPE) || defined(__APPLE__)
     switch (entry_ptr->d_type) {
         case DT_BLK: return S_IFBLK;
         case DT_CHR: return S_IFCHR;
@@ -58,6 +67,7 @@ rust_dir_get_mode(struct dirent* entry_ptr) {
         case DT_LNK: return S_IFLNK;
         case DT_REG: return S_IFREG;
         case DT_SOCK: return S_IFSOCK;
+        case DT_DIR: return S_IFDIR;
     }
 #endif
     return -1;
@@ -84,12 +94,7 @@ rust_dirent_t_size() {
 }
 #endif
 
-uintptr_t
-rust_running_on_valgrind() {
-    return RUNNING_ON_VALGRIND;
-}
-
-#if defined(__WIN32__)
+#if defined(_WIN32)
 int
 get_num_cpus() {
     SYSTEM_INFO sysinfo;
@@ -131,19 +136,19 @@ get_num_cpus() {
 }
 #endif
 
+RUST_BUILTIN_API
 uintptr_t
 rust_get_num_cpus() {
     return get_num_cpus();
 }
 
-unsigned int
-rust_valgrind_stack_register(void *start, void *end) {
-  return VALGRIND_STACK_REGISTER(start, end);
-}
-
-void
-rust_valgrind_stack_deregister(unsigned int id) {
-  VALGRIND_STACK_DEREGISTER(id);
+uintptr_t
+rust_running_on_valgrind() {
+#ifdef _WIN32
+    return 0;
+#else
+    return RUNNING_ON_VALGRIND;
+#endif
 }
 
 #if defined(__DragonFly__)
index c755cf67caa9f6b52dad2e8007673b6fc1bd8f94..8824cef2a816c153ea468796cebea190d99a91f6 100644 (file)
@@ -135,6 +135,8 @@ struct ManyInts {
     struct TwoU8s arg6;
 };
 
+// MSVC doesn't allow empty structs or unions
+#ifndef _MSC_VER
 struct Empty {
 };
 
@@ -148,6 +150,7 @@ rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts
     assert(v1.arg6.one == v2.arg6.one + 1);
     assert(v1.arg6.two == v2.arg6.two + 1);
 }
+#endif
 
 intptr_t
 rust_get_test_int() {
@@ -191,9 +194,7 @@ rust_dbg_abi_2(struct floats f) {
 }
 
 int
-rust_dbg_static_mut;
-
-int rust_dbg_static_mut = 3;
+rust_dbg_static_mut = 3;
 
 void
 rust_dbg_static_mut_check_four() {
index 042b955d13c3fd40e69bb7ec694277ab2622f57b..744c1c2e2a71e0a767984561480b822e92437e0c 100644 (file)
@@ -336,9 +336,13 @@ get_host_triple() {
             _ostype=unknown-dragonfly
             ;;
 
-        OpenBSD)
+       Bitrig)
+            _ostype=unknown-bitrig
+            ;;
+
+       OpenBSD)
             _ostype=unknown-openbsd
-           ;;
+            ;;
 
        Darwin)
             _ostype=apple-darwin
index 47bdc9335c4019819de309ac70da326c1c528162..a7a6ed3bfe749503cbe5a8b1cb618c8dca3c1b6a 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.
 //
@@ -37,27 +37,34 @@ pub fn parse_cmd(name: &str) -> Option<Box<Subcommand>> {
     }
 }
 
-fn write_toc(book: &Book, path_to_root: &Path, out: &mut Write) -> io::Result<()> {
+fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Result<()> {
     fn walk_items(items: &[BookItem],
                   section: &str,
-                  path_to_root: &Path,
+                  current_page: &BookItem,
                   out: &mut Write) -> io::Result<()> {
         for (i, item) in items.iter().enumerate() {
-            try!(walk_item(item, &format!("{}{}.", section, i + 1)[..], path_to_root, out));
+            try!(walk_item(item, &format!("{}{}.", section, i + 1)[..], current_page, out));
         }
         Ok(())
     }
     fn walk_item(item: &BookItem,
                  section: &str,
-                 path_to_root: &Path,
+                 current_page: &BookItem,
                  out: &mut Write) -> io::Result<()> {
-        try!(writeln!(out, "<li><a href='{}'><b>{}</b> {}</a>",
-                 path_to_root.join(&item.path.with_extension("html")).display(),
+        let class_string = if item.path == current_page.path {
+          "class='active'"
+        } else {
+        ""
+        };
+
+        try!(writeln!(out, "<li><a {} href='{}'><b>{}</b> {}</a>",
+                 class_string,
+                 current_page.path_to_root.join(&item.path).with_extension("html").display(),
                  section,
                  item.title));
         if !item.children.is_empty() {
             try!(writeln!(out, "<ul class='section'>"));
-            let _ = walk_items(&item.children[..], section, path_to_root, out);
+            let _ = walk_items(&item.children[..], section, current_page, out);
             try!(writeln!(out, "</ul>"));
         }
         try!(writeln!(out, "</li>"));
@@ -67,7 +74,7 @@ fn write_toc(book: &Book, path_to_root: &Path, out: &mut Write) -> io::Result<()
 
     try!(writeln!(out, "<div id='toc' class='mobile-hidden'>"));
     try!(writeln!(out, "<ul class='chapter'>"));
-    try!(walk_items(&book.chapters[..], "", path_to_root, out));
+    try!(walk_items(&book.chapters[..], "", &current_page, out));
     try!(writeln!(out, "</ul>"));
     try!(writeln!(out, "</div>"));
 
@@ -115,7 +122,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
                   <span class="bar"></span>
                 </button>
               </div>"#));
-            let _ = write_toc(book, &item.path_to_root, &mut toc);
+            let _ = write_toc(book, &item, &mut toc);
             try!(writeln!(&mut toc, "<div id='page-wrapper'>"));
             try!(writeln!(&mut toc, "<div id='page'>"));
         }
@@ -151,10 +158,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
     // create index.html from the root README
     try!(fs::copy(&tgt.join("README.html"), &tgt.join("index.html")));
 
-    // Copy some js for playpen
-    let mut jquery = try!(File::create(tgt.join("jquery.js")));
-    let js = include_bytes!("../librustdoc/html/static/jquery-2.1.0.min.js");
-    try!(jquery.write_all(js));
+    // Copy js for playpen
     let mut playpen = try!(File::create(tgt.join("playpen.js")));
     let js = include_bytes!("../librustdoc/html/static/playpen.js");
     try!(playpen.write_all(js));
index a5192eefd57ba2e5c61fcccf1ea1f35c796278ca..aae5f21a73dc653f0e7b7e37bde2095ae0a2f666 100644 (file)
@@ -97,6 +97,11 @@ body {
     color: #000000;
 }
 
+.chapter li a.active {
+    text-decoration: underline;
+    font-weight: bold;
+}
+
 #toggle-nav {
     height: 20px;
     width:  30px;
index 26303d13b6cfcb61542d1d46ff45d29186a405a1..f33b79cc1888f770c5bfe861b0072e18979516bb 100644 (file)
@@ -71,6 +71,5 @@ document.addEventListener("DOMContentLoaded", function(event) {
 
 });
 </script>
-<script type="text/javascript" src="jquery.js"></script>
 <script type="text/javascript" src="playpen.js"></script>
 "#;
index 09fcd518c1e7e3998f32851738559f36840d845d..acb1c5cbd90baabdc08ee46381cbd771719e57d5 100644 (file)
 
 #![deny(warnings)]
 
-#![feature(core)]
-#![feature(exit_status)]
-#![feature(rustdoc)]
-#![feature(rustc_private)]
+#![feature(iter_arith)]
 #![feature(path_relative_from)]
+#![feature(rustc_private)]
+#![feature(rustdoc)]
 
 extern crate rustdoc;
 extern crate rustc_back;
 
 use std::env;
 use std::error::Error;
+use std::process;
+use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use subcommand::Subcommand;
 use term::Term;
 
@@ -37,6 +38,8 @@ mod test;
 mod css;
 mod javascript;
 
+static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
+
 #[cfg(not(test))] // thanks #12327
 fn main() {
     let mut term = Term::new();
@@ -70,4 +73,5 @@ fn main() {
             }
         }
     }
+    process::exit(EXIT_STATUS.load(Ordering::SeqCst) as i32);
 }
index 44af43be7877344cfd878700984662adb9f60058..5a8e1f695ae6e846a9addc9b9d9f795a415ef9ac 100644 (file)
@@ -36,7 +36,7 @@ pub fn parse_name(name: &str) -> Option<Box<Subcommand>> {
                                                           build::parse_cmd,
                                                           serve::parse_cmd,
                                                           test::parse_cmd];
-    for parser in cmds.iter() {
+    for parser in &cmds {
         let parsed = (*parser)(name);
         if parsed.is_some() { return parsed }
     }
index 060297beb758bc37da200710b716e19036b6ac9a..cdd25e67c8ff13274da1928c75296862c8c958af 100644 (file)
@@ -11,9 +11,9 @@
 //! An abstraction of the terminal. Eventually, provide color and
 //! verbosity support. For now, just a wrapper around stdout/stderr.
 
-use std::env;
 use std::io;
 use std::io::prelude::*;
+use std::sync::atomic::Ordering;
 
 pub struct Term {
     err: Box<Write + 'static>
@@ -29,6 +29,6 @@ impl Term {
     pub fn err(&mut self, msg: &str) {
         // swallow any errors
         let _ = writeln!(&mut self.err, "{}", msg);
-        env::set_exit_status(101);
+        ::EXIT_STATUS.store(101, Ordering::SeqCst);
     }
 }
index 7e0630fd242d39c83dfff871136a8d0118950208..df83f32670c0c892529201fdb7ae5928e797dd5d 100644 (file)
@@ -16,22 +16,31 @@ using namespace llvm;
 using namespace llvm::sys;
 using namespace llvm::object;
 
+// libmorestack is not used on other platforms
+#if defined(__linux__) || defined(__APPLE__)
+extern "C" void __morestack(void);
+
+static void* morestack_addr() {
+    return reinterpret_cast<void*>(__morestack);
+}
+#endif
+
 class RustJITMemoryManager : public SectionMemoryManager
 {
     typedef SectionMemoryManager Base;
 
-    const void *morestack;
-
     public:
 
-    RustJITMemoryManager(const void *morestack_ptr)
-        : morestack(morestack_ptr)
-        {}
+    RustJITMemoryManager() {}
 
     uint64_t getSymbolAddress(const std::string &Name) override
     {
+#if defined(__linux__) || defined(__APPLE__)
         if (Name == "__morestack" || Name == "___morestack")
-            return reinterpret_cast<uint64_t>(morestack);
+            return reinterpret_cast<uint64_t>(__morestack);
+        if (Name == "__morestack_addr" || Name == "___morestack_addr")
+            return reinterpret_cast<uint64_t>(morestack_addr);
+#endif
 
         return Base::getSymbolAddress(Name);
     }
@@ -39,11 +48,6 @@ class RustJITMemoryManager : public SectionMemoryManager
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef)
 
-extern "C" LLVMRustJITMemoryManagerRef LLVMRustCreateJITMemoryManager(void *morestack)
-{
-    return wrap(new RustJITMemoryManager(morestack));
-}
-
 extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
 {
     std::string err;
@@ -60,6 +64,13 @@ extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
 extern "C" void LLVMExecutionEngineAddModule(
     LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
 {
+#ifdef _WIN32
+    // On Windows, MCJIT must generate ELF objects
+    std::string target = getProcessTriple();
+    target += "-elf";
+    target = Triple::normalize(target);
+    unwrap(mref)->setTargetTriple(target);
+#endif
     LLVMAddModule(eeref, mref);
 }
 
@@ -74,27 +85,33 @@ extern "C" LLVMBool LLVMExecutionEngineRemoveModule(
     return ee->removeModule(m);
 }
 
-extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(
-    LLVMModuleRef mod, LLVMRustJITMemoryManagerRef mref)
+extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
 {
     // These are necessary for code generation to work properly.
     InitializeNativeTarget();
     InitializeNativeTargetAsmPrinter();
     InitializeNativeTargetAsmParser();
 
+#ifdef _WIN32
+    // On Windows, MCJIT must generate ELF objects
+    std::string target = getProcessTriple();
+    target += "-elf";
+    target = Triple::normalize(target);
+    unwrap(mod)->setTargetTriple(target);
+#endif
+
     std::string error_str;
     TargetOptions options;
 
-    options.JITEmitDebugInfo = true;
-    options.NoFramePointerElim = true;
+    RustJITMemoryManager *mm = new RustJITMemoryManager;
 
     ExecutionEngine *ee =
     #if LLVM_VERSION_MINOR >= 6
         EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))
-            .setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(unwrap(mref)))
+            .setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(mm))
     #else
         EngineBuilder(unwrap(mod))
-            .setMCJITMemoryManager(unwrap(mref))
+            .setMCJITMemoryManager(mm)
     #endif
             .setEngineKind(EngineKind::JIT)
             .setErrorStr(&error_str)
index a2ab8040198ff7a3266bd58194556d2d7255fd31..2c0240eb8f92bac7476ff00467bbb5a6b5e8d430 100644 (file)
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
+#if LLVM_VERSION_MINOR >= 7
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#else
 #include "llvm/Target/TargetLibraryInfo.h"
+#endif
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
+
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
 using namespace llvm;
+using namespace llvm::legacy;
 
 extern cl::opt<bool> EnableARMEHABI;
 
@@ -71,7 +78,6 @@ LLVMRustCreateTargetMachine(const char *triple,
                             CodeGenOpt::Level OptLevel,
                             bool EnableSegmentedStacks,
                             bool UseSoftFloat,
-                            bool NoFramePointerElim,
                             bool PositionIndependentExecutable,
                             bool FunctionSections,
                             bool DataSections) {
@@ -91,12 +97,12 @@ LLVMRustCreateTargetMachine(const char *triple,
 
     TargetOptions Options;
     Options.PositionIndependentExecutable = PositionIndependentExecutable;
-    Options.NoFramePointerElim = NoFramePointerElim;
     Options.FloatABIType = FloatABI::Default;
-    Options.UseSoftFloat = UseSoftFloat;
     if (UseSoftFloat) {
         Options.FloatABIType = FloatABI::Soft;
     }
+    Options.DataSections = DataSections;
+    Options.FunctionSections = FunctionSections;
 
     TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
                                                        real_cpu,
@@ -105,8 +111,6 @@ LLVMRustCreateTargetMachine(const char *triple,
                                                        RM,
                                                        CM,
                                                        OptLevel);
-    TM->setDataSections(DataSections);
-    TM->setFunctionSections(FunctionSections);
     return wrap(TM);
 }
 
@@ -123,12 +127,32 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
                           LLVMPassManagerRef PMR,
                           LLVMModuleRef M) {
     PassManagerBase *PM = unwrap(PMR);
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+    PM->add(createTargetTransformInfoWrapperPass(
+          unwrap(TM)->getTargetIRAnalysis()));
+#else
+#if LLVM_VERSION_MINOR == 6
     PM->add(new DataLayoutPass());
 #else
     PM->add(new DataLayoutPass(unwrap(M)));
 #endif
     unwrap(TM)->addAnalysisPasses(*PM);
+#endif
+}
+
+extern "C" void
+LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
+                                    CodeGenOpt::Level OptLevel,
+                                    bool MergeFunctions,
+                                    bool SLPVectorize,
+                                    bool LoopVectorize) {
+#if LLVM_VERSION_MINOR >= 6
+    // Ignore mergefunc for now as enabling it causes crashes.
+    //unwrap(PMB)->MergeFunctions = MergeFunctions;
+#endif
+    unwrap(PMB)->SLPVectorize = SLPVectorize;
+    unwrap(PMB)->OptLevel = OptLevel;
+    unwrap(PMB)->LoopVectorize = LoopVectorize;
 }
 
 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
@@ -138,7 +162,11 @@ LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
                               LLVMModuleRef M,
                               bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
+#if LLVM_VERSION_MINOR >= 7
+    TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
+#else
     TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
+#endif
     if (DisableSimplifyLibCalls)
       TLI->disableAllFunctions();
     unwrap(PMB)->LibraryInfo = TLI;
@@ -151,10 +179,17 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
                        LLVMModuleRef M,
                        bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
+#if LLVM_VERSION_MINOR >= 7
+    TargetLibraryInfoImpl TLII(TargetTriple);
+    if (DisableSimplifyLibCalls)
+      TLII.disableAllFunctions();
+    unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
+#else
     TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
     if (DisableSimplifyLibCalls)
       TLI->disableAllFunctions();
     unwrap(PMB)->add(TLI);
+#endif
 }
 
 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
@@ -204,10 +239,19 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
     LLVMRustSetLastError(ErrorInfo.c_str());
     return false;
   }
-  formatted_raw_ostream FOS(OS);
 
+#if LLVM_VERSION_MINOR >= 7
+  unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
+#else
+  formatted_raw_ostream FOS(OS);
   unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
+#endif
   PM->run(*unwrap(M));
+
+  // Apparently `addPassesToEmitFile` adds an 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;
   return true;
 }
 
index 375c5fc746c5b80843b0d03ccb7c2c9aac447264..70ef64afc433628a6b8d422c55a00eedbf681c5e 100644 (file)
@@ -141,6 +141,15 @@ extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const
   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
 }
 
+extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
+                                               const char *Name,
+                                               const char *Value) {
+  Function *F = unwrap<Function>(Fn);
+  AttrBuilder B;
+  B.addAttribute(Name, Value);
+  F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
+}
+
 extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
   Function *f = unwrap<Function>(fn);
   LLVMContext &C = f->getContext();
@@ -228,12 +237,37 @@ inline Metadata **unwrap(LLVMMetadataRef *Vals) {
 typedef LLVMValueRef LLVMMetadataRef;
 #endif
 
+template<typename DIT>
+DIT* unwrapDIptr(LLVMMetadataRef ref) {
+    return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
+}
+
+#if LLVM_VERSION_MINOR <= 6
 template<typename DIT>
 DIT unwrapDI(LLVMMetadataRef ref) {
     return DIT(ref ? unwrap<MDNode>(ref) : NULL);
 }
+#else
+#define DIDescriptor DIScope
+#define DIArray DINodeArray
+#define unwrapDI unwrapDIptr
+#endif
 
-extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION;
+#if LLVM_VERSION_MINOR <= 5
+#define DISubroutineType DICompositeType
+#endif
+
+extern "C" uint32_t LLVMRustDebugMetadataVersion() {
+    return DEBUG_METADATA_VERSION;
+}
+
+extern "C" uint32_t LLVMVersionMinor() {
+  return LLVM_VERSION_MINOR;
+}
+
+extern "C" uint32_t LLVMVersionMajor() {
+  return LLVM_VERSION_MAJOR;
+}
 
 extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
                                       const char *name,
@@ -286,7 +320,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
     LLVMMetadataRef ParameterTypes) {
     return wrap(Builder->createSubroutineType(
         unwrapDI<DIFile>(File),
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+        DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
+#elif LLVM_VERSION_MINOR >= 6
         unwrapDI<DITypeArray>(ParameterTypes)));
 #else
         unwrapDI<DIArray>(ParameterTypes)));
@@ -312,11 +348,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
     return wrap(Builder->createFunction(
         unwrapDI<DIScope>(Scope), Name, LinkageName,
         unwrapDI<DIFile>(File), LineNo,
-        unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
+        unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
         Flags, isOptimized,
         unwrap<Function>(Fn),
-        unwrapDI<MDNode*>(TParam),
-        unwrapDI<MDNode*>(Decl)));
+        unwrapDIptr<MDNode>(TParam),
+        unwrapDIptr<MDNode>(Decl)));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
@@ -363,7 +399,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
         AlignInBits,
         Flags,
         unwrapDI<DIType>(DerivedFrom),
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         RunTimeLang,
         unwrapDI<DIType>(VTableHolder),
         UniqueId
@@ -426,7 +466,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
         unwrapDI<DIType>(Ty),
         isLocalToUnit,
         cast<Constant>(unwrap(Val)),
-        unwrapDI<MDNode*>(Decl)));
+        unwrapDIptr<MDNode>(Decl)));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
@@ -476,7 +516,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
     LLVMMetadataRef Subscripts) {
     return wrap(Builder->createArrayType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
-        unwrapDI<DIArray>(Subscripts)));
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Subscripts))
+#else
+        unwrapDI<DIArray>(Subscripts)
+#endif
+    ));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
@@ -487,7 +532,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
     LLVMMetadataRef Subscripts) {
     return wrap(Builder->createVectorType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
-        unwrapDI<DIArray>(Subscripts)));
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Subscripts))
+#else
+        unwrapDI<DIArray>(Subscripts)
+#endif
+    ));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
@@ -501,12 +551,18 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
     DIBuilderRef Builder,
     LLVMMetadataRef* Ptr,
     unsigned Count) {
+#if LLVM_VERSION_MINOR >= 7
+    Metadata **DataValue = unwrap(Ptr);
+    return wrap(Builder->getOrCreateArray(
+        ArrayRef<Metadata*>(DataValue, Count)).get());
+#else
     return wrap(Builder->getOrCreateArray(
 #if LLVM_VERSION_MINOR >= 6
         ArrayRef<Metadata*>(unwrap(Ptr), Count)));
 #else
         ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
 #endif
+#endif
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
@@ -515,21 +571,21 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
     LLVMMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
+    LLVMValueRef DL,
     LLVMBasicBlockRef InsertAtEnd) {
-#if LLVM_VERSION_MINOR >= 6
-    DIExpression Expr;
-    if (AddrOpsCount == 0) {
-      Expr = Builder->createExpression();
-    } else {
-      llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
-      Expr = Builder->createExpression(addr_ops);
-    }
-#endif
     return wrap(Builder->insertDeclare(
         unwrap(Val),
+#if LLVM_VERSION_MINOR >= 7
+        unwrap<DILocalVariable>(VarInfo),
+#else
         unwrapDI<DIVariable>(VarInfo),
+#endif
 #if LLVM_VERSION_MINOR >= 6
-        Expr,
+        Builder->createExpression(
+          llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
+#endif
+#if LLVM_VERSION_MINOR >= 7
+        DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
 #endif
         unwrap(InsertAtEnd)));
 }
@@ -540,21 +596,23 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
     LLVMMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
+    LLVMValueRef DL,
     LLVMValueRef InsertBefore) {
 #if LLVM_VERSION_MINOR >= 6
-    DIExpression Expr;
-    if (AddrOpsCount == 0) {
-      Expr = Builder->createExpression();
-    } else {
-      llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
-      Expr = Builder->createExpression(addr_ops);
-    }
 #endif
     return wrap(Builder->insertDeclare(
         unwrap(Val),
+#if LLVM_VERSION_MINOR >= 7
+        unwrap<DILocalVariable>(VarInfo),
+#else
         unwrapDI<DIVariable>(VarInfo),
+#endif
 #if LLVM_VERSION_MINOR >= 6
-        Expr,
+        Builder->createExpression(
+          llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
+#endif
+#if LLVM_VERSION_MINOR >= 7
+        DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
 #endif
         unwrap<Instruction>(InsertBefore)));
 }
@@ -585,7 +643,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
         LineNumber,
         SizeInBits,
         AlignInBits,
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         unwrapDI<DIType>(ClassType)));
 }
 
@@ -610,7 +672,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
         SizeInBits,
         AlignInBits,
         Flags,
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         RunTimeLang,
         UniqueId
         ));
@@ -628,10 +694,14 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
     return wrap(Builder->createTemplateTypeParameter(
       unwrapDI<DIDescriptor>(Scope),
       Name,
-      unwrapDI<DIType>(Ty),
+      unwrapDI<DIType>(Ty)
+#if LLVM_VERSION_MINOR <= 6
+      ,
       unwrapDI<MDNode*>(File),
       LineNo,
-      ColumnNo));
+      ColumnNo
+#endif
+      ));
 }
 
 extern "C" int64_t LLVMDIBuilderCreateOpDeref()
@@ -663,7 +733,10 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
     LLVMMetadataRef CompositeType,
     LLVMMetadataRef TypeArray)
 {
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+    DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
+    Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
+#elif LLVM_VERSION_MINOR >= 6
     DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
     Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
 #else
@@ -682,11 +755,15 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
 
     DebugLoc debug_loc = DebugLoc::get(Line,
                                        Column,
-                                       unwrapDI<MDNode*>(Scope),
-                                       unwrapDI<MDNode*>(InlinedAt));
+                                       unwrapDIptr<MDNode>(Scope),
+                                       unwrapDIptr<MDNode>(InlinedAt));
 
 #if LLVM_VERSION_MINOR >= 6
-    return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
+    return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(
+#if LLVM_VERSION_MINOR <= 6
+            context
+#endif
+        )));
 #else
     return wrap(debug_loc.getAsMDNode(context));
 #endif
@@ -711,7 +788,12 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     Module *Dst = unwrap(dst);
 #if LLVM_VERSION_MINOR >= 6
     std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
+#if LLVM_VERSION_MINOR >= 7
+    ErrorOr<std::unique_ptr<Module>> Src =
+        llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
+#else
     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
+#endif
 #else
     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
@@ -729,7 +811,11 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
 #if LLVM_VERSION_MINOR >= 6
     raw_string_ostream Stream(Err);
     DiagnosticPrinterRawOStream DP(Stream);
+#if LLVM_VERSION_MINOR >= 7
+    if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
+#else
     if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
+#endif
 #else
     if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
 #endif
@@ -803,8 +889,12 @@ extern "C" const Archive::Child*
 LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
     if (rai->cur == rai->end)
         return NULL;
+#if LLVM_VERSION_MINOR >= 6
     const Archive::Child &ret = *rai->cur;
     return &ret;
+#else
+    return rai->cur.operator->();
+#endif
 }
 
 extern "C" void
@@ -837,9 +927,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
 }
 
 extern "C" void
-LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
+LLVMRustSetDLLStorageClass(LLVMValueRef Value,
+                           GlobalValue::DLLStorageClassTypes Class) {
     GlobalValue *V = unwrap<GlobalValue>(Value);
-    V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
+    V->setDLLStorageClass(Class);
 }
 
 // Note that the two following functions look quite similar to the
@@ -931,7 +1022,11 @@ extern "C" void LLVMWriteDebugLocToString(
     RustStringRef str)
 {
     raw_rust_string_ostream os(str);
+#if LLVM_VERSION_MINOR >= 7
+    unwrap(dl)->print(os);
+#else
     unwrap(dl)->print(*unwrap(C), os);
+#endif
 }
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
index 1ea40fc46a52196764be269294605440a042f794..38b7b49a3443e7371a55d2fd664b49a56e54d7ae 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-03-04
+2015-06-16
index 8a4330acf43417e831690e9f564207685de03e5e..2a47e8b089549a77bc20b0761c835adb953505a2 100644 (file)
@@ -12,7 +12,6 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
-#include "llvm/PassManager.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Object.h"
 
+#if LLVM_VERSION_MINOR >= 7
+#include "llvm/IR/LegacyPassManager.h"
+#else
+#include "llvm/PassManager.h"
+#endif
+
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/Linker/Linker.h"
 
-// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
-// to get around glibc issues. See the function for more information.
-#ifdef __linux__
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
 void LLVMRustSetLastError(const char*);
 
 typedef struct OpaqueRustString *RustStringRef;
index 7c4b3866b2a99dbea1e238dc06d6225013fabd1c..1b2613d8c5045f21c655da2af1a5ac900bbdd71c 100644 (file)
@@ -1,3 +1,13 @@
+S 2015-05-24 ba0e1cd
+  bitrig-x86_64 2a710e16e3e3ef3760df1f724d66b3af34c1ef3f
+  freebsd-x86_64 370db40613f5c08563ed7e38357826dd42d4e0f8
+  linux-i386 a6f22e481eabf098cc65bda97bf7e434a1fcc20b
+  linux-x86_64 5fd8698fdfe953e6c4d86cf4fa1d5f3a0053248c
+  macos-i386 9a273324a6b63a40f67a553029c0a9fb692ffd1f
+  macos-x86_64 e5b12cb7c179fc98fa905a3c84803645d946a6ae
+  winnt-i386 18d8d76c5380ee2247dd534bfb2c4ed1b3d83461
+  winnt-x86_64 ef27ce42af4941be24a2f6097d969ffc845a31ee
+
 S 2015-04-27 857ef6e
   bitrig-x86_64 d28e2a5f8b478e69720703e751774f5e728a8edd
   freebsd-x86_64 18925db56f6298cc190d1f41615ab5871de1dda0
diff --git a/src/test/auxiliary/attr_plugin_test.rs b/src/test/auxiliary/attr_plugin_test.rs
new file mode 100644 (file)
index 0000000..a6cae74
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+
+#![feature(plugin_registrar)]
+#![feature(rustc_private)]
+
+extern crate syntax;
+
+extern crate rustc;
+
+use syntax::feature_gate::AttributeType;
+use rustc::plugin::Registry;
+
+
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_attribute("foo".to_owned(), AttributeType::Normal);
+    reg.register_attribute("bar".to_owned(), AttributeType::CrateLevel);
+    reg.register_attribute("baz".to_owned(), AttributeType::Whitelisted);
+}
diff --git a/src/test/auxiliary/const_fn_lib.rs b/src/test/auxiliary/const_fn_lib.rs
new file mode 100644 (file)
index 0000000..b0d5a6b
--- /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 that exports a const fn. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+#![feature(const_fn)]
+
+pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
index 0edbeb2d02ca4ccdb917b30b22d151d9f3229a68..8c1445a172d8d21eb74b5ce6a60af930416a4e55 100644 (file)
@@ -37,7 +37,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
 fn expand(cx: &mut ExtCtxt,
           span: Span,
           mitem: &ast::MetaItem,
-          item: Annotatable,
+          item: &Annotatable,
           push: &mut FnMut(Annotatable)) {
     let trait_def = TraitDef {
         span: span,
@@ -54,6 +54,7 @@ fn expand(cx: &mut ExtCtxt,
                 args: vec![],
                 ret_ty: Literal(Path::new_local("isize")),
                 attributes: vec![],
+                is_unsafe: false,
                 combine_substructure: combine_substructure(box |cx, span, substr| {
                     let zero = cx.expr_isize(span, 0);
                     cs_fold(false,
@@ -70,5 +71,5 @@ fn expand(cx: &mut ExtCtxt,
         ],
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
index 92963b2812dd8ef49bfb9dc617207869e08e3667..01fde91fef57b93ca0bce8f1eae5bf0ef26c3b49 100644 (file)
@@ -39,7 +39,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
 fn expand(cx: &mut ExtCtxt,
           span: Span,
           mitem: &ast::MetaItem,
-          item: Annotatable,
+          item: &Annotatable,
           push: &mut FnMut(Annotatable)) {
     let trait_def = TraitDef {
         span: span,
@@ -56,12 +56,13 @@ fn expand(cx: &mut ExtCtxt,
                 args: vec![],
                 ret_ty: Literal(Path::new_local("isize")),
                 attributes: vec![],
+                is_unsafe: false,
                 combine_substructure: combine_substructure(Box::new(totalsum_substructure)),
             },
         ],
     };
 
-    trait_def.expand(cx, mitem, &item, push)
+    trait_def.expand(cx, mitem, item, push)
 }
 
 // Mostly copied from syntax::ext::deriving::hash
index 91a404bbba3935c4c9e2c802a303f69641aaa7b2..22cbc415eb4cef9849a1366e017b5cf9236122a4 100644 (file)
 #[inline(never)]
 #[cfg(target_arch = "x86_64")]
 pub extern "win64" fn foo(a: isize, b: isize, c: isize, d: isize) {
-    assert!(a == 1);
-    assert!(b == 2);
-    assert!(c == 3);
-    assert!(d == 4);
+    assert_eq!(a, 1);
+    assert_eq!(b, 2);
+    assert_eq!(c, 3);
+    assert_eq!(d, 4);
 
     println!("a: {}, b: {}, c: {}, d: {}",
              a, b, c, d)
@@ -26,10 +26,10 @@ pub extern "win64" fn foo(a: isize, b: isize, c: isize, d: isize) {
 #[inline(never)]
 #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))]
 pub extern fn foo(a: isize, b: isize, c: isize, d: isize) {
-    assert!(a == 1);
-    assert!(b == 2);
-    assert!(c == 3);
-    assert!(d == 4);
+    assert_eq!(a, 1);
+    assert_eq!(b, 2);
+    assert_eq!(c, 3);
+    assert_eq!(d, 4);
 
     println!("a: {}, b: {}, c: {}, d: {}",
              a, b, c, d)
index 67474e7902170c91e96cc2a31474cb7e4a884894..373fc04217540d3d3ec3665ba6cbcc8310758cce 100644 (file)
@@ -8,15 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_fn)]
+
 use std::sync::atomic;
 
 pub const C1: usize = 1;
-pub const C2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
+pub const C2: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
 pub const C3: fn() = foo;
 pub const C4: usize = C1 * C1 + C1 / C1;
 pub const C5: &'static usize = &C4;
 
 pub static S1: usize = 3;
-pub static S2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
+pub static S2: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
 
 fn foo() {}
diff --git a/src/test/auxiliary/issue-18913-1.rs b/src/test/auxiliary/issue-18913-1.rs
new file mode 100644 (file)
index 0000000..4315e27
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![crate_name = "foo"]
+
+pub fn foo() -> i32 { 0 }
diff --git a/src/test/auxiliary/issue-18913-2.rs b/src/test/auxiliary/issue-18913-2.rs
new file mode 100644 (file)
index 0000000..dcdeaec
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![crate_name = "foo"]
+
+pub fn foo() -> i32 { 1 }
index 435f0176162b89db3968973dae1f18e37324bf84..7403bcf4afb31694fdffcbb238ca9236217c6a7b 100644 (file)
@@ -22,6 +22,7 @@ pub struct Baz;
 
 impl Baz {
     pub fn baz(&self) {}
+    pub fn static_baz() {}
 }
 
 impl Deref for Bar {
index 22ccb3dfacdf1285912e6bbab1083ca38e17d73d..7d82e79f949110d03efc1396b2845685c8b4393c 100644 (file)
@@ -34,54 +34,54 @@ pub mod testtypes {
 
     // Skipping ty_bot
 
-    // Tests ty_bool
+    // Tests TyBool
     pub type FooBool = bool;
 
-    // Tests ty_char
+    // Tests TyChar
     pub type FooChar = char;
 
-    // Tests ty_int (does not test all variants of IntTy)
+    // Tests TyInt (does not test all variants of IntTy)
     pub type FooInt = isize;
 
-    // Tests ty_uint (does not test all variants of UintTy)
+    // Tests TyUint (does not test all variants of UintTy)
     pub type FooUint = usize;
 
-    // Tests ty_float (does not test all variants of FloatTy)
+    // Tests TyFloat (does not test all variants of FloatTy)
     pub type FooFloat = f64;
 
-    // For ty_str, what kind of string should I use? &'static str? String? Raw str?
+    // For TyStr, what kind of string should I use? &'static str? String? Raw str?
 
-    // Tests ty_enum
+    // Tests TyEnum
     pub enum FooEnum {
         VarA(usize),
         VarB(usize, usize)
     }
 
-    // Tests ty_uniq (of u8)
+    // Tests TyBox (of u8)
     pub type FooUniq = Box<u8>;
 
-    // As with ty_str, what type should be used for ty_vec?
+    // As with TyStr, what type should be used for TyArray?
 
-    // Tests ty_ptr
+    // Tests TyRawPtr
     pub type FooPtr = *const u8;
 
-    // Skipping ty_rptr
+    // Skipping TyRef
 
-    // Skipping ty_bare_fn (how do you get a bare function type, rather than proc or closure?)
+    // Skipping TyBareFn (how do you get a bare function type, rather than proc or closure?)
 
-    // Tests ty_trait
+    // Tests TyTrait
     pub trait FooTrait {
         fn foo_method(&self) -> usize;
         fn foo_static_method() -> usize;
     }
 
-    // Tests ty_struct
+    // Tests TyStruct
     pub struct FooStruct {
         pub pub_foo_field: usize,
         foo_field: usize
     }
 
-    // Tests ty_tup
+    // Tests TyTuple
     pub type FooTuple = (u8, i8, bool);
 
     // Skipping ty_param
@@ -90,7 +90,7 @@ pub mod testtypes {
 
     // Skipping ty_self
 
-    // Skipping ty_infer
+    // Skipping TyInfer
 
-    // Skipping ty_err
+    // Skipping TyError
 }
index d195bd7e77bd8bb9ae335f9ad155f9c816abe413..24978e434cc2fd417dec68f1f739d965040b91d9 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(no_std)]
 #![no_std]
 #![feature(lang_items)]
+#![feature(associated_type_defaults)]
 
 #[lang="sized"]
 pub trait Sized { }
diff --git a/src/test/auxiliary/lifetime_bound_will_change_warning_lib.rs b/src/test/auxiliary/lifetime_bound_will_change_warning_lib.rs
new file mode 100644 (file)
index 0000000..95f8b39
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+#![crate_type = "rlib"]
+
+// Helper for testing that we get suitable warnings when lifetime
+// bound change will cause breakage.
+
+pub fn just_ref(x: &Fn()) {
+}
+
+pub fn ref_obj(x: &Box<Fn()>) {
+    // this will change to &Box<Fn()+'static>...
+}
index 9196a156ad1c9e2835c97082420b6f7536785f8d..ce3360787136a099ed5a38adcb0544323bf8ffc8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_misc)]
+#![feature(dynamic_lib)]
 
 // We're testing linkage visibility; the compiler warns us, but we want to
 // do the runtime check that these functions aren't exported.
index d61f47fd7ef27cf49556c5a86afb5248b3ae149a..bacc1acd3c4c30c34c66b7d1a17f8e7f10e11521 100644 (file)
@@ -24,5 +24,5 @@ pub fn plugin_registrar(reg: &mut Registry) {
     // Normally, we would name a pass that was registered through
     // C++ static object constructors in the same .so file as the
     // plugin registrar.
-    reg.register_llvm_pass("inline");
+    reg.register_llvm_pass("gvn");
 }
index 53a6672d4888deb4cf5d6cbeb0ffd9206fc51bac..9474533a9b5a756b5abb6250164c36c42623381c 100644 (file)
@@ -108,7 +108,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
 fn expand_duplicate(cx: &mut ExtCtxt,
                     sp: Span,
                     mi: &MetaItem,
-                    it: Annotatable,
+                    it: &Annotatable,
                     push: &mut FnMut(Annotatable))
 {
     let copy_name = match mi.node {
diff --git a/src/test/auxiliary/xcrate_associated_type_defaults.rs b/src/test/auxiliary/xcrate_associated_type_defaults.rs
new file mode 100644 (file)
index 0000000..43852a4
--- /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.
+
+#![feature(associated_type_defaults)]
+
+pub trait Foo {
+    type Input = usize;
+    fn bar(&self, _: Self::Input) {}
+}
+
+impl Foo for () {}
index eebf6feaffac33d0a4e120a26f48587a219d5e69..d2537e09901cb90c876b7bef9610435a30f4c566 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-pretty very bad with line comments
 
 #![feature(unboxed_closures, rand, std_misc, collections, duration, duration_span)]
+#![feature(bitset)]
 
 extern crate collections;
 extern crate rand;
index 6e85abb8e149fa64033690be0eb8b282594b9108..3cc03f5218cebeaf237ff92b4fc18de2bdb07ce1 100644 (file)
@@ -10,7 +10,7 @@
 
 // Microbenchmarks for various functions in std and extra
 
-#![feature(rand, collections, std_misc, duration, duration_span)]
+#![feature(rand, vec_push_all, duration, duration_span)]
 
 use std::iter::repeat;
 use std::mem::swap;
@@ -72,7 +72,7 @@ fn vec_plus() {
     while i < 1500 {
         let rv = repeat(i).take(r.gen_range(0, i + 1)).collect::<Vec<_>>();
         if r.gen() {
-            v.extend(rv.into_iter());
+            v.extend(rv);
         } else {
             let mut rv = rv.clone();
             rv.push_all(&v);
index 93e3394097bc57695a002cf2a9affb1256a2b344..24ecaf4b0247145e121df407af89471fb685e543 100644 (file)
@@ -17,7 +17,7 @@
 
 // no-pretty-expanded FIXME #15189
 
-#![feature(duration, duration_span, std_misc)]
+#![feature(duration, duration_span, future)]
 
 use std::env;
 use std::sync::{Arc, Future, Mutex, Condvar};
index 32504350e42682d33fcea64af426e6a1fe65c032..3bc1782bd0c9e0ecf5e7bcb95f8ebb77f8dc37fc 100644 (file)
@@ -103,7 +103,7 @@ impl Perm {
             let d = idx / self.fact[i] as i32;
             self.cnt[i] = d;
             idx %= self.fact[i] as i32;
-            for (place, val) in pp.iter_mut().zip(self.perm.p[..i+1].iter()) {
+            for (place, val) in pp.iter_mut().zip(&self.perm.p[..i+1]) {
                 *place = (*val) as u8
             }
 
index 145ab71446354183d32dcefdcb80223b70532aa5..f69e155ad388885cfd39930798bc7898a61b0c62 100644 (file)
@@ -124,11 +124,11 @@ impl<'a, W: Write> RepeatFasta<'a, W> {
         let mut buf = repeat(0).take(alu_len + LINE_LEN).collect::<Vec<_>>();
         let alu: &[u8] = self.alu.as_bytes();
 
-        for (slot, val) in buf.iter_mut().zip(alu.iter()) {
+        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].iter()) {
+        for (slot, val) in buf[alu_len..buf_len].iter_mut().zip(&alu[..LINE_LEN]) {
             *slot = *val;
         }
 
index 365a86464e2d377a6c82ef2072be1d37aed31558..b4e5ca201492a0d3600c5ee0f0cd65b3cfae0588 100644 (file)
@@ -158,7 +158,7 @@ fn main() {
         Some(channel::<String>())
     }).collect::<Vec<_>>();
     let mut from_child = Vec::new();
-    let to_child  = sizes.iter().zip(streams.iter_mut()).map(|(sz, stream_ref)| {
+    let to_child  = sizes.iter().zip(&mut streams).map(|(sz, stream_ref)| {
         let sz = *sz;
         let stream = replace(stream_ref, None);
         let (to_parent_, from_child_) = stream.unwrap();
index 87b9869051cadff2160cf8dc350d9bbc1786f128..8ae07558c168fb34aa172d1d92a2418b72c42cf3 100644 (file)
@@ -40,7 +40,7 @@
 
 // ignore-android: FIXME(#10393) hangs without output
 
-#![feature(box_syntax, std_misc, collections)]
+#![feature(box_syntax, owned_ascii_ext, vec_push_all)]
 
 use std::ascii::OwnedAsciiExt;
 use std::env;
@@ -317,7 +317,7 @@ fn main() {
     for (i, freq) in nb_freqs {
         print_frequencies(&freq.join().unwrap(), i);
     }
-    for (&occ, freq) in OCCURRENCES.iter().zip(occ_freqs.into_iter()) {
+    for (&occ, freq) in OCCURRENCES.iter().zip(occ_freqs) {
         print_occurrences(&mut freq.join().unwrap(), occ);
     }
 }
index f2714d55e5ea772753b032451524ee927873b0b1..232d6b414f580cb4b973388793e13a5551ee94da 100644 (file)
@@ -38,7 +38,7 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#![feature(simd, core)]
+#![feature(core_simd, core)]
 
 // ignore-pretty very bad with line comments
 
@@ -54,7 +54,7 @@ const LIMIT: f64 = 2.0;
 const WORKERS: usize = 16;
 
 fn mandelbrot<W: Write>(w: usize, mut out: W) -> io::Result<()> {
-    assert!(WORKERS % 2 == 0);
+    assert_eq!(WORKERS % 2, 0);
 
     // Ensure w and h are multiples of 8.
     let w = (w + 7) / 8 * 8;
@@ -76,7 +76,7 @@ fn mandelbrot<W: Write>(w: usize, mut out: W) -> io::Result<()> {
     let v_consts = f64x2(1.5, 1.0);
 
     // A lot of this code assumes this (so do other lang benchmarks)
-    assert!(w == h);
+    assert_eq!(w, h);
     let mut precalc_r = Vec::with_capacity(w);
     let mut precalc_i = Vec::with_capacity(h);
 
@@ -108,8 +108,8 @@ fn mandelbrot<W: Write>(w: usize, mut out: W) -> io::Result<()> {
 
     for res in precalc_futures {
         let (rs, is) = res.join().unwrap();
-        precalc_r.extend(rs.into_iter());
-        precalc_i.extend(is.into_iter());
+        precalc_r.extend(rs);
+        precalc_i.extend(is);
     }
 
     assert_eq!(precalc_r.len(), w);
index 150522fd02d4cb75ab41d8a0fb3c445bdb351b61..aa40f6f868c305b37f2b96e94dd58b78e7129449 100644 (file)
@@ -40,7 +40,7 @@
 
 // no-pretty-expanded FIXME #15189
 
-#![feature(core)]
+#![feature(iter_cmp)]
 
 use std::iter::repeat;
 use std::sync::Arc;
@@ -315,7 +315,7 @@ fn par_search(masks: Vec<Vec<Vec<u64>>>) -> Data {
 
     // launching the search in parallel on every masks at minimum
     // coordinate (0,0)
-    for m in (*masks)[0].iter().flat_map(|masks_pos| masks_pos.iter()) {
+    for m in (*masks)[0].iter().flat_map(|masks_pos| masks_pos) {
         let masks = masks.clone();
         let tx = tx.clone();
         let m = *m;
index 368dbbb931c269e5b48e8041526b7c7ada882873..5ba678ce183dd14cd8a3463dbcfb02321b33bba5 100644 (file)
@@ -158,7 +158,7 @@ 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 {
+    for bi in bodies.iter() {
         px += bi.vx * bi.mass;
         py += bi.vy * bi.mass;
         pz += bi.vz * bi.mass;
index 0fa22abde3cbd9ee695ec1b392bd9aa6d415b9c1..1598b20922338bb07a0f36da9c1e0e6ea319101b 100644 (file)
 // no-pretty-expanded FIXME #15189
 
 #![allow(non_snake_case)]
-#![feature(unboxed_closures, core, os, scoped)]
+#![feature(unboxed_closures, iter_arith, core_simd, scoped)]
 
 use std::iter::repeat;
 use std::thread;
-use std::mem;
-use std::os;
 use std::env;
-use std::raw::Repr;
 use std::simd::f64x2;
 
 fn main() {
@@ -107,7 +104,7 @@ fn A(i: usize, j: usize) -> f64 {
 }
 
 fn dot(v: &[f64], u: &[f64]) -> f64 {
-    v.iter().zip(u.iter()).map(|(a, b)| *a * *b).sum()
+    v.iter().zip(u).map(|(a, b)| *a * *b).sum()
 }
 
 
index d7e556a124fe1ff635b6cfa9c110469adf7ed0cb..6a39a6db0c7284769937e2e07c19db7d8600d916 100644 (file)
@@ -10,7 +10,7 @@
 
 // Microbenchmark for the smallintmap library
 
-#![feature(collections, duration, duration_span)]
+#![feature(vecmap, duration, duration_span)]
 
 use std::collections::VecMap;
 use std::env;
index babae4d149f52d45e88c1c72cc71c48302f2f9c0..3bd7b7812511200a53275609ea23cdfe92ada2bb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax, duration, duration_span, collections)]
+#![feature(box_syntax, duration, duration_span, vec_push_all)]
 
 use std::env;
 use std::thread;
diff --git a/src/test/codegen/coercions.rs b/src/test/codegen/coercions.rs
new file mode 100644 (file)
index 0000000..2a136d7
--- /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.
+
+// compile-flags: -C no-prepopulate-passes
+
+static X: i32 = 5;
+
+// CHECK-LABEL: @raw_ptr_to_raw_ptr_noop
+// CHECK-NOT: alloca
+#[no_mangle]
+pub fn raw_ptr_to_raw_ptr_noop() -> *const i32{
+    &X as *const i32
+}
+
+// CHECK-LABEL: @reference_to_raw_ptr_noop
+// CHECK-NOT: alloca
+#[no_mangle]
+pub fn reference_to_raw_ptr_noop() -> *const i32 {
+    &X
+}
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
new file mode 100644 (file)
index 0000000..7706c97
--- /dev/null
@@ -0,0 +1,142 @@
+// 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
+
+#![feature(allocator)]
+
+pub struct S {
+  _field: [i64; 4],
+}
+
+pub struct UnsafeInner {
+  _field: std::cell::UnsafeCell<i16>,
+}
+
+// CHECK: zeroext i1 @boolean(i1 zeroext)
+#[no_mangle]
+pub fn boolean(x: bool) -> bool {
+  x
+}
+
+// CHECK: @readonly_borrow(i32* noalias readonly dereferenceable(4))
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+pub fn readonly_borrow(_: &i32) {
+}
+
+// CHECK: @static_borrow(i32* noalias readonly dereferenceable(4))
+// static borrow may be captured
+#[no_mangle]
+pub fn static_borrow(_: &'static i32) {
+}
+
+// CHECK: @named_borrow(i32* noalias readonly dereferenceable(4))
+// borrow with named lifetime may be captured
+#[no_mangle]
+pub fn named_borrow<'r>(_: &'r i32) {
+}
+
+// CHECK: @unsafe_borrow(%UnsafeInner* dereferenceable(2))
+// unsafe interior means this isn't actually readonly and there may be aliases ...
+#[no_mangle]
+pub fn unsafe_borrow(_: &UnsafeInner) {
+}
+
+// CHECK: @mutable_unsafe_borrow(%UnsafeInner* noalias dereferenceable(2))
+// ... unless this is a mutable borrow, those never alias
+#[no_mangle]
+pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
+}
+
+// CHECK: @mutable_borrow(i32* noalias dereferenceable(4))
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+pub fn mutable_borrow(_: &mut i32) {
+}
+
+// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32))
+#[no_mangle]
+pub fn indirect_struct(_: S) {
+}
+
+// CHECK: @borrowed_struct(%S* noalias readonly dereferenceable(32))
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+pub fn borrowed_struct(_: &S) {
+}
+
+// CHECK: noalias dereferenceable(4) i32* @_box(i32* noalias dereferenceable(4))
+#[no_mangle]
+pub fn _box(x: Box<i32>) -> Box<i32> {
+  x
+}
+
+// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32))
+#[no_mangle]
+pub fn struct_return() -> S {
+  S {
+    _field: [0, 0, 0, 0]
+  }
+}
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]])
+#[no_mangle]
+fn helper(_: usize) {
+}
+
+// CHECK: @slice(i8* noalias nonnull readonly, [[USIZE]])
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+fn slice(_: &[u8]) {
+}
+
+// CHECK: @mutable_slice(i8* noalias nonnull, [[USIZE]])
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+fn mutable_slice(_: &mut [u8]) {
+}
+
+// CHECK: @unsafe_slice(%UnsafeInner* nonnull, [[USIZE]])
+// unsafe interior means this isn't actually readonly and there may be aliases ...
+#[no_mangle]
+pub fn unsafe_slice(_: &[UnsafeInner]) {
+}
+
+// CHECK: @str(i8* noalias nonnull readonly, [[USIZE]])
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+fn str(_: &[u8]) {
+}
+
+// CHECK: @trait_borrow(i8* nonnull, void (i8*)** nonnull)
+// FIXME #25759 This should also have `nocapture`
+#[no_mangle]
+fn trait_borrow(_: &Drop) {
+}
+
+// CHECK: @trait_box(i8* noalias nonnull, void (i8*)** nonnull)
+#[no_mangle]
+fn trait_box(_: Box<Drop>) {
+}
+
+// CHECK: { i16*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly, [[USIZE]])
+#[no_mangle]
+fn return_slice(x: &[u16]) -> &[u16] {
+  x
+}
+
+// CHECK: noalias i8* @allocator()
+#[no_mangle]
+#[allocator]
+pub fn allocator() -> *const i8 {
+  std::ptr::null()
+}
diff --git a/src/test/codegen/iterate-over-array.cc b/src/test/codegen/iterate-over-array.cc
deleted file mode 100644 (file)
index 9261bdd..0000000
+++ /dev/null
@@ -1,27 +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.
-
-#include <stdlib.h>
-#include <assert.h>
-
-struct slice {
-  int const *p;
-  size_t len;
-};
-
-extern "C"
-size_t test(slice s) {
-  size_t y = 0;
-  for (int i = 0; i < s.len; ++i) {
-       assert(i < s.len);
-       y += s.p[i];
-  }
-  return y;
-}
diff --git a/src/test/codegen/iterate-over-array.rs b/src/test/codegen/iterate-over-array.rs
deleted file mode 100644 (file)
index a5b4492..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.
-
-#[no_mangle]
-pub fn test(x: &[isize]) -> isize {
-    let mut y = 0;
-    let mut i = 0;
-    while (i < x.len()) {
-        y += x[i];
-        i += 1;
-    }
-    y
-}
diff --git a/src/test/codegen/loads.rs b/src/test/codegen/loads.rs
new file mode 100644 (file)
index 0000000..45b8731
--- /dev/null
@@ -0,0 +1,52 @@
+// 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
+
+pub struct Bytes {
+  a: u8,
+  b: u8,
+  c: u8,
+  d: u8,
+}
+
+// CHECK-LABEL: @borrow
+#[no_mangle]
+pub fn borrow(x: &i32) -> &i32 {
+// CHECK: load i32*, i32** %x{{.*}}, !nonnull
+    x
+}
+
+// CHECK-LABEL: @_box
+#[no_mangle]
+pub fn _box(x: Box<i32>) -> i32 {
+// CHECK: load i32*, i32** %x{{.*}}, !nonnull
+    *x
+}
+
+// CHECK-LABEL: small_array_alignment
+// The array is loaded as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
+// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
+// CHECK: ret i32 [[VAR]]
+    x
+}
+
+// CHECK-LABEL: small_struct_alignment
+// The struct is loaded as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+pub fn small_struct_alignment(x: Bytes) -> Bytes {
+// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
+// CHECK: ret i32 [[VAR]]
+    x
+}
diff --git a/src/test/codegen/scalar-function-call.cc b/src/test/codegen/scalar-function-call.cc
deleted file mode 100644 (file)
index ce3173c..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.
-
-#include <stdlib.h>
-
-size_t foo(size_t x) {
-    return x * x;
-}
-
-extern "C"
-void test() {
-    size_t x = foo(10);
-}
diff --git a/src/test/codegen/scalar-function-call.rs b/src/test/codegen/scalar-function-call.rs
deleted file mode 100644 (file)
index fe93c86..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo(x: isize) -> isize {
-    x * x
-}
-
-#[no_mangle]
-pub fn test() {
-    let _x = foo(10);
-}
diff --git a/src/test/codegen/single-return-value.cc b/src/test/codegen/single-return-value.cc
deleted file mode 100644 (file)
index 97d80d3..0000000
+++ /dev/null
@@ -1,14 +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.
-
-extern "C"
-int test() {
-  return 5;
-}
diff --git a/src/test/codegen/single-return-value.rs b/src/test/codegen/single-return-value.rs
deleted file mode 100644 (file)
index 5addba1..0000000
+++ /dev/null
@@ -1,14 +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.
-
-#[no_mangle]
-pub fn test() -> isize {
-    5
-}
diff --git a/src/test/codegen/small-dense-int-switch.cc b/src/test/codegen/small-dense-int-switch.cc
deleted file mode 100644 (file)
index db93829..0000000
+++ /dev/null
@@ -1,21 +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.
-
-#include <stdlib.h>
-
-extern "C"
-size_t test(size_t x, size_t y) {
-  switch (x) {
-  case 1: return y;
-  case 2: return y*2;
-  case 4: return y*3;
-  default: return 11;
-  }
-}
diff --git a/src/test/codegen/small-dense-int-switch.rs b/src/test/codegen/small-dense-int-switch.rs
deleted file mode 100644 (file)
index cf05a2e..0000000
+++ /dev/null
@@ -1,19 +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.
-
-#[no_mangle]
-pub fn test(x: isize, y: isize) -> isize {
-    match x {
-        1 => y,
-        2 => y*2,
-        4 => y*3,
-        _ => 11
-    }
-}
diff --git a/src/test/codegen/stack-alloc-string-slice.cc b/src/test/codegen/stack-alloc-string-slice.cc
deleted file mode 100644 (file)
index a81f76e..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.
-
-#include <stddef.h>
-
-struct slice {
-  char const *p;
-  size_t len;
-};
-
-extern "C"
-void test() {
-  struct slice s = { .p = "hello",
-                     .len = 5 };
-}
diff --git a/src/test/codegen/stack-alloc-string-slice.rs b/src/test/codegen/stack-alloc-string-slice.rs
deleted file mode 100644 (file)
index 188ee24..0000000
+++ /dev/null
@@ -1,14 +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.
-
-#[no_mangle]
-pub fn test() {
-    let _x = "hello";
-}
diff --git a/src/test/codegen/static-method-call-multi.cc b/src/test/codegen/static-method-call-multi.cc
deleted file mode 100644 (file)
index 6c03e32..0000000
+++ /dev/null
@@ -1,27 +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.
-
-#include <stdlib.h>
-
-struct Struct {
-  size_t field;
-  size_t method(size_t x) {
-       return this->field + x;
-  }
-};
-
-extern "C"
-size_t test(Struct &a,
-                       Struct &b,
-                       Struct &c,
-                       Struct &d,
-                       Struct &e) {
-  return a.method(b.method(c.method(d.method(e.method(1)))));
-}
diff --git a/src/test/codegen/static-method-call-multi.rs b/src/test/codegen/static-method-call-multi.rs
deleted file mode 100644 (file)
index 025f9b5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub struct Struct {
-    field: isize
-}
-
-impl Struct {
-    fn method(&self, x: isize) -> isize {
-        self.field + x
-    }
-}
-
-#[no_mangle]
-pub fn test(a: &Struct,
-            b: &Struct,
-            c: &Struct,
-            d: &Struct,
-            e: &Struct) -> isize {
-    a.method(b.method(c.method(d.method(e.method(1)))))
-}
diff --git a/src/test/codegen/static-method-call.cc b/src/test/codegen/static-method-call.cc
deleted file mode 100644 (file)
index 36cfa4f..0000000
+++ /dev/null
@@ -1,23 +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.
-
-#include <stdlib.h>
-
-struct Struct {
-  size_t field;
-  size_t method() {
-       return this->field;
-  }
-};
-
-extern "C"
-size_t test(Struct &s) {
-  return s.method();
-}
diff --git a/src/test/codegen/static-method-call.rs b/src/test/codegen/static-method-call.rs
deleted file mode 100644 (file)
index fca3784..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub struct Struct {
-    field: isize
-}
-
-impl Struct {
-    fn method(&self) -> isize {
-        self.field
-    }
-}
-
-#[no_mangle]
-pub fn test(s: &Struct) -> isize {
-    s.method()
-}
diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs
new file mode 100644 (file)
index 0000000..15cf76b
--- /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.
+
+// compile-flags: -C no-prepopulate-passes
+
+pub struct Bytes {
+  a: u8,
+  b: u8,
+  c: u8,
+  d: u8,
+}
+
+// CHECK-LABEL: small_array_alignment
+// The array is stored as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+pub fn small_array_alignment(x: &mut [i8; 4]) {
+// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]*, [4 x i8]** %x
+// CHECK: [[VAR2:%[0-9]+]] = bitcast [4 x i8]* [[VAR]] to i32*
+// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
+    *x = [0; 4];
+}
+
+// CHECK-LABEL: small_struct_alignment
+// The struct is stored as i32, but its alignment is lower, go with 1 byte to avoid target
+// dependent alignment
+#[no_mangle]
+pub fn small_struct_alignment(x: &mut Bytes) {
+// CHECK: [[VAR:%[0-9]+]] = load %Bytes*, %Bytes** %x
+// CHECK: [[VAR2:%[0-9]+]] = bitcast %Bytes* [[VAR]] to i32*
+// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
+    *x = Bytes {
+        a: 0,
+        b: 0,
+        c: 0,
+        d: 0,
+    };
+}
diff --git a/src/test/codegen/virtual-method-call-struct-return.cc b/src/test/codegen/virtual-method-call-struct-return.cc
deleted file mode 100644 (file)
index 345f21c..0000000
+++ /dev/null
@@ -1,25 +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.
-
-#include <stdlib.h>
-
-struct Stuff {
-  size_t a;
-  double b;
-};
-
-struct Struct {
-  virtual Stuff method() = 0;
-};
-
-extern "C"
-size_t test(Struct &s) {
-  return s.method().a;
-}
diff --git a/src/test/codegen/virtual-method-call-struct-return.rs b/src/test/codegen/virtual-method-call-struct-return.rs
deleted file mode 100644 (file)
index ae83409..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub struct Stuff {
-  a: isize,
-  b: f64
-}
-
-pub trait Trait {
-    fn method(&self) -> Stuff;
-}
-
-#[no_mangle]
-pub fn test(t: &Trait) -> isize {
-    t.method().a
-}
diff --git a/src/test/codegen/virtual-method-call.cc b/src/test/codegen/virtual-method-call.cc
deleted file mode 100644 (file)
index 9fcafdf..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.
-
-#include <stdlib.h>
-
-struct Struct {
-  virtual size_t method() = 0;
-};
-
-extern "C"
-size_t test(Struct &s) {
-  return s.method();
-}
diff --git a/src/test/codegen/virtual-method-call.rs b/src/test/codegen/virtual-method-call.rs
deleted file mode 100644 (file)
index 9bfeef1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub trait Trait {
-    fn method(&self) -> isize;
-}
-
-#[no_mangle]
-pub fn test(t: &Trait) -> isize {
-    t.method()
-}
diff --git a/src/test/compile-fail-fulldeps/plugin-attr-register-deny.rs b/src/test/compile-fail-fulldeps/plugin-attr-register-deny.rs
new file mode 100644 (file)
index 0000000..0d2a5a3
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:attr_plugin_test.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![plugin(attr_plugin_test)]
+#![deny(unused_attributes)]
+
+#[baz]
+fn baz() { } // no error
+
+#[foo]
+pub fn main() {
+     //~^^ ERROR unused
+    #[bar]
+    fn inner() {}
+    //~^^ ERROR crate
+    //~^^^ ERROR unused
+    baz();
+    inner();
+}
index cf68efe5855b754659c918c778da6e5de52be419..c83a154056ba24b8cf4c77b519959384eaad1a14 100644 (file)
@@ -20,7 +20,7 @@ use syntax::parse;
 use syntax::print::pprust;
 
 fn main() {
-    let ps = syntax::parse::new_parse_sess();
+    let ps = syntax::parse::ParseSess::new();
     let mut cx = syntax::ext::base::ExtCtxt::new(
         &ps, vec![],
         syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
index 5ebcdb20b19523d44c6ab7ae1638ec71cb0b8369..79f0c436759b389f957be0b1562c5eef8c874658 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 //
-// ignore-stage1 (#20184)
+// WONTFIX(#20184) Needs landing pads (not present in stage1) or the compiler hangs.
+// ignore-stage1
 // compile-flags: -C codegen-units=2
 // error-pattern: build without -C codegen-units for more exact errors
 
index e68c3e30b9a7b08f5a4da6c097a0e929fc644c07..7eab831258f2ecfdbdbc61d7670b3373d2cd83b7 100644 (file)
@@ -13,7 +13,7 @@
 struct Foo;
 
 impl Foo {
-    type Bar = isize; //~ERROR associated items are not allowed in inherent impls
+    type Bar = isize; //~ERROR associated types are not allowed in inherent impls
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/associated-const-type-parameters.rs b/src/test/compile-fail/associated-const-type-parameters.rs
new file mode 100644 (file)
index 0000000..e48ff59
--- /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.
+
+#![feature(associated_consts)]
+
+pub trait Foo {
+    const MIN: i32;
+
+    fn get_min() -> i32 {
+        Self::MIN //~ ERROR E0329
+    }
+}
+
+fn get_min<T: Foo>() -> i32 {
+    T::MIN; //~ ERROR E0329
+    <T as Foo>::MIN //~ ERROR E0329
+}
+
+fn main() {}
index 1c708da30a70707194ef6891c708475f1e04f119..c1feb8ac45900a052d0ae393029bd71787c9e5ac 100644 (file)
@@ -28,15 +28,15 @@ impl Foo for isize {
 }
 
 pub fn main() {
-    let a = &42 as &Foo<A=usize, B=char>;
+    let a = &42isize as &Foo<A=usize, B=char>;
 
-    let b = &42 as &Foo<A=usize>;
+    let b = &42isize as &Foo<A=usize>;
     //~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
 
-    let c = &42 as &Foo<B=char>;
+    let c = &42isize as &Foo<B=char>;
     //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
 
-    let d = &42 as &Foo;
+    let d = &42isize as &Foo;
     //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
     //~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
 }
index b9a62ff4e417afd9d3840bdc836bb69ff8c53cd7..e603cca7f384b838f6ff6313de42723bdf088025 100644 (file)
@@ -45,7 +45,6 @@ pub fn f1_uint_uint() {
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR the trait `Foo` is not implemented
-    //~| ERROR the trait `Foo` is not implemented
 }
 
 pub fn f2_int() {
index 38ba652f53bc3931678e33b31ec1b92b8bafbd11..c35c9255ed28e8353928d9d1a92e348578166ec3 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `m1::a`. Did you mean `args`?
+// error-pattern: unresolved name `m1::arguments`. Did you mean `arguments`?
 
 mod m1 {}
 
-fn main(args: Vec<String>) { log(debug, m1::a); }
+fn main(arguments: Vec<String>) { log(debug, m1::arguments); }
index f397d0b387da5d4fa538d53983de57ab621aeba6..af34887dec954fda455c740c5d55984cad3a586e 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name `m1::a`. Did you mean `args`?
+// error-pattern: unresolved name `m1::arguments`. Did you mean `arguments`?
 
 mod m1 {
-    pub mod a {}
+    pub mod arguments {}
 }
 
-fn main(args: Vec<String>) {
-    log(debug, m1::a);
+fn main(arguments: Vec<String>) {
+    log(debug, m1::arguments);
 }
index 8310d4ba1444af4ed249726f6867424948604751..7284fa7a850f0cbd63aedac91cc1c4ddf429e3c3 100644 (file)
@@ -10,7 +10,7 @@
 
 
 fn foo(x: *const Box<isize>) -> Box<isize> {
-    let y = *x; //~ ERROR dereference of unsafe pointer requires unsafe function or block
+    let y = *x; //~ ERROR dereference of raw pointer requires unsafe function or block
     return y;
 }
 
index a6d55ad3991f393e142c3872aacaef4d186e55e4..037364c7a531c4ff64a64504fe02bfb61ec62e27 100644 (file)
@@ -23,5 +23,5 @@ impl <T: Sync> Foo for T { }
 fn main() {
     let (tx, rx) = channel();
     1193182.foo(tx);
-    assert!(rx.recv() == 1193182);
+    assert_eq!(rx.recv(), 1193182);
 }
diff --git a/src/test/compile-fail/cast-ptr-to-int-const.rs b/src/test/compile-fail/cast-ptr-to-int-const.rs
new file mode 100644 (file)
index 0000000..7c32e31
--- /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() {
+    const X: u32 = main as u32; //~ ERROR E0018
+    const Y: u32 = 0;
+    const Z: u32 = &Y as *const u32 as u32; //~ ERROR E0018
+}
diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs
new file mode 100644 (file)
index 0000000..29ce8c1
--- /dev/null
@@ -0,0 +1,81 @@
+// 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 illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
+{
+    u as *const V //~ ERROR vtable kinds
+}
+
+fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
+{
+    u as *const str //~ ERROR vtable kinds
+}
+
+trait Foo { fn foo(&self) {} }
+impl<T> Foo for T {}
+
+trait Bar { fn foo(&self) {} }
+impl<T> Bar for T {}
+
+enum E {
+    A, B
+}
+
+fn main()
+{
+    let f: f32 = 1.2;
+    let v = 0 as *const u8;
+    let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
+    let foo: &Foo = &f;
+
+    let _ = v as &u8; //~ ERROR non-scalar
+    let _ = v as E; //~ ERROR non-scalar
+    let _ = v as fn(); //~ ERROR non-scalar
+    let _ = v as (u32,); //~ ERROR non-scalar
+    let _ = Some(&v) as *const u8; //~ ERROR non-scalar
+
+    let _ = v as f32; //~ ERROR through a usize first
+    let _ = main as f64; //~ ERROR through a usize first
+    let _ = &v as usize; //~ ERROR through a raw pointer first
+    let _ = f as *const u8; //~ ERROR through a usize first
+    let _ = 3 as bool; //~ ERROR compare with zero
+    let _ = E::A as bool; //~ ERROR compare with zero
+    let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
+
+    let _ = false as f32; //~ ERROR through an integer first
+    let _ = E::A as f32; //~ ERROR through an integer first
+    let _ = 'a' as f32; //~ ERROR through an integer first
+
+    let _ = false as *const u8; //~ ERROR through a usize first
+    let _ = E::A as *const u8; //~ ERROR through a usize first
+    let _ = 'a' as *const u8; //~ ERROR through a usize first
+
+    let _ = 42usize as *const [u8]; //~ ERROR illegal cast
+    let _ = v as *const [u8]; //~ ERROR illegal cast
+    let _ = fat_v as *const Foo;
+    //~^ ERROR `core::marker::Sized` is not implemented for the type `[u8]`
+    let _ = foo as *const str; //~ ERROR illegal cast
+    let _ = foo as *mut str; //~ ERROR illegal cast
+    let _ = main as *mut str; //~ ERROR illegal cast
+    let _ = &f as *mut f32; //~ ERROR illegal cast
+    let _ = &f as *const f64; //~ ERROR illegal cast
+    let _ = fat_v as usize; //~ ERROR through a raw pointer first
+
+    let a : *const str = "hello";
+    let _ = a as *const Foo;
+    //~^ ERROR `core::marker::Sized` is not implemented for the type `str`
+
+    // check no error cascade
+    let _ = main.f as *const u32; //~ ERROR attempted access of field
+
+    let cf: *const Foo = &0;
+    let _ = cf as *const [u8]; //~ ERROR vtable kinds
+    let _ = cf as *const Bar; //~ ERROR vtable kinds
+}
index a7f0917ed86b9a15da621a1c150f541744fc4f11..7cc5c727bc7df786e045124167adf0757df82167 100644 (file)
@@ -13,7 +13,7 @@ fn foo(_x: isize) { }
 fn main() {
     let v: u64 = 5;
     let x = foo as extern "C" fn() -> isize;
-    //~^ ERROR mismatched types
+    //~^ ERROR non-scalar cast
     let y = v as extern "Rust" fn(isize) -> (isize, isize);
     //~^ ERROR non-scalar cast
     y(x());
index 0180bccbca40bcfd752fc17c855814554a583196..c3a1de11752f813460c1d33e622a576893d23a5a 100644 (file)
@@ -117,7 +117,7 @@ static mut STATIC14: SafeStruct = SafeStruct {
 //~^ ERROR mutable statics are not allowed to have destructors
     field1: SafeEnum::Variant1,
     field2: SafeEnum::Variant4("str".to_string())
-//~^ ERROR static contains unimplemented expression type
+//~^ ERROR method calls in statics are limited to constant inherent methods
 };
 
 static STATIC15: &'static [Box<MyOwned>] = &[
index 23f4218fc1ebda71b1ae5e674f053d5b63b7471c..332965cc94014ae89e9ecdb98abfe974c98d3ad9 100644 (file)
@@ -15,14 +15,14 @@ trait Foo { fn dummy(&self) { } }
 trait Bar: Foo { }
 trait Baz: Bar { }
 
-// Subtraits of Baz are not legal:
+// Supertraits of Baz are not legal:
 impl Foo for Baz { }   //~ ERROR E0371
 impl Bar for Baz { }   //~ ERROR E0371
 impl Baz for Baz { }   //~ ERROR E0371
 
 // But other random traits are:
 trait Other { }
-impl Other for Baz { } // OK, Bar not a subtrait of Baz
+impl Other for Baz { } // OK, Other not a supertrait of Baz
 
 // If the trait is not object-safe, we give a more tailored message
 // because we're such schnuckels:
index 6e3732908ac06451beb0f61b3d74f802d0ccf62e..e6851f02cb6079b3734119a355ecfd317274a7aa 100644 (file)
@@ -9,18 +9,8 @@
 // except according to those terms.
 
 static a: &'static str = "foo";
-static b: *const u8 = a as *const u8;
-//~^ ERROR mismatched types
-//~| expected *const u8
-//~| found &'static str
-//~| expected u8
-//~| found str
-static c: *const u8 = &a as *const u8;
-//~^ ERROR mismatched types
-//~| expected *const u8
-//~| found &&'static str
-//~| expected u8
-//~| found &-ptr
+static b: *const u8 = a as *const u8; //~ ERROR illegal cast
+static c: *const u8 = &a as *const u8; //~ ERROR illegal cast
 
 fn main() {
 }
diff --git a/src/test/compile-fail/const-deref-ptr.rs b/src/test/compile-fail/const-deref-ptr.rs
new file mode 100644 (file)
index 0000000..fa15f3e
--- /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.
+
+// Check that you can't dereference raw pointers in constants.
+
+fn main() {
+    static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~ ERROR E0396
+    println!("{}", C);
+}
diff --git a/src/test/compile-fail/const-fn-mismatch.rs b/src/test/compile-fail/const-fn-mismatch.rs
new file mode 100644 (file)
index 0000000..d813cf3
--- /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.
+
+// Test that we can't declare a const fn in an impl -- right now it's
+// just not allowed at all, though eventually it'd make sense to allow
+// it if the trait fn is const (but right now no trait fns can be
+// const).
+
+#![feature(const_fn)]
+
+trait Foo {
+    fn f() -> u32;
+}
+
+impl Foo for u32 {
+    const fn f() -> u32 { 22 } //~ ERROR E0379
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/const-fn-not-in-trait.rs b/src/test/compile-fail/const-fn-not-in-trait.rs
new file mode 100644 (file)
index 0000000..191f3e0
--- /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.
+
+// Test that const fn is illegal in a trait declaration, whether or
+// not a default is provided.
+
+#![feature(const_fn)]
+
+trait Foo {
+    const fn f() -> u32; //~ ERROR trait fns cannot be declared const
+    const fn g() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/const-fn-not-safe-for-const.rs b/src/test/compile-fail/const-fn-not-safe-for-const.rs
new file mode 100644 (file)
index 0000000..baa3eba
--- /dev/null
@@ -0,0 +1,47 @@
+// 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 can't call random fns in a const fn or do other bad things.
+
+#![feature(const_fn)]
+
+use std::mem::transmute;
+
+fn random() -> u32 { 0 }
+
+const fn sub(x: &u32) -> usize {
+    unsafe { transmute(x) } //~ ERROR E0015
+}
+
+const fn sub1() -> u32 {
+    random() //~ ERROR E0015
+}
+
+static Y: u32 = 0;
+
+const fn get_Y() -> u32 {
+    Y
+        //~^ ERROR E0013
+        //~| ERROR cannot refer to other statics by value
+}
+
+const fn get_Y_addr() -> &'static u32 {
+    &Y
+        //~^ ERROR E0013
+}
+
+const fn get() -> u32 {
+    let x = 22; //~ ERROR E0016
+    let y = 44; //~ ERROR E0016
+    x + y
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/const-fn-stability-calls-2.rs b/src/test/compile-fail/const-fn-stability-calls-2.rs
new file mode 100644 (file)
index 0000000..dd9a415
--- /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.
+
+// Test use of const fn from another crate without a feature gate.
+
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+fn main() {
+    let x: [usize; foo()] = []; //~ ERROR unsupported constant expr
+}
diff --git a/src/test/compile-fail/const-fn-stability-calls-3.rs b/src/test/compile-fail/const-fn-stability-calls-3.rs
new file mode 100644 (file)
index 0000000..0f413b0
--- /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.
+
+// Test use of const fn from another crate without a feature gate.
+
+#![feature(rustc_attrs)]
+#![allow(unused_variables)]
+
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+    let x = foo(); // use outside a constant is ok
+}
diff --git a/src/test/compile-fail/const-fn-stability-calls.rs b/src/test/compile-fail/const-fn-stability-calls.rs
new file mode 100644 (file)
index 0000000..6090776
--- /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.
+
+// Test use of const fn from another crate without a feature gate.
+
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+static FOO: usize = foo(); //~ ERROR const fns are an unstable feature
+const BAR: usize = foo(); //~ ERROR const fns are an unstable feature
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo() //~ ERROR const fns are an unstable feature
+}
+
+fn main() {
+//    let x: [usize; foo()] = [];
+}
diff --git a/src/test/compile-fail/const-fn-stability.rs b/src/test/compile-fail/const-fn-stability.rs
new file mode 100644 (file)
index 0000000..9913c2f
--- /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.
+
+// Test use of const fn without feature gate.
+
+const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+
+trait Foo {
+    const fn foo() -> u32; //~ ERROR const fn is unstable
+    const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+impl Foo {
+    const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+impl Foo for u32 {
+    const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [];
+}
diff --git a/src/test/compile-fail/cross-fn-cache-hole.rs b/src/test/compile-fail/cross-fn-cache-hole.rs
new file mode 100644 (file)
index 0000000..0aefd0a
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.
+
+// Check that when there are vacuous predicates in the environment
+// (which make a fn uncallable) we don't erroneously cache those and
+// then consider them satisfied elsewhere. The current technique for
+// doing this is just to filter "global" predicates out of the
+// environment, which means that we wind up with an error in the
+// function `vacuous`, because even though `i32: Bar<u32>` is implied
+// by its where clause, that where clause never holds.
+
+trait Foo<X,Y>: Bar<X> {
+}
+
+trait Bar<X> { }
+
+fn vacuous<A>()
+    where i32: Foo<u32, A>
+{
+    // vacuous could never be called, because it requires that i32:
+    // Bar<u32>. But the code doesn't check that this could never be
+    // satisfied.
+    require::<i32, u32>();
+    //~^ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
+}
+
+fn require<A,B>()
+    where A: Bar<B>
+{
+}
+
+fn main() {
+    require::<i32, u32>();
+}
index 280e2ed095266f54f943de374503a38a86bc62f7..d808d7972721f5786b8750d80bd2d4eea7b0c3d1 100644 (file)
@@ -15,5 +15,5 @@
 fn main() {
     let x = || panic!();
     x();
-    std::io::println("Foo bar"); //~ ERROR: unreachable statement
+    println!("Foo bar"); //~ ERROR: unreachable statement
 }
index 3f455e148a09be30fb0919dfd00f1279f3b0491e..08db643df00e4736003e083e012f3e9898fbb587 100644 (file)
@@ -28,29 +28,29 @@ fn main() {
     // if n > m, it's a type mismatch error.
 
     // n < m
-    let &x = &(&1 as &T);
-    let &x = &&(&1 as &T);
-    let &&x = &&(&1 as &T);
+    let &x = &(&1isize as &T);
+    let &x = &&(&1isize as &T);
+    let &&x = &&(&1isize as &T);
 
     // n == m
-    let &x = &1 as &T;      //~ ERROR type `&T` cannot be dereferenced
-    let &&x = &(&1 as &T);  //~ ERROR type `&T` cannot be dereferenced
-    let box x = box 1 as Box<T>; //~ ERROR the trait `core::marker::Sized` is not implemented
+    let &x = &1isize as &T;      //~ ERROR type `&T` cannot be dereferenced
+    let &&x = &(&1isize as &T);  //~ ERROR type `&T` cannot be dereferenced
+    let box x = box 1isize as Box<T>; //~ ERROR the trait `core::marker::Sized` is not implemented
 
     // n > m
-    let &&x = &1 as &T;
+    let &&x = &1isize as &T;
     //~^ ERROR mismatched types
     //~| expected `T`
     //~| found `&_`
     //~| expected trait T
     //~| found &-ptr
-    let &&&x = &(&1 as &T);
+    let &&&x = &(&1isize as &T);
     //~^ ERROR mismatched types
     //~| expected `T`
     //~| found `&_`
     //~| expected trait T
     //~| found &-ptr
-    let box box x = box 1 as Box<T>;
+    let box box x = box 1isize as Box<T>;
     //~^ ERROR mismatched types
     //~| expected `T`
     //~| found `Box<_>`
index f3c3f31e4afc629e8cf29c52bd300232abd6e21c..19f790ddc90717875b915d866a5bd7670bfe7ae0 100644 (file)
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
+#![feature(const_fn)]
+
 use std::cell::Cell;
 use id::Id;
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
-    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index 10bfe70640ca820ae84c011c8e1b6f066764f087..584e5eabf0cd8f7e21cee5de46b9ea11bcfac8e3 100644 (file)
@@ -17,6 +17,7 @@
 //  for the error message we see here.)
 
 #![allow(unstable)]
+#![feature(const_fn)]
 
 extern crate arena;
 
@@ -26,9 +27,9 @@ use id::Id;
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
-    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index 6e543d017f26045b10177d560f656d0531d499bc..6e0679da949e1792c3e3881ed0a915175c53511a 100644 (file)
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
+#![feature(const_fn)]
+
 use std::cell::Cell;
 use id::Id;
 
 mod s {
-    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
-    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index 53a14fd8fac926a5d7069b79c954b52711f2a386..bc33ff8399aa5611fd59cd17c55469a61e0fec16 100644 (file)
 //
 // (Compare against compile-fail/dropck_arr_cycle_checked.rs)
 
+#![feature(const_fn)]
+
 use std::cell::Cell;
 use id::Id;
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
-    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index b4fd45845f7a024da42365a2a0639b0927cda1be..da667dcb1e88253feba1aa1682adfbd2f201ef6b 100644 (file)
@@ -12,6 +12,7 @@
 
 trait Foo { fn foo(&self) {} }
 impl Foo for str {}
+impl Foo for [u8] {}
 
 fn test1<T: ?Sized + Foo>(t: &T) {
     let u: &Foo = t;
@@ -28,9 +29,9 @@ fn test3() {
     //~^ ERROR `core::marker::Sized` is not implemented for the type `str`
 }
 
-fn test4() {
-    let _: &Foo = "hi" as &Foo;
-    //~^ ERROR `core::marker::Sized` is not implemented for the type `str`
+fn test4(x: &[u8]) {
+    let _: &Foo = x as &Foo;
+    //~^ ERROR `core::marker::Sized` is not implemented for the type `[u8]`
 }
 
 fn main() { }
index 2099424b05c281c1941d52ba8fe97ad10ae9299c..25cab09b7cb497ff59f9b933ecb13b69e2b53a53 100644 (file)
@@ -8,20 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Make sure casts between thin pointer <-> fat pointer are illegal.
-
-pub trait Trait {}
+trait Trait {}
 
+// Make sure casts between thin-pointer <-> fat pointer obey RFC401
 fn main() {
     let a: &[i32] = &[1, 2, 3];
     let b: Box<[i32]> = Box::new([1, 2, 3]);
+    let p = a as *const [i32];
+    let q = a.as_ptr();
 
-    a as usize; //~ ERROR non-scalar cast
+    a as usize; //~ ERROR illegal cast
     b as usize; //~ ERROR non-scalar cast
+    p as usize; //~ ERROR illegal cast; cast through a raw pointer
 
-    let a: usize = 42;
-    a as *const [i32]; //~ ERROR cast to fat pointer: `usize` as `*const [i32]`
+    // #22955
+    q as *const [i32]; //~ ERROR illegal cast
 
-    let a: *const u8 = &42;
-    a as *const [u8]; //~ ERROR cast to fat pointer: `*const u8` as `*const [u8]`
+    // #21397
+    let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR illegal cast
+    let mut fail: *const str = 0 as *const str; //~ ERROR illegal cast
 }
diff --git a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs b/src/test/compile-fail/feature-gate-assoc-type-defaults.rs
new file mode 100644 (file)
index 0000000..fc4871a
--- /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.
+
+trait Foo {
+    type Bar = u8; //~ ERROR associated type defaults are unstable
+}
+
+fn main() {}
index dcd7a0ded812fcd7176d7143fe207ecfc34fb438..32c50b1b8c159b732b56ef4c5472d2785c5686e2 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(simd, core)]
+#![feature(simd, core_simd)]
 #![allow(dead_code)]
 
 use std::simd::f32x4;
diff --git a/src/test/compile-fail/feature-gate-static-assert.rs b/src/test/compile-fail/feature-gate-static-assert.rs
deleted file mode 100644 (file)
index 2574039..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.
-
-#[static_assert] //~ ERROR `#[static_assert]` is an experimental feature
-static X: bool = true;
-
-fn main() {}
index 51e23a689a1ad148266a61102aa82a54ec66191d..d2df0d9ef270204834ffaf8f1d96c204292d30ec 100644 (file)
 
 // RFC 736 (and Issue 21407): functional struct update should respect privacy.
 
+#![feature(const_fn)]
+
 // The `foo` module attempts to maintains an invariant that each `S`
 // has a unique `u64` id.
 use self::foo::S;
 mod foo {
     use std::cell::{UnsafeCell};
 
-    static mut count : UnsafeCell<u64> = UnsafeCell { value: 1 };
+    static mut count : UnsafeCell<u64> = UnsafeCell::new(1);
 
     pub struct S { pub a: u8, pub b: String, secret_uid: u64 }
 
index 3b4def8c5086954ff69b1ee9973c3981d4067c26..6201d9862bb6974da1296c603c010f5a8ee64276 100644 (file)
@@ -11,7 +11,7 @@
 struct Foo;
 impl Foo {
     fn orange(&self){}
-    fn orange(&self){}   //~ ERROR error: duplicate method
+    fn orange(&self){}   //~ ERROR duplicate method
 }
 
 fn main() {}
index ce3c8c52b0e477726a0d3151ef35e76ebbf17483..2249741cdaac5964b9913bfc07f5d003ce2dd1ef 100644 (file)
@@ -12,7 +12,7 @@ trait Trait {
     fn outer(self) {
         fn inner(_: Self) {
             //~^ ERROR can't use type parameters from outer function
-            //~^^ ERROR use of undeclared type name `Self`
+            //~^^ ERROR use of `Self` outside of an impl or trait
         }
     }
 }
index 3f994102a173e0853f052c0b7ba9f3d65e0864bc..219f08ad35a845917eb139e83b9352440a20e372 100644 (file)
@@ -15,18 +15,8 @@ struct X {
 
 fn main() {
     let x = X { a: [0] };
-    let _f = &x.a as *mut u8;
-    //~^ ERROR mismatched types
-    //~| expected `*mut u8`
-    //~| found `&[u8; 1]`
-    //~| expected u8
-    //~| found array of 1 elements
+    let _f = &x.a as *mut u8; //~ ERROR illegal cast
 
     let local: [u8; 1] = [0];
-    let _v = &local as *mut u8;
-    //~^ ERROR mismatched types
-    //~| expected `*mut u8`
-    //~| found `&[u8; 1]`
-    //~| expected u8,
-    //~| found array of 1 elements
+    let _v = &local as *mut u8; //~ ERROR illegal cast
 }
index 7da1b9efd3942c043d5176dfa8a0e6988541ae0c..a1663772bad136178b64221f5f38392461eab60a 100644 (file)
@@ -9,11 +9,6 @@
 // except according to those terms.
 
 // macro f should not be able to inject a reference to 'n'.
-//
-// Ignored because `for` loops are not hygienic yet; they will require special
-// handling since they introduce a new pattern binding position.
-
-// ignore-test
 
 macro_rules! f { () => (n) }
 
index a4e0f69b63b39e0b55c2353ca65c1d95221c6180..6f627bfe704a85d50329de907925fa8930ba68e1 100644 (file)
@@ -20,6 +20,7 @@ mod Y {
 
 static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
 //~^ ERROR the trait `core::marker::Sync` is not implemented for the type
-//~| ERROR function calls in statics are limited to struct and enum constructors
+//~| ERROR cannot refer to other statics by value, use the address-of operator or a constant instead
+//~| ERROR E0015
 
 fn main() {}
index 011a9c1777638b66b3ac8aa08736f9846745b90f..a079161d42efaf836b452dba541bdc33371a7e6c 100644 (file)
@@ -14,5 +14,5 @@ enum Test {
 
 fn main() {
     let _x = Test::Foo as *const isize;
-    //~^ ERROR illegal cast; cast through an integer first: `Test` as `*const isize`
+    //~^ ERROR illegal cast; cast through a usize first: `Test` as `*const isize`
 }
index d6f70ae1e57416498d181cd251d4f80fb423e79b..f5b7a0c13b7287fb26616b3df28c39b89fe7ed13 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 static X: usize = 0 as *const usize as usize;
-//~^ ERROR: can not cast a pointer to an integer in statics
+//~^ ERROR: raw pointers cannot be cast to integers in statics
 
 fn main() {
     assert_eq!(X, 0);
index dfa5bca8ccdb657b153f2235d798157d7ec2c416..ec6d1141c1a057aff2677424b9393f8884bc888d 100644 (file)
@@ -8,14 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_fn)]
+
 use std::cell::UnsafeCell;
 
-const A: UnsafeCell<usize> = UnsafeCell { value: 1 };
+const A: UnsafeCell<usize> = UnsafeCell::new(1);
 const B: &'static UnsafeCell<usize> = &A;
 //~^ ERROR: cannot borrow a constant which contains interior mutability
 
 struct C { a: UnsafeCell<usize> }
-const D: C = C { a: UnsafeCell { value: 1 } };
+const D: C = C { a: UnsafeCell::new(1) };
 const E: &'static UnsafeCell<usize> = &D.a;
 //~^ ERROR: cannot borrow a constant which contains interior mutability
 const F: &'static C = &D;
diff --git a/src/test/compile-fail/issue-18058.rs b/src/test/compile-fail/issue-18058.rs
new file mode 100644 (file)
index 0000000..bbb5402
--- /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.
+
+impl Undefined {}
+//~^ ERROR use of undeclared type name `Undefined`
+
+fn main() {}
index 43e9ca5fa6e7aa5b2bca45ff533377fb2134fee3..4601db9dba0fc11fdc741eb0d9ce3702de4abf65 100644 (file)
@@ -15,5 +15,5 @@ struct Obj<F> where F: FnMut() -> u32 {
 fn main() {
     let o = Obj { closure: || 42 };
     o.closure(); //~ ERROR no method named `closure` found
-    //~^ NOTE use `(s.closure)(...)` if you meant to call the function stored in the `closure` field
+    //~^ NOTE use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
 }
index a4a8eac682dc3c35b888f7c64d0ecd8c739801f2..258c63b7428b6f2c6314786345190f55fbbc7511 100644 (file)
 #[lang = "sized"]
 trait Sized { }
 
+struct S;
+
 #[start]
 fn main(_: isize, _: *const *const u8) -> isize {
+    let _ = S;
     0
 }
index fe7807042e55b706c3b8e2177a02d5b135012cb1..d3b97a9c058633a45fd9f15717e0c2717c4856ff 100644 (file)
@@ -40,8 +40,8 @@ pub fn main() {
     //~^ ERROR cannot move out of borrowed content
 
     let c = unsafe { *mut_ptr() };
-    //~^ ERROR cannot move out of dereference of unsafe pointer
+    //~^ ERROR cannot move out of dereference of raw pointer
 
     let d = unsafe { *const_ptr() };
-    //~^ ERROR cannot move out of dereference of unsafe pointer
+    //~^ ERROR cannot move out of dereference of raw pointer
 }
index a2cac55033c1f30b023b4f39dc1b9d19c66fd11c..16ce84715b154ce17e1c4bd1b883d140aaa8c577 100644 (file)
@@ -11,5 +11,5 @@
 struct Inches(i32);
 
 fn main() {
-    Inches as f32; //~ ERROR illegal cast; cast through an integer first
+    Inches as f32; //~ ERROR illegal cast; cast through a usize first
 }
index 1fdc87357143a6cbe55958a6634492dcacf06d8e..bcbc414d3534bb3245dbd086701a0a2d7c68305e 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0 as &std::any::Any; //~ ERROR cast to fat pointer: `i32` as `&core::any::Any`
+    0 as &std::any::Any; //~ ERROR non-scalar cast
 }
index 6983d1f0706a008f65526c43c1ca238c0d3afb53..442e6bcda5a092f855dc8577e805f339ee07d925 100644 (file)
@@ -10,7 +10,7 @@
 
 trait Expr : PartialEq<Self::Item> {
     //~^ ERROR: unsupported cyclic reference between types/traits detected
-    type Item = Expr;
+    type Item;
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-23073.rs b/src/test/compile-fail/issue-23073.rs
new file mode 100644 (file)
index 0000000..2d21917
--- /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(associated_type_defaults)]
+
+trait Foo { type T; }
+trait Bar {
+    type Foo: Foo;
+    type FooT = <<Self as Bar>::Foo>::T; //~ ERROR ambiguous associated type
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-23173.rs b/src/test/compile-fail/issue-23173.rs
new file mode 100644 (file)
index 0000000..946e4b9
--- /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.
+
+enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
+
+fn use_token(token: &Token) { unimplemented!() }
+
+fn main() {
+    use_token(&Token::Homura); //~ ERROR no associated item named
+}
diff --git a/src/test/compile-fail/issue-23589.rs b/src/test/compile-fail/issue-23589.rs
new file mode 100644 (file)
index 0000000..1c1d42d
--- /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() {
+    let v: Vec(&str) = vec!['1', '2'];
+    //~^ ERROR parenthesized parameters may only be used with a trait
+}
diff --git a/src/test/compile-fail/issue-2392.rs b/src/test/compile-fail/issue-2392.rs
new file mode 100644 (file)
index 0000000..c5598e8
--- /dev/null
@@ -0,0 +1,68 @@
+// 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(core)]
+use std::boxed::FnBox;
+
+struct Obj<F> where F: FnOnce() -> u32 {
+    closure: F,
+    not_closure: usize,
+}
+
+struct BoxedObj {
+    boxed_closure: Box<FnBox() -> u32>,
+}
+
+struct Wrapper<F> where F: FnMut() -> u32 {
+    wrap: Obj<F>,
+}
+
+fn func() -> u32 {
+    0
+}
+
+fn check_expression() -> Obj<Box<FnBox() -> u32>> {
+    Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
+}
+
+fn main() {
+    // test variations of function
+
+    let o_closure = Obj { closure: || 42, not_closure: 42 };
+    o_closure.closure(); //~ ERROR no method named `closure` found
+    //~^ NOTE use `(o_closure.closure)(...)` if you meant to call the function stored
+
+    o_closure.not_closure(); //~ ERROR no method named `not_closure` found
+    //~^ NOTE did you mean to write `o_closure.not_closure`?
+
+    let o_func = Obj { closure: func, not_closure: 5 };
+    o_func.closure(); //~ ERROR no method named `closure` found
+    //~^ NOTE use `(o_func.closure)(...)` if you meant to call the function stored
+
+    let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
+    boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
+    //~^ NOTE use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored
+
+    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
+    boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
+    //~^ NOTE use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored
+
+    // test expression writing in the notes
+
+    let w = Wrapper { wrap: o_func };
+    w.wrap.closure();//~ ERROR no method named `closure` found
+    //~^ NOTE use `(w.wrap.closure)(...)` if you meant to call the function stored
+
+    w.wrap.not_closure();//~ ERROR no method named `not_closure` found
+    //~^ NOTE did you mean to write `w.wrap.not_closure`?
+
+    check_expression().closure();//~ ERROR no method named `closure` found
+    //~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored
+}
diff --git a/src/test/compile-fail/issue-24081.rs b/src/test/compile-fail/issue-24081.rs
new file mode 100644 (file)
index 0000000..11376ce
--- /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::ops::Add; //~ ERROR import `Add` conflicts with type in this module
+use std::ops::Sub; //~ ERROR import `Sub` conflicts with type in this module
+use std::ops::Mul; //~ ERROR import `Mul` conflicts with type in this module
+use std::ops::Div; //~ ERROR import `Div` conflicts with existing submodule
+use std::ops::Rem; //~ ERROR import `Rem` conflicts with trait in this module
+
+type Add = bool;
+struct Sub { x: f32 }
+enum Mul { A, B }
+mod Div { }
+trait Rem { }
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-24322.rs b/src/test/compile-fail/issue-24322.rs
new file mode 100644 (file)
index 0000000..bb726ac
--- /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 B;
+
+impl B {
+    fn func(&self) -> u32 { 42 }
+}
+
+fn main() {
+    let x: &fn(&B) -> u32 = &B::func; //~ ERROR mismatched types
+}
index 7ac73a931f113db0d40803d880d13831e9de4965..1fca8eb6ac4f3272f49c4c7ef3ffa4c0cc69a206 100644 (file)
@@ -11,7 +11,7 @@
 fn main() {
     static foo: Fn() -> u32 = || -> u32 {
         //~^ ERROR: mismatched types:
-        //~| expected `core::ops::Fn() -> u32`,
+        //~| expected `core::ops::Fn() -> u32 + 'static`,
         //~| found closure
         //~| (expected trait core::ops::Fn,
         //~| found closure)
diff --git a/src/test/compile-fail/issue-2478.rs b/src/test/compile-fail/issue-2478.rs
deleted file mode 100644 (file)
index 3aea9c3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-
-fn foo<'a>() -> &'a isize {  //~ ERROR unconstrained region
-    return &x;
-}
-static x: isize = 5;
-fn main() {}
diff --git a/src/test/compile-fail/issue-24968.rs b/src/test/compile-fail/issue-24968.rs
new file mode 100644 (file)
index 0000000..f51b77b
--- /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 foo(_: Self) {
+    //~^ ERROR use of `Self` outside of an impl or trait
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-25396.rs b/src/test/compile-fail/issue-25396.rs
new file mode 100644 (file)
index 0000000..3ada57c
--- /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.
+
+use foo::baz;
+use bar::baz; //~ ERROR a module named `baz` has already been imported
+
+use foo::Quux;
+use bar::Quux; //~ ERROR a trait named `Quux` has already been imported
+
+use foo::blah;
+use bar::blah; //~ ERROR a type named `blah` has already been imported
+
+use foo::WOMP;
+use bar::WOMP; //~ ERROR a value named `WOMP` has already been imported
+
+fn main() {}
+
+mod foo {
+    pub mod baz {}
+    pub trait Quux { }
+    pub type blah = (f64, u32);
+    pub const WOMP: u8 = 5;
+}
+
+mod bar {
+    pub mod baz {}
+    pub type Quux = i32;
+    struct blah { x: i8 }
+    pub const WOMP: i8 = -5;
+}
diff --git a/src/test/compile-fail/issue-25700.rs b/src/test/compile-fail/issue-25700.rs
new file mode 100644 (file)
index 0000000..477c323
--- /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.
+
+struct S<T: 'static>(Option<&'static T>);
+
+trait Tr { type Out; }
+impl<T> Tr for T { type Out = T; }
+
+impl<T: 'static> Copy for S<T> where S<T>: Tr<Out=T> {}
+impl<T: 'static> Clone for S<T> where S<T>: Tr<Out=T> {
+    fn clone(&self) -> Self { *self }
+}
+fn main() {
+    let t = S::<()>(None);
+    drop(t);
+    drop(t); //~ ERROR use of moved value
+}
diff --git a/src/test/compile-fail/issue-25826.rs b/src/test/compile-fail/issue-25826.rs
new file mode 100644 (file)
index 0000000..00e1279
--- /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 id<T>(t: T) -> T { t }
+fn main() {
+    const A: bool = id::<u8> as *const () < id::<u16> as *const ();
+    //~^ ERROR raw pointers cannot be compared in constants [E0395]
+    println!("{}", A);
+}
diff --git a/src/test/compile-fail/issue-26194.rs b/src/test/compile-fail/issue-26194.rs
new file mode 100644 (file)
index 0000000..b5c875c
--- /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 S(String);
+
+impl S {
+    fn f(self: *mut S) -> String { self.0 }
+    //~^ ERROR mismatched self type
+}
+
+fn main() { S("".to_owned()).f(); }
diff --git a/src/test/compile-fail/issue-26262.rs b/src/test/compile-fail/issue-26262.rs
new file mode 100644 (file)
index 0000000..8d79fd4
--- /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.
+
+// Check that projections don't count as constraining type parameters.
+
+struct S<T>(T);
+
+trait Tr { type Assoc; fn test(); }
+
+impl<T: Tr> S<T::Assoc> {
+//~^ ERROR the type parameter `T` is not constrained
+    fn foo(self, _: T) {
+        T::test();
+    }
+}
+
+trait Trait1<T> { type Bar; }
+trait Trait2<'x> { type Foo; }
+
+impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+//~^ ERROR the lifetime parameter `'a` is not constrained
+    type Bar = &'a ();
+}
+
+fn main() {}
index 553436607d159ca79a940c3bcb6da3ebb64a4b92..328de9f8187e56d2f1b38658fca5db8fd3d806e6 100644 (file)
@@ -17,7 +17,7 @@ impl Foo {
         Foo { baz: 0 }.bar();
     }
 
-    fn bar() { //~ ERROR duplicate method
+    fn bar() { //~ ERROR duplicate associated function
     }
 }
 
index da32408e199249a400013283b282e565a81e563f..b1d96f9b5277885dbb62dea04ef58c23e3b11f34 100644 (file)
@@ -17,6 +17,6 @@ impl Foo for isize {
 }
 
 fn main() {
-    (&5 as &Foo).foo();
+    (&5isize as &Foo).foo();
     //~^ ERROR: no method named `foo` found for type `&Foo` in the current scope
 }
index 9e797019392450e201d0958e24809a6e031e03a8..8261862c5fc518545718f7605f423e4e113a4670 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Creating a stack closure which references an owned pointer and then
-// transferring ownership of the owned box before invoking the stack
+// Creating a stack closure which references an box and then
+// transferring ownership of the box before invoking the stack
 // closure results in a crash.
 
 #![feature(box_syntax)]
index 6a36b2f84bfc901e9992bba0905422cf4be94f0d..7d0a9007829926e1ea4bb198ffcfd4ef5d0ffa1e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(box_syntax)]
+#![feature(const_fn)]
 
 use std::cell::RefCell;
 
@@ -17,6 +18,5 @@ static boxed: Box<RefCell<isize>> = box RefCell::new(0);
 //~^ ERROR allocations are not allowed in statics
 //~| ERROR the trait `core::marker::Sync` is not implemented for the type
 //~| ERROR the trait `core::marker::Sync` is not implemented for the type
-//~| ERROR function calls in statics are limited to struct and enum constructors
 
 fn main() { }
index 95ab2bbab14a3e7e2f8f48db73242a2d78e71dc6..997c940c9547e9ffd24877c98b8cb35c25099342 100644 (file)
@@ -37,7 +37,7 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
     assert_copy::<&'static mut isize>(); //~ ERROR `core::marker::Copy` is not implemented
     assert_copy::<&'a mut isize>();  //~ ERROR `core::marker::Copy` is not implemented
 
-    // owned pointers are not ok
+    // boxes are not ok
     assert_copy::<Box<isize>>();   //~ ERROR `core::marker::Copy` is not implemented
     assert_copy::<String>();   //~ ERROR `core::marker::Copy` is not implemented
     assert_copy::<Vec<isize> >(); //~ ERROR `core::marker::Copy` is not implemented
index d4ee93e9ca5d665df18e742aa256643c3de90c07..3474a73b31fdcab834dc557911b1eab3eb09f15a 100644 (file)
@@ -28,7 +28,6 @@ fn f<T>(val: T) {
     let a = &t as &Gettable<T>;
     //~^ ERROR the trait `core::marker::Send` is not implemented
     //~^^ ERROR the trait `core::marker::Copy` is not implemented
-    //~^^^ ERROR the parameter type `T` may not live long enough
 }
 
 fn g<T>(val: T) {
@@ -51,8 +50,10 @@ fn foo2<'a>() {
 }
 
 fn foo3<'a>() {
-    let t: Box<S<String>> = box S(marker::PhantomData);
-    let a: Box<Gettable<String>> = t;
+    struct Foo; // does not impl Copy
+
+    let t: Box<S<Foo>> = box S(marker::PhantomData);
+    let a: Box<Gettable<Foo>> = t;
     //~^ ERROR the trait `core::marker::Copy` is not implemented
 }
 
diff --git a/src/test/compile-fail/lifetime-bound-will-change-warning.rs b/src/test/compile-fail/lifetime-bound-will-change-warning.rs
new file mode 100644 (file)
index 0000000..4b57570
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.
+
+// aux-build:lifetime_bound_will_change_warning_lib.rs
+
+// Test that we get suitable warnings when lifetime bound change will
+// cause breakage.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![feature(rustc_attrs)]
+
+extern crate lifetime_bound_will_change_warning_lib as lib;
+
+fn just_ref(x: &Fn()) {
+}
+
+fn ref_obj(x: &Box<Fn()>) {
+    // this will change to &Box<Fn()+'static>...
+
+    // Note: no warning is issued here, because the type of `x` will change to 'static
+    if false { ref_obj(x); }
+}
+
+fn test1<'a>(x: &'a Box<Fn()+'a>) {
+    // just_ref will stay the same.
+    just_ref(&**x)
+}
+
+fn test1cc<'a>(x: &'a Box<Fn()+'a>) {
+    // same as test1, but cross-crate
+    lib::just_ref(&**x)
+}
+
+fn test2<'a>(x: &'a Box<Fn()+'a>) {
+    // but ref_obj will not, so warn.
+    ref_obj(x) //~ WARNING this code may fail to compile in Rust 1.3
+}
+
+fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+    // same as test2, but cross crate
+    lib::ref_obj(x) //~ WARNING this code may fail to compile in Rust 1.3
+}
+
+fn test3<'a>(x: &'a Box<Fn()+'static>) {
+    // here, we have a 'static bound, so even when ref_obj changes, no error results
+    ref_obj(x)
+}
+
+fn test3cc<'a>(x: &'a Box<Fn()+'static>) {
+    // same as test3, but cross crate
+    lib::ref_obj(x)
+}
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+}
index 3a9baecb9c60e7b595702c82debaf74a76475466..8e37dd805d56d14fdee1a6f7d8fdee4afcbd1eda 100644 (file)
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
 #![deny(dead_code)]
-#![feature(libc)]
-#![feature(core)]
-
-extern crate libc;
 
 struct Foo {
     x: usize,
     b: bool, //~ ERROR: struct field is never used
-    marker: std::marker::NoCopy
 }
 
 fn field_read(f: Foo) -> usize {
@@ -30,14 +25,15 @@ enum XYZ {
     X, //~ ERROR variant is never used
     Y { //~ ERROR variant is never used
         a: String,
-        b: isize //~ ERROR: struct field is never used
+        b: i32, //~ ERROR: struct field is never used
+        c: i32, //~ ERROR: struct field is never used
     },
     Z
 }
 
 fn field_match_in_patterns(b: XYZ) -> String {
     match b {
-        XYZ::Y { a, .. } => a,
+        XYZ::Y { a, b: _, .. } => a,
         _ => "".to_string()
     }
 }
@@ -45,22 +41,23 @@ fn field_match_in_patterns(b: XYZ) -> String {
 struct Bar {
     x: usize, //~ ERROR: struct field is never used
     b: bool,
+    c: bool, //~ ERROR: struct field is never used
     _guard: ()
 }
 
 #[repr(C)]
 struct Baz {
-    x: libc::c_uint
+    x: u32,
 }
 
 fn field_match_in_let(f: Bar) -> bool {
-    let Bar { b, .. } = f;
+    let Bar { b, c: _, .. } = f;
     b
 }
 
 fn main() {
-    field_read(Foo { x: 1, b: false, marker: std::marker::NoCopy });
+    field_read(Foo { x: 1, b: false });
     field_match_in_patterns(XYZ::Z);
-    field_match_in_let(Bar { x: 42, b: true, _guard: () });
+    field_match_in_let(Bar { x: 42, b: true, c: false, _guard: () });
     let _ = Baz { x: 0 };
 }
diff --git a/src/test/compile-fail/lint-dead-code-variant.rs b/src/test/compile-fail/lint-dead-code-variant.rs
new file mode 100644 (file)
index 0000000..0116d63
--- /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.
+
+#![deny(dead_code)]
+
+#[derive(Clone)]
+enum Enum {
+    Variant1, //~ ERROR: variant is never used
+    Variant2,
+}
+
+fn main() {
+    let e = Enum::Variant2;
+    e.clone();
+}
index 1f70828e411ef1cfc472b6ed1884690939457c71..5867bc2f09deb273967b0c986178d108acfb0bf2 100644 (file)
@@ -12,7 +12,7 @@
 #![deny(exceeding_bitshifts)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
-#![feature(core, negate_unsigned)]
+#![feature(num_bits_bytes, negate_unsigned)]
 
 fn main() {
       let n = 1u8 << 7;
index 04db6c8c8f39c97798136e1af46f2f2136b79143..c98d7083743b8179e7b7cd7f980fee46466ba72e 100644 (file)
@@ -12,6 +12,7 @@
 // injected intrinsics by the compiler.
 #![deny(missing_docs)]
 #![allow(dead_code)]
+#![feature(associated_type_defaults)]
 
 //! Some garbage docs for the crate here
 #![doc="More garbage"]
index ed6a0bd37eb284d689b451a32d0f186c6f514d53..eb5b77f7a45a352a3d7fa6a0287e26e7ff188cf0 100644 (file)
@@ -52,6 +52,8 @@ fn main() {
     let x = 9223372036854775808_i64; //~ error: literal out of range for i64
     let x = -9223372036854775808_i64; // should be OK
     let x = 18446744073709551615_i64; //~ error: literal out of range for i64
+    let x: i64 = -9223372036854775809; //~ error: literal out of range for i64
+    let x = -9223372036854775809_i64; //~ error: literal out of range for i64
 
     let x = -3.40282348e+38_f32; //~ error: literal out of range for f32
     let x =  3.40282348e+38_f32; //~ error: literal out of range for f32
diff --git a/src/test/compile-fail/macro-followed-by-seq-bad.rs b/src/test/compile-fail/macro-followed-by-seq-bad.rs
new file mode 100644 (file)
index 0000000..0ee2221
--- /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.
+
+// Regression test for issue #25436: check that things which can be
+// followed by any token also permit X* to come afterwards.
+
+macro_rules! foo {
+  ( $a:expr $($b:tt)* ) => { }; //~ ERROR not allowed for `expr` fragments
+  ( $a:ty $($b:tt)* ) => { };   //~ ERROR not allowed for `ty` fragments
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/macro-seq-followed-by-seq.rs b/src/test/compile-fail/macro-seq-followed-by-seq.rs
new file mode 100644 (file)
index 0000000..b4f7134
--- /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.
+
+// Check that we cannot have two sequence repetitions in a row.
+
+macro_rules! foo {
+  ( $($a:expr)* $($b:tt)* ) => { }; //~ ERROR sequence repetition followed by another sequence
+  ( $($a:tt)* $($b:tt)* ) => { }; //~ ERROR sequence repetition followed by another sequence
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/match-ill-type1.rs b/src/test/compile-fail/match-ill-type1.rs
deleted file mode 100644 (file)
index c60ef2e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    match 1 {
-        1...2_usize => 1, //~ ERROR mismatched types in range
-        _ => 2,
-    };
-}
index c3292adfa34139cfab55adc0c204c288f7ef2d07..234b74f76d1e05eb39916d06434236140aca929e 100644 (file)
@@ -8,22 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//error-pattern: lower range bound
-//error-pattern: only char and numeric types
-//error-pattern: mismatched types
-
 fn main() {
     match 5 {
-      6 ... 1 => { }
-      _ => { }
+        6 ... 1 => { }
+        _ => { }
+    };
+    //~^^^ ERROR lower range bound must be less than or equal to upper
+
+    match "wow" {
+        "bar" ... "foo" => { }
     };
+    //~^^ ERROR only char and numeric types are allowed in range
+    //~| start type: &'static str
+    //~| end type: &'static str
 
     match "wow" {
-      "bar" ... "foo" => { }
+        10 ... "what" => ()
     };
+    //~^^ ERROR only char and numeric types are allowed in range
+    //~| start type: _
+    //~| end type: &'static str
 
     match 5 {
-      'c' ... 100 => { }
-      _ => { }
+        'c' ... 100 => { }
+        _ => { }
     };
+    //~^^^ ERROR mismatched types in range
+    //~| expected char
+    //~| found integral variable
 }
index 04b234d8db7f1fa2ed2eedf6e130c1d067e8beb1..afc858c0c299e5a588ff61ef7e1e830258bb9261 100644 (file)
@@ -22,7 +22,7 @@ fn f() {
         //~^ ERROR constant in pattern `a` should have an upper case name such as `A`
         (x, y) => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
 }
 
 mod m {
@@ -37,7 +37,7 @@ fn g() {
         //~^ ERROR constant in pattern `aha` should have an upper case name such as `AHA`
         (x, y)   => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
 }
 
 mod n {
@@ -51,7 +51,7 @@ fn h() {
 //~^ ERROR constant in pattern `not_okay` should have an upper case name such as `NOT_OKAY`
         (x, y)   => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
 }
 
 fn main () {
diff --git a/src/test/compile-fail/method-help-unsatisfied-bound.rs b/src/test/compile-fail/method-help-unsatisfied-bound.rs
new file mode 100644 (file)
index 0000000..375d507
--- /dev/null
@@ -0,0 +1,18 @@
+// 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;
+
+fn main() {
+    let a: Result<(), Foo> = Ok(());
+    a.unwrap();
+    //~^ ERROR no method named `unwrap` found for type `core::result::Result<(), Foo>`
+    //~| NOTE the following trait bounds were not satisfied: `Foo : core::fmt::Debug`
+}
index f8ea5dda183366df38ecfa9544f08d21d4406a97..3b794da10536e078c8dd6d8b204196205a0500ee 100644 (file)
@@ -13,5 +13,5 @@
 mod mod_file_aux;
 
 fn main() {
-    assert!(mod_file_aux::bar() == 10); //~ ERROR unresolved name
+    assert_eq!(mod_file_aux::bar(), 10); //~ ERROR unresolved name
 }
diff --git a/src/test/compile-fail/move-closure-span.rs b/src/test/compile-fail/move-closure-span.rs
new file mode 100644 (file)
index 0000000..3c590e8
--- /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.
+
+// Make sure that the span of a closure marked `move` begins at the `move` keyword.
+
+fn main() {
+    let x: () =
+    move //~ ERROR mismatched types
+    || ();
+}
diff --git a/src/test/compile-fail/nonbool_static_assert.rs b/src/test/compile-fail/nonbool_static_assert.rs
deleted file mode 100644 (file)
index 7a7912b..0000000
+++ /dev/null
@@ -1,17 +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.
-
-#![feature(static_assert)]
-#![allow(dead_code)]
-
-#[static_assert]
-static E: i32 = 1; //~ ERROR can only have static_assert on a static with type `bool`
-
-fn main() {}
index 1b323edd589e1d5c368f09ab8413928a66542856..5331062d9b68d84d487145c37920b7c10c037d8f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: is not UTF-8
+// error-pattern: did not contain valid UTF-8
 
 fn foo() {
     include!("not-utf8.bin")
index 23ddea4499a728c51b1fa08bb416cb6a0de71b2c..b5c4e0c767b003fd06b05032ec3f0f270a1984db 100644 (file)
@@ -39,5 +39,9 @@ fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
       //~| ERROR mismatched types
 }
 
+fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+    load0(ss) //~ WARNING E0398
+}
+
 fn main() {
 }
index ac03c085b7b6cc6c3d03bbe8f742daa7677f58a2..104e10f3207dbd24de32e26d540a778dd2d55912 100644 (file)
 #![feature(rustc_attrs)]
 
 #[rustc_object_lifetime_default]
-struct A<T>(T); //~ ERROR None
+struct A<T>(T); //~ ERROR BaseDefault
 
 #[rustc_object_lifetime_default]
-struct B<'a,T>(&'a (), T); //~ ERROR None
+struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
 
 #[rustc_object_lifetime_default]
 struct C<'a,T:'a>(&'a T); //~ ERROR 'a
index fb4491a63757b4e27b93f6d24db04fd3dfc113db..067c17668c612c024c149d2cbd8a20908f254445 100644 (file)
@@ -14,6 +14,6 @@ use cci_class::kitties::cat;
 
 fn main() {
   let nyan : cat = cat(52, 99);
-  assert!((nyan.meows == 52));
+  assert_eq!(nyan.meows, 52);
   //~^ ERROR field `meows` of struct `cci_class::kitties::cat` is private
 }
index b98719e157ea62e76a0788f1cc09e84b3844085b..1423117dc816ad366f79ca85ed028cf83640f908 100644 (file)
@@ -20,5 +20,5 @@ mod cat {
 
 fn main() {
     let nyan = cat::new_cat();
-    assert!(nyan.meows == 52);    //~ ERROR field `meows` of struct `cat::Cat` is private
+    assert_eq!(nyan.meows, 52);    //~ ERROR field `meows` of struct `cat::Cat` is private
 }
diff --git a/src/test/compile-fail/pub-struct-field-span-26083.rs b/src/test/compile-fail/pub-struct-field-span-26083.rs
new file mode 100644 (file)
index 0000000..0dc7e09
--- /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.
+
+// Regression test for issue #26083
+// Test that span for public struct fields start at `pub` instead of the identifier
+
+struct Foo {
+    pub bar: u8,
+
+    pub
+    //~^ error: field `bar` is already declared [E0124]
+    bar: u8,
+
+    pub bar:
+    //~^ error: field `bar` is already declared [E0124]
+    u8,
+
+    bar:
+    //~^ error: field `bar` is already declared [E0124]
+    u8,
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/redundant-link-args.rs b/src/test/compile-fail/redundant-link-args.rs
deleted file mode 100644 (file)
index e7cf7c9..0000000
+++ /dev/null
@@ -1,29 +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.
-
-// ignore-test
-
-// error-pattern:library 'm' already added: can't specify link_args.
-
-/* I think it should undefined to have multiple modules that link in the same
-  library, but provide different link arguments. Unfortunately we don't track
-  link_args by module -- they are just appended as discovered into the crate
-  store -- but for now, it should be an error to provide link_args on a module
-  that's already been included (with or without link_args). */
-
-#[link_name= "m"]
-#[link_args="-foo"]             // this could have been elided.
-extern {
-}
-
-#[link_name= "m"]
-#[link_args="-bar"]             // this is the actual error trigger.
-extern {
-}
index 9e4c4e677cc695b1524561b77e7ae0e754caca0f..19c50d57e1b39565386fe8d2f3410830aacd25ca 100644 (file)
@@ -54,7 +54,7 @@ fn box_with_region_not_ok<'a>() {
     assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
 }
 
-// unsafe pointers are ok unless they point at unsendable things
+// raw pointers are ok unless they point at unsendable things
 
 fn unsafe_ok1<'a>(_: &'a isize) {
     assert_send::<*const isize>();
diff --git a/src/test/compile-fail/static-assert.rs b/src/test/compile-fail/static-assert.rs
deleted file mode 100644 (file)
index d0cfbfb..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.
-
-#![feature(static_assert)]
-#![allow(dead_code)]
-
-#[static_assert]
-static A: bool = false; //~ ERROR static assertion failed
-
-fn main() {
-}
diff --git a/src/test/compile-fail/static-assert2.rs b/src/test/compile-fail/static-assert2.rs
deleted file mode 100644 (file)
index 35f840d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(static_assert)]
-#![allow(dead_code)]
-
-#[static_assert]
-static E: bool = 1 == 2; //~ ERROR static assertion failed
-
-fn main() {}
index 08148328edcf30d7fe87ff7bccf5ee0a7b55afc6..e3bb01e6970786fa1bf94be2ce1502eedf4ec95a 100644 (file)
@@ -12,6 +12,6 @@
 
 static mut a: Box<isize> = box 3;
 //~^ ERROR allocations are not allowed in statics
-//~^^ ERROR mutable statics are not allowed to have owned pointers
+//~^^ ERROR mutable statics are not allowed to have boxes
 
 fn main() {}
index 7a957564587f9b7a7ea84d3a8532da718eb99a2e..a533a5bd54dccdd3d5d5b3b17463a458a41ee521 100644 (file)
@@ -11,6 +11,6 @@
 fn foo() -> isize { 23 }
 
 static a: [isize; 2] = [foo(); 2];
-//~^ ERROR: function calls in statics are limited to struct and enum constructors
+//~^ ERROR: E0015
 
 fn main() {}
index 9807fc43140d9a8426256f5e315116de7a8d855b..35877db610e34e70607b613ab73968120ff153ab 100644 (file)
@@ -15,11 +15,11 @@ use std::sync::atomic::*;
 use std::ptr;
 
 fn main() {
-    let x = ATOMIC_BOOL_INIT;
+    let x = AtomicBool::new(false);
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_ISIZE_INIT;
+    let x = AtomicIsize::new(0);
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_USIZE_INIT;
+    let x = AtomicUsize::new(0);
     let x = *&x; //~ ERROR: cannot move out of borrowed content
     let x: AtomicPtr<usize> = AtomicPtr::new(ptr::null_mut());
     let x = *&x; //~ ERROR: cannot move out of borrowed content
diff --git a/src/test/compile-fail/struct-field-assignability.rs b/src/test/compile-fail/struct-field-assignability.rs
deleted file mode 100644 (file)
index 685ce28..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// ignore-test
-
-// 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<'a> {
-    x: &'a isize
-}
-
-pub fn main() {
-    let f = Foo { x: &*(box 3) }; //~ ERROR borrowed value does not live long enough
-    assert_eq!(*f.x, 3);
-}
index d1e50638138c40fc5df877766079165dc75bcc6a..506aed6b2ee1db80740ae59788d486294f231be9 100644 (file)
@@ -17,6 +17,5 @@ pub fn main() {
     assert_eq!(concat_idents!(asd, f_f, dsa), "<.<".to_string());
     //~^ ERROR: unresolved name `asdf_fdsa`
 
-    assert!(stringify!(use_mention_distinction) ==
-                "use_mention_distinction");
+    assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
 }
index a33cd0edca5b480c6b7f7d00c71f1c437a864d2e..7d6a1c9c1544c296daafa72c8817564ab609226e 100644 (file)
@@ -13,6 +13,6 @@
 trait MyDefaultImpl {}
 
 impl<T> MyDefaultImpl for .. {}
-//~^ ERROR default trait implementations are not allowed to have genercis
+//~^ ERROR default trait implementations are not allowed to have generics
 
 fn main() {}
index 3129dceffbb664c3d2471ba61e3a38b7df2562b1..836f08d0e78bb21d2fe2fcf5786f6f9cca1d7acf 100644 (file)
@@ -22,8 +22,8 @@ fn c(x: Box<Foo+Sync+Send>) {
 
 fn d(x: Box<Foo>) {
     a(x); //~  ERROR mismatched types
-          //~| expected `Box<Foo + Send>`
-          //~| found `Box<Foo>`
+          //~| expected `Box<Foo + Send + 'static>`
+          //~| found `Box<Foo + 'static>`
           //~| expected bounds `Send`
           //~| found no bounds
 }
index c18c5b386e8b21816be1abd6ff4e38818ea86978..988961e7fa14a7d522c4f3c13fa4cce01e00f3fb 100644 (file)
@@ -32,23 +32,27 @@ impl<T> Foo<T> {
 }
 
 struct Baz {
-//~^ ERROR not implemented
-    a: Foo<isize>,
+    a: Foo<isize>, //~ ERROR not implemented
 }
 
 enum Boo {
-//~^ ERROR not implemented
-    Quux(Bar<usize>),
+    Quux(Bar<usize>), //~ ERROR not implemented
 }
 
 struct Badness<U> {
-//~^ ERROR not implemented
-    b: Foo<U>,
+    b: Foo<U>, //~ ERROR not implemented
 }
 
 enum MoreBadness<V> {
-//~^ ERROR not implemented
-    EvenMoreBadness(Bar<V>),
+    EvenMoreBadness(Bar<V>), //~ ERROR not implemented
+}
+
+struct TupleLike(
+    Foo<i32>, //~ ERROR not implemented
+);
+
+enum Enum {
+    DictionaryLike { field: Bar<u8> }, //~ ERROR not implemented
 }
 
 trait PolyTrait<T>
@@ -58,7 +62,7 @@ trait PolyTrait<T>
 
 struct Struct;
 
-impl PolyTrait<Foo<usize>> for Struct {
+impl PolyTrait<Foo<u16>> for Struct {
 //~^ ERROR not implemented
 }
 
index 3aec23a55b8118e9f4766c28ed7c5d2c9e02e5d5..b1e4d06affe7d1c0d3aa14a220a80cae58b12048 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 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.
 //
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 impl<T> Option<T> {
-//~^ ERROR cannot associate methods with a type outside the crate the type is defined in
+//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined
     pub fn foo(&self) { }
 }
 
index 3ef760053c709fc8b9115b0981b59ea15d4c3ee4..8dc977a8e490bf3aa213e447e39046e2e2e681c5 100644 (file)
@@ -19,9 +19,6 @@ use std::marker::Send;
 
 struct Outer<T: Send>(T);
 
-struct TestType;
-impl !Send for TestType {}
-
 struct Outer2<T>(T);
 
 unsafe impl<T: Send> Sync for Outer2<T> {}
@@ -30,29 +27,41 @@ fn is_send<T: Send>(_: T) {}
 fn is_sync<T: Sync>(_: T) {}
 
 fn dummy() {
+    struct TestType;
+    impl !Send for TestType {}
+
     Outer(TestType);
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `dummy::TestType`
 
     is_send(TestType);
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `dummy::TestType`
 
     is_send((8, TestType));
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `dummy::TestType`
 }
 
 fn dummy2() {
+    struct TestType;
+    impl !Send for TestType {}
+
     is_send(Box::new(TestType));
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `dummy2::TestType`
 }
 
 fn dummy3() {
+    struct TestType;
+    impl !Send for TestType {}
+
     is_send(Box::new(Outer2(TestType)));
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `dummy3::TestType`
 }
 
 fn main() {
+    struct TestType;
+    impl !Send for TestType {}
+
     // This will complain about a missing Send impl because `Sync` is implement *just*
     // for T that are `Send`. Look at #20366 and #19950
     is_sync(Outer2(TestType));
-    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `main::TestType`
 }
index 285a5dbee053dc8aa7ab8120627cfeedce248f82..e10a76c65bcf1f0efa00bc8c54c2772625c4d096 100644 (file)
@@ -11,5 +11,5 @@
 fn main() {
     let x : i16 = 22;
     ((&x) as *const i16) as f32;
-    //~^ ERROR illegal cast; cast through an integer first: `*const i16` as `f32`
+    //~^ ERROR illegal cast; cast through a usize first: `*const i16` as `f32`
 }
index 4f572e87639f051208ba7efa78d14a961e8e35ab..8057ca56621c12930278034aee6bc98b119f3821 100644 (file)
@@ -40,6 +40,6 @@ fn test() {
 }
 
 fn main() {
-    foo::<i32>();
-    //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
+    foo::<u32>();
+    //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<u32>`
 }
diff --git a/src/test/compile-fail/typo-suggestion.rs b/src/test/compile-fail/typo-suggestion.rs
new file mode 100644 (file)
index 0000000..d5cf6a2
--- /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.
+
+fn main() {
+    let foo = 1;
+
+    // `foo` shouldn't be suggested, it is too dissimilar from `bar`.
+    println!("Hello {}", bar);
+    //~^ ERROR: unresolved name `bar`
+
+    // But this is close enough.
+    println!("Hello {}", fob);
+    //~^ ERROR: unresolved name `fob`. Did you mean `foo`?
+}
index b3fe178dc455e83b0d8c40f7092b57cbee1090fd..2e8f9d42e789547cba427470d8a9fcf6bfd79140 100644 (file)
@@ -12,5 +12,5 @@ use std::borrow::IntoCow;
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR too few type parameters provided: expected 1 parameter(s)
+    //~^ ERROR too few type parameters provided: expected 1 parameter
 }
index 1e36c47c0973b443b5104abcf31245495554a81f..3f88f16d2c3ad5e9b9975e6288bec4215db14108 100644 (file)
@@ -18,7 +18,6 @@ struct Bar<A> {
 fn bar() {
     let x: Box<Bar()> = panic!();
     //~^ ERROR parenthesized parameters may only be used with a trait
-    //~^^ ERROR associated type bindings are not allowed here
 }
 
 fn main() { }
index f50d91a4ddd9faf571eed087af1e867f1d394942..fd6c8ad08d65eb6258e50b57ad05defcce9886d8 100644 (file)
@@ -16,7 +16,6 @@ struct Bar<A> {
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized parameters may only be used with a trait
-    //~^^ ERROR associated type bindings are not allowed here
 }
 
 fn main() { }
index 4ea7051775e132edf7e53eae6d1081adcfda8a40..cff10329b858970d2ddd03da32ef21788319921f 100644 (file)
@@ -10,7 +10,7 @@
 
 
 fn f(p: *const u8) {
-    *p = 0; //~ ERROR dereference of unsafe pointer requires unsafe function or block
+    *p = 0; //~ ERROR dereference of raw pointer requires unsafe function or block
     return;
 }
 
index bdf079e24d2a1e40af13796ba5ad172038152a7c..bf87df71fd87dc77163aebfe05b48caec1ef56c1 100644 (file)
@@ -10,7 +10,7 @@
 
 
 fn f(p: *const u8) -> u8 {
-    return *p; //~ ERROR dereference of unsafe pointer requires unsafe function or block
+    return *p; //~ ERROR dereference of raw pointer requires unsafe function or block
 }
 
 fn main() {
index dc10f795cd4229df96e75cb1f5c6fb69c8f1bc31..afa574bf85a8d950f5c2d77f61b336c270e304a7 100644 (file)
@@ -24,7 +24,7 @@ struct S3 {
     g: [usize]
 }
 struct S4 {
-    f: str, //~ ERROR `core::marker::Sized` is not implemented
+    f: [u8], //~ ERROR `core::marker::Sized` is not implemented
     g: usize
 }
 enum E<X: ?Sized> {
diff --git a/src/test/compile-fail/use-paths-as-items.rs b/src/test/compile-fail/use-paths-as-items.rs
new file mode 100644 (file)
index 0000000..8a10eef
--- /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.
+
+// Each path node in a `use` declaration must be treated as an item. If not, the following code
+// will trigger an ICE.
+//
+// Related issue: #25763
+
+use std::{mem, ptr};
+use std::mem; //~ ERROR has already been imported
+
+fn main() {}
index c30aa7b817bf4fcfce1f7d262a6f7cd21db0dcf0..375289596841d5ae59474d5a80034f71ac5926e3 100644 (file)
 // conditions above to be satisfied, meaning that if the dropck is
 // sound, it should reject this code.
 
+#![feature(const_fn)]
+
 use std::cell::Cell;
 use id::Id;
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, Ordering};
 
-    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
 
     /// generates globally unique count (global across the current
     /// process, that is)
index cac52306d6ae0e1a4d08dfd13763c4552f6099a7..10227f1820d96b0c04a71732dc69f0b090dd93ff 100644 (file)
@@ -28,7 +28,7 @@ fn main() {
     let mut x1 = X { y: [0, 0] };
 
     // This is still an error since we don't allow casts from &mut [T; n] to *mut T.
-    let p1: *mut u8 = &mut x1.y as *mut _;  //~ ERROR mismatched types
+    let p1: *mut u8 = &mut x1.y as *mut _;  //~ ERROR illegal cast
     let t1: *mut [u8; 2] = &mut x1.y as *mut _;
     let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
 }
index 5fc580755043d426185fd02a7b656132184e325b..ec5a6fa3d3f16e0dc0e6e9d04ac84e14faa5fb0f 100644 (file)
 
 #![allow(dead_code, unused_variables)]
 #![omit_gdb_pretty_printer_section]
-#![feature(std_misc, core)]
+#![feature(const_fn)]
+#![feature(static_mutex)]
 
 // This test makes sure that the compiler doesn't crash when trying to assign
 // debug locations to const-expressions.
 
-use std::sync::MUTEX_INIT;
+use std::sync::StaticMutex;
 use std::cell::UnsafeCell;
 
 const CONSTANT: u64 = 3 + 4;
@@ -49,7 +50,7 @@ const VEC: [u32; 8] = [0; 8];
 
 const NESTED: (Struct, TupleStruct) = (STRUCT, TUPLE_STRUCT);
 
-const UNSAFE_CELL: UnsafeCell<bool> = UnsafeCell { value: false };
+const UNSAFE_CELL: UnsafeCell<bool> = UnsafeCell::new(false);
 
 fn main() {
     let mut _constant = CONSTANT;
@@ -61,6 +62,6 @@ fn main() {
     let mut _string = STRING;
     let mut _vec = VEC;
     let mut _nested = NESTED;
-    let mut _extern = MUTEX_INIT;
+    let mut _extern = StaticMutex::new();
     let mut _unsafe_cell = UNSAFE_CELL;
 }
diff --git a/src/test/debuginfo/gdb-pretty-std.rs b/src/test/debuginfo/gdb-pretty-std.rs
deleted file mode 100644 (file)
index c42f7f1..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-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-windows failing on win32 bot
-// ignore-freebsd: gdb package too new
-// ignore-lldb
-// ignore-android: FIXME(#10381)
-// compile-flags:-g
-// min-gdb-version 7.7
-
-// gdb-command: run
-
-// gdb-command: print slice
-// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3}
-
-// gdb-command: print vec
-// gdb-check:$2 = Vec<u64>(len: 4, cap: [...]) = {4, 5, 6, 7}
-
-// gdb-command: print str_slice
-// gdb-check:$3 = "IAMA string slice!"
-
-// gdb-command: print string
-// gdb-check:$4 = "IAMA string!"
-
-// gdb-command: print some
-// gdb-check:$5 = Some = {8}
-
-// gdb-command: print none
-// gdb-check:$6 = None
-
-#![allow(unused_variables)]
-
-fn main() {
-
-    // &[]
-    let slice: &[i32] = &[0, 1, 2, 3];
-
-    // Vec
-    let vec = vec![4u64, 5, 6, 7];
-
-    // &str
-    let str_slice = "IAMA string slice!";
-
-    // String
-    let string = "IAMA string!".to_string();
-
-    // Option
-    let some = Some(8i16);
-    let none: Option<i64> = None;
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
deleted file mode 100644 (file)
index 56a973f..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-windows failing on win32 bot
-// ignore-freebsd: output doesn't match
-// ignore-tidy-linelength
-// ignore-lldb
-// ignore-android: FIXME(#10381)
-// compile-flags:-g
-
-// This test uses some GDB Python API features (e.g. accessing anonymous fields)
-// which are only available in newer GDB version. The following directive will
-// case the test runner to ignore this test if an older GDB version is used:
-// min-gdb-version 7.7
-
-// gdb-command: run
-
-// gdb-command: print regular_struct
-// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false, the_fourth_field = "I'm so pretty, oh so pretty..."}
-
-// gdb-command: print tuple
-// gdb-check:$2 = {true, 103, "blub"}
-
-// gdb-command: print tuple_struct
-// gdb-check:$3 = TupleStruct = {-104.5, 105}
-
-// gdb-command: print empty_struct
-// gdb-check:$4 = EmptyStruct
-
-// gdb-command: print c_style_enum1
-// gdb-check:$5 = CStyleEnumVar1
-
-// gdb-command: print c_style_enum2
-// gdb-check:$6 = CStyleEnumVar2
-
-// gdb-command: print c_style_enum3
-// gdb-check:$7 = CStyleEnumVar3
-
-// gdb-command: print mixed_enum_c_style_var
-// gdb-check:$8 = MixedEnumCStyleVar
-
-// gdb-command: print mixed_enum_tuple_var
-// gdb-check:$9 = MixedEnumTupleVar = {106, 107, false}
-
-// gdb-command: print mixed_enum_struct_var
-// gdb-check:$10 = MixedEnumStructVar = {field1 = 108.5, field2 = 109}
-
-// gdb-command: print some
-// gdb-check:$11 = Some = {110}
-
-// gdb-command: print none
-// gdb-check:$12 = None
-
-// gdb-command: print some_fat
-// gdb-check:$13 = Some = {"abc"}
-
-// gdb-command: print none_fat
-// gdb-check:$14 = None
-
-// gdb-command: print nested_variant1
-// gdb-check:$15 = NestedVariant1 = {NestedStruct = {regular_struct = RegularStruct = {the_first_field = 111, the_second_field = 112.5, the_third_field = true, the_fourth_field = "NestedStructString1"}, tuple_struct = TupleStruct = {113.5, 114}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar2, mixed_enum = MixedEnumTupleVar = {115, 116, false}}}
-
-// gdb-command: print nested_variant2
-// gdb-check:$16 = NestedVariant2 = {abc = NestedStruct = {regular_struct = RegularStruct = {the_first_field = 117, the_second_field = 118.5, the_third_field = false, the_fourth_field = "NestedStructString10"}, tuple_struct = TupleStruct = {119.5, 120}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar3, mixed_enum = MixedEnumStructVar = {field1 = 121.5, field2 = -122}}}
-
-// gdb-command: print none_check1
-// gdb-check:$17 = None
-
-// gdb-command: print none_check2
-// gdb-check:$18 = None
-
-#![allow(dead_code, unused_variables)]
-
-use self::CStyleEnum::{CStyleEnumVar1, CStyleEnumVar2, CStyleEnumVar3};
-use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar};
-use self::NestedEnum::{NestedVariant1, NestedVariant2};
-
-struct RegularStruct {
-    the_first_field: isize,
-    the_second_field: f64,
-    the_third_field: bool,
-    the_fourth_field: &'static str,
-}
-
-struct TupleStruct(f64, i16);
-
-struct EmptyStruct;
-
-enum CStyleEnum {
-    CStyleEnumVar1,
-    CStyleEnumVar2,
-    CStyleEnumVar3,
-}
-
-enum MixedEnum {
-    MixedEnumCStyleVar,
-    MixedEnumTupleVar(u32, u16, bool),
-    MixedEnumStructVar { field1: f64, field2: i32 }
-}
-
-struct NestedStruct {
-    regular_struct: RegularStruct,
-    tuple_struct: TupleStruct,
-    empty_struct: EmptyStruct,
-    c_style_enum: CStyleEnum,
-    mixed_enum: MixedEnum,
-}
-
-enum NestedEnum {
-    NestedVariant1(NestedStruct),
-    NestedVariant2 { abc: NestedStruct }
-}
-
-fn main() {
-
-    let regular_struct = RegularStruct {
-        the_first_field: 101,
-        the_second_field: 102.5,
-        the_third_field: false,
-        the_fourth_field: "I'm so pretty, oh so pretty..."
-    };
-
-    let tuple = ( true, 103u32, "blub" );
-
-    let tuple_struct = TupleStruct(-104.5, 105);
-
-    let empty_struct = EmptyStruct;
-
-    let c_style_enum1 = CStyleEnumVar1;
-    let c_style_enum2 = CStyleEnumVar2;
-    let c_style_enum3 = CStyleEnumVar3;
-
-    let mixed_enum_c_style_var = MixedEnumCStyleVar;
-    let mixed_enum_tuple_var = MixedEnumTupleVar(106, 107, false);
-    let mixed_enum_struct_var = MixedEnumStructVar { field1: 108.5, field2: 109 };
-
-    let some = Some(110_usize);
-    let none: Option<isize> = None;
-    let some_fat = Some("abc");
-    let none_fat: Option<&'static str> = None;
-
-    let nested_variant1 = NestedVariant1(
-        NestedStruct {
-            regular_struct: RegularStruct {
-                the_first_field: 111,
-                the_second_field: 112.5,
-                the_third_field: true,
-                the_fourth_field: "NestedStructString1",
-            },
-            tuple_struct: TupleStruct(113.5, 114),
-            empty_struct: EmptyStruct,
-            c_style_enum: CStyleEnumVar2,
-            mixed_enum: MixedEnumTupleVar(115, 116, false)
-        }
-    );
-
-    let nested_variant2 = NestedVariant2 {
-        abc: NestedStruct {
-            regular_struct: RegularStruct {
-                the_first_field: 117,
-                the_second_field: 118.5,
-                the_third_field: false,
-                the_fourth_field: "NestedStructString10",
-            },
-            tuple_struct: TupleStruct(119.5, 120),
-            empty_struct: EmptyStruct,
-            c_style_enum: CStyleEnumVar3,
-            mixed_enum: MixedEnumStructVar {
-                field1: 121.5,
-                field2: -122
-            }
-        }
-    };
-
-    let none_check1: Option<(usize, Vec<usize>)> = None;
-    let none_check2: Option<String> = None;
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/generic-trait-generic-static-default-method.rs b/src/test/debuginfo/generic-trait-generic-static-default-method.rs
deleted file mode 100644 (file)
index 45da87a..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// ignore-test
-
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-g
-// gdb-command:run
-
-// gdb-command:print arg1
-// gdb-check:$1 = 1000
-// gdb-command:print *arg2
-// gdb-check:$2 = {1, 2.5}
-// gdb-command:continue
-
-// gdb-command:print arg1
-// gdb-check:$3 = 2000
-// gdb-command:print *arg2
-// gdb-check:$4 = {3.5, {4, 5, 6}}
-// gdb-command:continue
-
-#![omit_gdb_pretty_printer_section]
-
-struct Struct {
-    x: isize
-}
-
-trait Trait<T1> {
-    fn generic_static_default_method<T2>(arg1: isize, arg2: &(T1, T2)) -> isize {
-        zzz(); // #break
-        arg1
-    }
-}
-
-impl<T> Trait<T> for Struct {}
-
-fn main() {
-
-    // Is this really how to use these?
-    Trait::generic_static_default_method::<isize, Struct, float>(1000, &(1, 2.5));
-    Trait::generic_static_default_method::<float, Struct, (isize, isize, isize)>(2000,
-            &(3.5, (4, 5, 6)));
-
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/issue11600.rs b/src/test/debuginfo/issue11600.rs
deleted file mode 100644 (file)
index dea2a0c..0000000
+++ /dev/null
@@ -1,30 +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.
-
-// This test was actually never run before because commands were only parsed up to the first
-// function definition but the test relied on the function being above the commands. Ignore for now.
-// ignore-test
-
-fn main() {
-    let args : Vec<String> = ::std::os::args();
-    ::std::io::println(args[0]);
-}
-
-// ignore-lldb
-
-// This test case checks whether compile unit names are set correctly, so that the correct default
-// source file can be found.
-
-// compile-flags:-g
-// gdb-command:list
-// gdb-check:1[...]fn main() {
-// gdb-check:2[...]let args : Vec<String> = ::std::os::args();
-// gdb-check:3[...]::std::io::println(args[0]);
-// gdb-check:4[...]}
index 65a83088d805102cdc156f37a9a80dd4b9465905..fba21d9a553ba80d7c341ac83170f7e274fd1a29 100644 (file)
@@ -67,7 +67,7 @@
 // lldb-check:[...]$5 = Void
 
 // lldb-command:print some_str
-// lldb-check:[...]$6 = Some(&str { data_ptr: [...], length: 3 })
+// lldb-check:[...]$6 = Some("abc")
 
 // lldb-command:print none_str
 // lldb-check:[...]$7 = None
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
new file mode 100644 (file)
index 0000000..5766217
--- /dev/null
@@ -0,0 +1,87 @@
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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-windows failing on win32 bot
+// ignore-freebsd: gdb package too new
+// ignore-android: FIXME(#10381)
+// compile-flags:-g
+// min-gdb-version 7.7
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print slice
+// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3}
+
+// gdb-command: print vec
+// gdb-check:$2 = Vec<u64>(len: 4, cap: [...]) = {4, 5, 6, 7}
+
+// gdb-command: print str_slice
+// gdb-check:$3 = "IAMA string slice!"
+
+// gdb-command: print string
+// gdb-check:$4 = "IAMA string!"
+
+// gdb-command: print some
+// gdb-check:$5 = Some = {8}
+
+// gdb-command: print none
+// gdb-check:$6 = None
+
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command: run
+
+// lldb-command: print slice
+// lldb-check:[...]$0 = &[0, 1, 2, 3]
+
+// lldb-command: print vec
+// lldb-check:[...]$1 = vec![4, 5, 6, 7]
+
+// lldb-command: print str_slice
+// lldb-check:[...]$2 = "IAMA string slice!"
+
+// lldb-command: print string
+// lldb-check:[...]$3 = "IAMA string!"
+
+// lldb-command: print some
+// lldb-check:[...]$4 = Some(8)
+
+// lldb-command: print none
+// lldb-check:[...]$5 = None
+
+
+#![allow(unused_variables)]
+
+fn main() {
+
+    // &[]
+    let slice: &[i32] = &[0, 1, 2, 3];
+
+    // Vec
+    let vec = vec![4u64, 5, 6, 7];
+
+    // &str
+    let str_slice = "IAMA string slice!";
+
+    // String
+    let string = "IAMA string!".to_string();
+
+    // Option
+    let some = Some(8i16);
+    let none: Option<i64> = None;
+
+    zzz(); // #break
+}
+
+fn zzz() { () }
index 7b337ba2cc8a659cce9f38818eb8a953781f219a..6bc8892a83a6939cc497505522f720a978106f3b 100644 (file)
@@ -42,7 +42,7 @@
 
 #![allow(unused_variables)]
 #![omit_gdb_pretty_printer_section]
-#![feature(core)]
+#![feature(core_simd)]
 
 use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
 
diff --git a/src/test/debuginfo/trait-generic-static-default-method.rs b/src/test/debuginfo/trait-generic-static-default-method.rs
deleted file mode 100644 (file)
index d066af5..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// ignore-test
-
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:print arg1
-// gdb-check:$1 = 1000
-// gdb-command:print arg2
-// gdb-check:$2 = 0.5
-// gdb-command:continue
-
-// gdb-command:print arg1
-// gdb-check:$3 = 2000
-// gdb-command:print *arg2
-// gdb-check:$4 = {1, 2, 3}
-// gdb-command:continue
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print arg1
-// lldb-check:[...]$0 = 1000
-// lldb-command:print arg2
-// lldb-check:[...]$1 = 0.5
-// lldb-command:continue
-
-// lldb-command:print arg1
-// lldb-check:[...]$2 = 2000
-// lldb-command:print *arg2
-// lldb-check:[...]$3 = (1, 2, 3)
-// lldb-command:continue
-
-#![omit_gdb_pretty_printer_section]
-
-struct Struct {
-    x: isize
-}
-
-trait Trait {
-    fn generic_static_default_method<T>(arg1: isize, arg2: T) -> isize {
-        zzz(); // #break
-        arg1
-    }
-}
-
-impl Trait for Struct {}
-
-fn main() {
-
-    // Is this really how to use these?
-    Trait::generic_static_default_method::<Struct, float>(1000, 0.5);
-    Trait::generic_static_default_method::<Struct, &(isize, isize, isize)>(2000, &(1, 2, 3));
-
-}
-
-fn zzz() {()}
diff --git a/src/test/parse-fail/extern-crate-unexpected-token.rs b/src/test/parse-fail/extern-crate-unexpected-token.rs
new file mode 100644 (file)
index 0000000..2518686
--- /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.
+
+extern crte foo; //~ ERROR expected one of `crate`, `fn`, or `{`, found `crte`
index 7fb7233dc698269ff6f5adcae23a2010a6316678..21cca129658c526b6c1997a62353a5e6f8124814 100644 (file)
@@ -13,4 +13,4 @@
 // Verifies that the expected token errors for `extern crate` are
 // raised
 
-extern "C" mod foo; //~ERROR expected `{` or `fn`, found `mod`
+extern "C" mod foo; //~ERROR expected one of `fn` or `{`, found `mod`
diff --git a/src/test/parse-fail/issue-14182.rs b/src/test/parse-fail/issue-14182.rs
deleted file mode 100644 (file)
index 176e17c..0000000
+++ /dev/null
@@ -1,29 +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
-
-// ignore-test FIXME(japari) remove test
-
-struct Foo {
-    f: for <'b> |&'b isize|:
-      'b -> &'b isize //~ ERROR use of undeclared lifetime name `'b`
-}
-
-fn main() {
-    let mut x: Vec< for <'a> ||
-       :'a //~ ERROR use of undeclared lifetime name `'a`
-    > = Vec::new();
-    x.push(|| {});
-
-    let foo = Foo {
-        f: |x| x
-    };
-}
index 9975609d8d3f89a5fedc9fa8b1b2036da02a23a9..5931631cceefcb7431bf0699544c4d54c7229f56 100644 (file)
@@ -11,7 +11,7 @@
 // compile-flags: -Z parse-only
 
 fn main() {
-    assert!(1 == 2)
-    assert!(3 == 4) //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `assert`
+    assert_eq!(1, 2)
+    assert_eq!(3, 4) //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `assert_eq`
     println!("hello");
 }
index 2a0ed9dcc243fe97cd1206147b18ca156cef55b3..1cc0e62f5b2d5cfb5d9a2db13809b873c7096872 100644 (file)
 // compile-flags: -Z parse-only
 
 trait A {
-    fn foo(*mut self); //~ ERROR cannot pass self by unsafe pointer
-    fn bar(*self); //~ ERROR cannot pass self by unsafe pointer
+    fn foo(*mut self); //~ ERROR cannot pass self by raw pointer
+    fn bar(*self); //~ ERROR cannot pass self by raw pointer
 }
 
 struct X;
 impl A for X {
-    fn foo(*mut self) { } //~ ERROR cannot pass self by unsafe pointer
-    fn bar(*self) { } //~ ERROR cannot pass self by unsafe pointer
+    fn foo(*mut self) { } //~ ERROR cannot pass self by raw pointer
+    fn bar(*self) { } //~ ERROR cannot pass self by raw pointer
 }
 
 fn main() { }
diff --git a/src/test/parse-fail/regions-fn-bound.rs b/src/test/parse-fail/regions-fn-bound.rs
deleted file mode 100644 (file)
index 8762c13..0000000
+++ /dev/null
@@ -1,50 +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
-
-// ignore-test
-// ignored because the first error does not show up.
-
-// 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
-
-fn of<T>() -> |T| { panic!(); }
-fn subtype<T>(x: |T|) { panic!(); }
-
-fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
-    // Here, x, y, and z are free.  Other letters
-    // are bound.  Note that the arrangement
-    // subtype::<T1>(of::<T2>()) will typecheck
-    // iff T1 <: T2.
-
-    // should be the default:
-    subtype::< ||:'static>(of::<||>());
-    subtype::<||>(of::< ||:'static>());
-
-    //
-    subtype::< <'x> ||>(of::<||>());    //~ ERROR mismatched types
-    subtype::< <'x> ||>(of::< <'y> ||>());  //~ ERROR mismatched types
-
-    subtype::< <'x> ||>(of::< ||:'static>()); //~ ERROR mismatched types
-    subtype::< ||:'static>(of::< <'x> ||>());
-
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/regions-infer-paramd-method.rs b/src/test/parse-fail/regions-infer-paramd-method.rs
deleted file mode 100644 (file)
index b1aebf4..0000000
+++ /dev/null
@@ -1,69 +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.
-
-// ignore-test
-// ignored due to problems with by value self.
-
-// 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
-
-// Here: foo is parameterized because it contains a method that
-// refers to self.
-
-trait foo<'a> {
-    fn self_int(self) -> &'a isize;
-
-    fn any_int(self) -> &isize;
-}
-
-struct with_foo<'a> {
-    f: @foo<'a>
-}
-
-trait set_foo_foo {
-    fn set_foo(&mut self, f: @foo);
-}
-
-impl<'a> set_foo_foo for with_foo<'a> {
-    fn set_foo(&mut self, f: @foo) {
-        self.f = f; //~ ERROR mismatched types: expected `@foo/&self`, found `@foo/&`
-    }
-}
-
-// Bar is not region parameterized.
-
-trait bar {
-    fn any_int(&self) -> &isize;
-}
-
-struct with_bar {
-    f: bar
-}
-
-trait set_foo_bar {
-    fn set_foo(&mut self, f: bar);
-}
-
-impl set_foo_bar for with_bar {
-    fn set_foo(&mut self, f: bar) {
-        self.f = f;
-    }
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/regions-trait-2.rs b/src/test/parse-fail/regions-trait-2.rs
deleted file mode 100644 (file)
index e2e3fcd..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-// ignore-test #5723
-
-// Test that you cannot escape a reference
-// into a trait.
-
-struct ctxt { v: usize }
-
-trait get_ctxt {
-    fn get_ctxt(&self) -> &'a ctxt;
-}
-
-struct has_ctxt<'a> { c: &'a ctxt }
-
-impl<'a> get_ctxt for has_ctxt<'a> {
-    fn get_ctxt(&self) -> &'a ctxt { self.c }
-}
-
-fn make_gc() -> @get_ctxt  {
-    let ctxt = ctxt { v: 22 };
-    let hc = has_ctxt { c: &ctxt };
-    return @hc as @get_ctxt;
-    //~^ ERROR source contains reference
-}
-
-fn main() {
-    make_gc().get_ctxt().v;
-}
diff --git a/src/test/parse-fail/regions-trait-3.rs b/src/test/parse-fail/regions-trait-3.rs
deleted file mode 100644 (file)
index 57b182f..0000000
+++ /dev/null
@@ -1,47 +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.
-
-// ignore-test
-// ignore'd due to problems with by-value self.
-
-// 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.
-
-// compile-flags: -Z parse-only
-
-trait get_ctxt<'a> {
-    fn get_ctxt(self) -> &'a usize;
-}
-
-fn make_gc1(gc: @get_ctxt<'a>) -> @get_ctxt<'b>  {
-    return gc; //~ ERROR mismatched types: expected `@get_ctxt/&b`, found `@get_ctxt/&a`
-}
-
-struct Foo {
-    r: &'a usize
-}
-
-impl get_ctxt for Foo<'a> {
-    fn get_ctxt(&self) -> &'a usize { self.r }
-}
-
-fn make_gc2<'a,'b>(foo: Foo<'a>) -> @get_ctxt<'b>  {
-    return @foo as @get_ctxt; //~ ERROR cannot infer
-}
-
-fn main() {
-}
index a85f85a395c61cf2813ddecdbbaa27beb6d0d37f..c9501e8166f14bf0f413cbec52129b89d8fdf435 100644 (file)
@@ -12,4 +12,4 @@
 
 fn f<F>(f: F) where F: Fn(isize) { f(10) }
 
-fn main() { f(|i| { assert!(i == 10) }) }
+fn main() { f(|i| { assert_eq!(i , 10) }) }
diff --git a/src/test/pretty/record-trailing-comma.rs b/src/test/pretty/record-trailing-comma.rs
deleted file mode 100644 (file)
index dd7fbf3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-// pp-exact
-struct Thing {
-    x: isize,
-    y: isize,
-}
-
-fn main() {
-    let sth = Thing{x: 0, y: 1,};
-    let sth2 = Thing{y: 9 , ..sth};
-    assert_eq!(sth.x + sth2.y, 9);
-}
index 6ae22392b939eff3d10ee811caa08710edb70d96..4251579bbdcd1ba21334bb2de131a762ebc7a3dc 100644 (file)
@@ -22,7 +22,7 @@ use syntax::parse;
 use syntax::print::pprust;
 
 fn main() {
-    let ps = syntax::parse::new_parse_sess();
+    let ps = syntax::parse::ParseSess::new();
     let mut cx = syntax::ext::base::ExtCtxt::new(
         &ps, vec![],
         syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs
deleted file mode 100644 (file)
index 07fac8e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-// error-pattern:index out of bounds
-
-use std::usize;
-
-fn main() {
-    let x = vec!(1_usize,2_usize,3_usize);
-
-    // This should cause a bounds-check panic, but may not if we do our
-    // bounds checking by comparing a scaled index value to the vector's
-    // length (in bytes), because the scaling of the index will cause it to
-    // wrap around to a small number.
-
-    let idx = usize::MAX & !(usize::MAX >> 1_usize);
-    println!("ov2 idx = 0x%x", idx);
-
-    // This should panic.
-    println!("ov2 0x%x",  x[idx]);
-}
diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs
deleted file mode 100644 (file)
index b7aff8d..0000000
+++ /dev/null
@@ -1,40 +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.
-
-// ignore-test
-// error-pattern:index out of bounds
-
-use std::u64;
-
-#[cfg(target_arch="x86")]
-fn main() {
-    let x = vec!(1_usize,2_usize,3_usize);
-
-    // This should cause a bounds-check panic, but may not if we do our
-    // bounds checking by truncating the index value to the size of the
-    // machine word, losing relevant bits of the index value.
-
-    // This test is only meaningful on 32-bit hosts.
-
-    let idx = u64::MAX & !(u64::MAX >> 1_usize);
-    println!("ov3 idx = 0x%8.8x%8.8x",
-           (idx >> 32) as usize,
-           idx as usize);
-
-    // This should panic.
-    println!("ov3 0x%x",  x[idx]);
-}
-
-#[cfg(any(target_arch="x86_64", target_arch = "aarch64"))]
-fn main() {
-    // This version just panics anyways, for symmetry on 64-bit hosts.
-    let x = vec!(1_usize,2_usize,3_usize);
-    error!("ov3 0x%x",  x[200]);
-}
diff --git a/src/test/run-fail/extern-panic.rs b/src/test/run-fail/extern-panic.rs
deleted file mode 100644 (file)
index f4a3adb..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test linked failure
-// error-pattern:explicit failure
-// Testing that runtime failure doesn't cause callbacks to abort abnormally.
-// Instead the failure will be delivered after the callbacks return.
-#![feature(std_misc, libc)]
-
-extern crate libc;
-use std::task;
-
-mod rustrt {
-    extern crate libc;
-
-    extern {
-        pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
-                             -> libc::uintptr_t;
-    }
-}
-
-extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 {
-        data
-    } else {
-        count(data - 1) + count(data - 1)
-    }
-}
-
-fn count(n: usize) -> usize {
-    unsafe {
-        task::deschedule();
-        rustrt::rust_dbg_call(cb, n)
-    }
-}
-
-fn main() {
-    for _ in 0..10 {
-        task::spawn(move|| {
-            let result = count(5);
-            println!("result = %?", result);
-            panic!();
-        });
-    }
-}
diff --git a/src/test/run-fail/issue-2061.rs b/src/test/run-fail/issue-2061.rs
deleted file mode 100644 (file)
index 252ac9b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-// error-pattern: thread '<main>' has overflowed its stack
-
-struct R {
-    b: isize,
-}
-
-impl Drop for R {
-    fn drop(&mut self) {
-        let _y = R { b: self.b };
-    }
-}
-
-fn main() {
-    let _x = R { b: 0 };
-}
diff --git a/src/test/run-fail/overflowing-simd-lsh-1.rs b/src/test/run-fail/overflowing-simd-lsh-1.rs
new file mode 100644 (file)
index 0000000..a3bce00
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::i32x4;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = i32x4(1, 0, 0, 0) << id(i32x4(32, 0, 0, 0));
+}
diff --git a/src/test/run-fail/overflowing-simd-lsh-2.rs b/src/test/run-fail/overflowing-simd-lsh-2.rs
new file mode 100644 (file)
index 0000000..e119bd0
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::i32x4;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = i32x4(1, 0, 0, 0) << id(i32x4(-1, 0, 0, 0));
+}
diff --git a/src/test/run-fail/overflowing-simd-lsh-3.rs b/src/test/run-fail/overflowing-simd-lsh-3.rs
new file mode 100644 (file)
index 0000000..4fb7fa9
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::u64x2;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = u64x2(1, 0) << id(u64x2(64, 0));
+}
diff --git a/src/test/run-fail/overflowing-simd-lsh-4.rs b/src/test/run-fail/overflowing-simd-lsh-4.rs
new file mode 100644 (file)
index 0000000..2fc177c
--- /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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// This function is checking that our automatic truncation does not
+// sidestep the overflow checking.
+
+#![feature(core_simd)]
+
+use std::simd::i8x16;
+
+fn eq_i8x16(i8x16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15): i8x16,
+            i8x16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15): i8x16)
+            -> bool
+{
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+        && (x8 == y8) && (x9 == y9) && (x10 == y10) && (x11 == y11)
+        && (x12 == y12) && (x13 == y13) && (x14 == y14) && (x15 == y15)
+}
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    // this signals overflow when checking is on
+    let x = i8x16(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+        << id(i8x16(17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+    // ... but when checking is off, the fallback will truncate the
+    // input to its lower three bits (= 1). Note that this is *not*
+    // the behavior of the x86 processor for 8- and 16-bit types,
+    // but it is necessary to avoid undefined behavior from LLVM.
+    //
+    // We check that here, by ensuring the result has only been
+    // shifted by one place; if overflow checking is turned off, then
+    // this assertion will pass (and the compiletest driver will
+    // report that the test did not produce the error expected above).
+    assert!(eq_i8x16(x, i8x16(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
+}
diff --git a/src/test/run-fail/overflowing-simd-rsh-1.rs b/src/test/run-fail/overflowing-simd-rsh-1.rs
new file mode 100644 (file)
index 0000000..dffd627
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::i32x4;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = i32x4(-1, 0, 0, 0) >> id(i32x4(32, 0, 0, 0));
+}
diff --git a/src/test/run-fail/overflowing-simd-rsh-2.rs b/src/test/run-fail/overflowing-simd-rsh-2.rs
new file mode 100644 (file)
index 0000000..2852e14
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::i32x4;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = i32x4(0, 0, 0, -1) >> id(i32x4(0, 0, 0, -1));
+}
diff --git a/src/test/run-fail/overflowing-simd-rsh-3.rs b/src/test/run-fail/overflowing-simd-rsh-3.rs
new file mode 100644 (file)
index 0000000..057eaa3
--- /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:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::i64x2;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = i64x2(0, -1) >> id(i64x2(0, 64));
+}
diff --git a/src/test/run-fail/overflowing-simd-rsh-4.rs b/src/test/run-fail/overflowing-simd-rsh-4.rs
new file mode 100644 (file)
index 0000000..a850fff
--- /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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// This function is checking that our (type-based) automatic
+// truncation does not sidestep the overflow checking.
+
+#![feature(core_simd)]
+
+use std::simd::i8x16;
+
+fn eq_i8x16(i8x16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15): i8x16,
+            i8x16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15): i8x16)
+            -> bool
+{
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+        && (x8 == y8) && (x9 == y9) && (x10 == y10) && (x11 == y11)
+        && (x12 == y12) && (x13 == y13) && (x14 == y14) && (x15 == y15)
+}
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    // this signals overflow when checking is on
+    let x = i8x16(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+        >> id(i8x16(17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+    // ... but when checking is off, the fallback will truncate the
+    // input to its lower three bits (= 1). Note that this is *not*
+    // the behavior of the x86 processor for 8- and 16-bit types,
+    // but it is necessary to avoid undefined behavior from LLVM.
+    //
+    // We check that here, by ensuring the result is not zero; if
+    // overflow checking is turned off, then this assertion will pass
+    // (and the compiletest driver will report that the test did not
+    // produce the error expected above).
+    assert!(eq_i8x16(x, i8x16(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
+}
index 7c6473ebfc26d1c7d73dc3f43d895de57ff89be5..6773c6b9b5184cb07995efd429e774a0acaee1bc 100644 (file)
@@ -9,4 +9,4 @@
 // except according to those terms.
 
 // error-pattern:1 == 2
-fn main() { assert!((1 == 2)); }
+fn main() { assert!(1 == 2); }
diff --git a/src/test/run-fail/too-much-recursion-unwinding.rs b/src/test/run-fail/too-much-recursion-unwinding.rs
deleted file mode 100644 (file)
index 6e5a9b2..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test leaks
-// error-pattern:ran out of stack
-
-// Test that the thread panicks after hitting the recursion limit
-// during unwinding
-
-fn recurse() {
-    println!("don't optimize me out");
-    recurse();
-}
-
-struct r {
-    recursed: *mut bool,
-}
-
-impl Drop for r {
-    fn drop(&mut self) {
-        unsafe {
-            if !*(self.recursed) {
-                *(self.recursed) = true;
-                recurse();
-            }
-        }
-    }
-}
-
-fn r(recursed: *mut bool) -> r {
-    r { recursed: recursed }
-}
-
-fn main() {
-    let mut recursed = false;
-    let _r = r(&mut recursed);
-    recurse();
-}
diff --git a/src/test/run-make/execution-engine/Makefile b/src/test/run-make/execution-engine/Makefile
new file mode 100644 (file)
index 0000000..387905f
--- /dev/null
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+# This is a basic test of LLVM ExecutionEngine functionality using compiled
+# Rust code built using the `rustc` crate.
+
+all:
+       $(RUSTC) test.rs
+       $(call RUN,test $(RUSTC))
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
new file mode 100644 (file)
index 0000000..8af3844
--- /dev/null
@@ -0,0 +1,250 @@
+// 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 rustc;
+extern crate rustc_driver;
+extern crate rustc_lint;
+extern crate rustc_resolve;
+extern crate syntax;
+
+use std::ffi::{CStr, CString};
+use std::mem::transmute;
+use std::path::PathBuf;
+use std::thread::Builder;
+
+use rustc::ast_map;
+use rustc::llvm;
+use rustc::metadata::cstore::RequireDynamic;
+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_resolve::MakeGlobMap;
+
+use syntax::diagnostics::registry::Registry;
+
+fn main() {
+    let program = r#"
+    #[no_mangle]
+    pub static TEST_STATIC: i32 = 42;
+    "#;
+
+    let program2 = r#"
+    #[no_mangle]
+    pub fn test_add(a: i32, b: i32) -> i32 { a + b }
+    "#;
+
+    let mut path = match std::env::args().nth(2) {
+        Some(path) => PathBuf::from(&path),
+        None => panic!("missing rustc path")
+    };
+
+    // Remove two segments from rustc path to get sysroot.
+    path.pop();
+    path.pop();
+
+    let mut ee = ExecutionEngine::new(program, path);
+
+    let test_static = match ee.get_global("TEST_STATIC") {
+        Some(g) => g as *const i32,
+        None => panic!("failed to get global")
+    };
+
+    assert_eq!(unsafe { *test_static }, 42);
+
+    ee.add_module(program2);
+
+    let test_add: fn(i32, i32) -> i32;
+
+    test_add = match ee.get_function("test_add") {
+        Some(f) => unsafe { transmute(f) },
+        None => panic!("failed to get function")
+    };
+
+    assert_eq!(test_add(1, 2), 3);
+}
+
+struct ExecutionEngine {
+    ee: llvm::ExecutionEngineRef,
+    modules: Vec<llvm::ModuleRef>,
+    sysroot: PathBuf,
+}
+
+impl ExecutionEngine {
+    pub fn new(program: &str, sysroot: PathBuf) -> ExecutionEngine {
+        let (llmod, deps) = compile_program(program, sysroot.clone())
+            .expect("failed to compile program");
+
+        let ee = unsafe { llvm::LLVMBuildExecutionEngine(llmod) };
+
+        if ee.is_null() {
+            panic!("Failed to create ExecutionEngine: {}", llvm_error());
+        }
+
+        let ee = ExecutionEngine{
+            ee: ee,
+            modules: vec![llmod],
+            sysroot: sysroot,
+        };
+
+        ee.load_deps(&deps);
+        ee
+    }
+
+    pub fn add_module(&mut self, program: &str) {
+        let (llmod, deps) = compile_program(program, self.sysroot.clone())
+            .expect("failed to compile program in add_module");
+
+        unsafe { llvm::LLVMExecutionEngineAddModule(self.ee, llmod); }
+
+        self.modules.push(llmod);
+        self.load_deps(&deps);
+    }
+
+    /// Returns a raw pointer to the named function.
+    pub fn get_function(&mut self, name: &str) -> Option<*const ()> {
+        let s = CString::new(name.as_bytes()).unwrap();
+
+        for &m in &self.modules {
+            let fv = unsafe { llvm::LLVMGetNamedFunction(m, s.as_ptr()) };
+
+            if !fv.is_null() {
+                let fp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, fv) };
+
+                assert!(!fp.is_null());
+                return Some(fp);
+            }
+        }
+        None
+    }
+
+    /// Returns a raw pointer to the named global item.
+    pub fn get_global(&mut self, name: &str) -> Option<*const ()> {
+        let s = CString::new(name.as_bytes()).unwrap();
+
+        for &m in &self.modules {
+            let gv = unsafe { llvm::LLVMGetNamedGlobal(m, s.as_ptr()) };
+
+            if !gv.is_null() {
+                let gp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, gv) };
+
+                assert!(!gp.is_null());
+                return Some(gp);
+            }
+        }
+        None
+    }
+
+    /// Loads all dependencies of compiled code.
+    /// Expects a series of paths to dynamic library files.
+    fn load_deps(&self, deps: &[PathBuf]) {
+        for path in deps {
+            let s = match path.as_os_str().to_str() {
+                Some(s) => s,
+                None => panic!(
+                    "Could not convert crate path to UTF-8 string: {:?}", path)
+            };
+            let cs = CString::new(s).unwrap();
+
+            let res = unsafe { llvm::LLVMRustLoadDynamicLibrary(cs.as_ptr()) };
+
+            if res == 0 {
+                panic!("Failed to load crate {:?}: {}",
+                    path.display(), llvm_error());
+            }
+        }
+    }
+}
+
+impl Drop for ExecutionEngine {
+    fn drop(&mut self) {
+        unsafe { llvm::LLVMDisposeExecutionEngine(self.ee) };
+    }
+}
+
+/// Returns last error from LLVM wrapper code.
+fn llvm_error() -> String {
+    String::from_utf8_lossy(
+        unsafe { CStr::from_ptr(llvm::LLVMRustGetLastError()).to_bytes() })
+        .into_owned()
+}
+
+fn build_exec_options(sysroot: PathBuf) -> Options {
+    let mut opts = basic_options();
+
+    // librustc derives sysroot from the executable name.
+    // Since we are not rustc, we must specify it.
+    opts.maybe_sysroot = Some(sysroot);
+
+    // Prefer faster build time
+    opts.optimize = config::No;
+
+    // Don't require a `main` function
+    opts.crate_types = vec![config::CrateTypeDylib];
+
+    opts
+}
+
+/// Compiles input up to phase 4, translation to LLVM.
+///
+/// Returns the LLVM `ModuleRef` and a series of paths to dynamic libraries
+/// for crates used in the given input.
+fn compile_program(input: &str, sysroot: PathBuf)
+                   -> Option<(llvm::ModuleRef, Vec<PathBuf>)> {
+    let input = Input::Str(input.to_string());
+    let thread = Builder::new().name("compile_program".to_string());
+
+    let handle = thread.spawn(move || {
+        let opts = build_exec_options(sysroot);
+        let sess = build_session(opts, None, Registry::new(&rustc::DIAGNOSTICS));
+        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+
+        let cfg = build_configuration(&sess);
+
+        let id = "input".to_string();
+
+        let krate = driver::phase_1_parse_input(&sess, cfg, &input);
+
+        let krate = driver::phase_2_configure_and_expand(&sess, krate, &id, None)
+            .expect("phase_2 returned `None`");
+
+        let mut forest = ast_map::Forest::new(krate);
+        let arenas = ty::CtxtArenas::new();
+        let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
+
+        driver::phase_3_run_analysis_passes(
+            sess, ast_map, &arenas, id, MakeGlobMap::No, |tcx, analysis| {
+
+            let trans = driver::phase_4_translate_to_llvm(tcx, analysis);
+
+            let crates = tcx.sess.cstore.get_used_crates(RequireDynamic);
+
+            // Collect crates used in the session.
+            // Reverse order finds dependencies first.
+            let deps = crates.into_iter().rev()
+                .filter_map(|(_, p)| p).collect();
+
+            assert_eq!(trans.modules.len(), 1);
+            let llmod = trans.modules[0].llmod;
+
+            // Workaround because raw pointers do not impl Send
+            let modp = llmod as usize;
+
+            (modp, deps)
+        }).1
+    }).unwrap();
+
+    match handle.join() {
+        Ok((llmod, deps)) => Some((llmod as llvm::ModuleRef, deps)),
+        Err(_) => None
+    }
+}
index 90e1330d4ae472c8b6121704dbce97672bc3a1dc..9923ff83a918500f0d3c888564fa986ee0035ef4 100644 (file)
@@ -16,6 +16,6 @@ extern crate c;
 fn t(a: &'static usize) -> usize { a as *const _ as usize }
 
 fn main() {
-    assert!(t(a::token()) == t(b::a_token()));
+    assert_eq!(t(a::token()), t(b::a_token()));
     assert!(t(a::token()) != t(c::a_token()));
 }
index 244f32b8ee5fc323feaf63457562faf436f95bb2..b53a870e2001cb0129151fa59b4c6a07209fd608 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_misc)]
+#![feature(dynamic_lib)]
 
 use std::dynamic_lib::DynamicLibrary;
 use std::path::Path;
index 81ed446595ab0c6474c7c9802621bcb41f0e6f2c..f58d2cd8f91d8d84d2d0ab95f65c87caa6380835 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(asm, core)]
+#![feature(asm, core_intrinsics)]
 #![crate_type="lib"]
 
 use std::intrinsics;
diff --git a/src/test/run-make/issue-25581/Makefile b/src/test/run-make/issue-25581/Makefile
new file mode 100644 (file)
index 0000000..ea69718
--- /dev/null
@@ -0,0 +1,7 @@
+-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)
+       $(call RUN,test) || exit 1
diff --git a/src/test/run-make/issue-25581/test.c b/src/test/run-make/issue-25581/test.c
new file mode 100644 (file)
index 0000000..5736b17
--- /dev/null
@@ -0,0 +1,16 @@
+// ignore-license
+#include <stddef.h>
+#include <stdint.h>
+
+struct ByteSlice {
+        uint8_t *data;
+        size_t len;
+};
+
+size_t slice_len(struct ByteSlice bs) {
+        return bs.len;
+}
+
+uint8_t slice_elem(struct ByteSlice bs, size_t idx) {
+        return bs.data[idx];
+}
diff --git a/src/test/run-make/issue-25581/test.rs b/src/test/run-make/issue-25581/test.rs
new file mode 100644 (file)
index 0000000..e2e86df
--- /dev/null
@@ -0,0 +1,32 @@
+// 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(libc)]
+
+extern crate libc;
+
+#[link(name = "test")]
+extern {
+    fn slice_len(s: &[u8]) -> libc::size_t;
+    fn slice_elem(s: &[u8], idx: libc::size_t) -> u8;
+}
+
+fn main() {
+    let data = [1,2,3,4,5];
+
+    unsafe {
+        assert_eq!(data.len(), slice_len(&data) as usize);
+        assert_eq!(data[0], slice_elem(&data, 0));
+        assert_eq!(data[1], slice_elem(&data, 1));
+        assert_eq!(data[2], slice_elem(&data, 2));
+        assert_eq!(data[3], slice_elem(&data, 3));
+        assert_eq!(data[4], slice_elem(&data, 4));
+    }
+}
diff --git a/src/test/run-make/issue-26006/Makefile b/src/test/run-make/issue-26006/Makefile
new file mode 100644 (file)
index 0000000..10c789d
--- /dev/null
@@ -0,0 +1,16 @@
+-include ../tools.mk
+
+ifndef IS_WINDOWS
+all: time
+
+time: libc
+       mkdir -p out/time out/time/deps
+       ln -sf out/libc/liblibc.rlib out/time/deps/
+       $(RUSTC) in/time/lib.rs -Ldependency=out/time/deps/
+
+libc:
+       mkdir -p out/libc
+       $(RUSTC) in/libc/lib.rs --crate-name=libc -o out/libc/liblibc.rlib
+else
+all:
+endif
diff --git a/src/test/run-make/issue-26006/in/libc/lib.rs b/src/test/run-make/issue-26006/in/libc/lib.rs
new file mode 100644 (file)
index 0000000..177ffdc
--- /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.
+#![crate_type="rlib"]
+
+pub fn something(){}
diff --git a/src/test/run-make/issue-26006/in/time/lib.rs b/src/test/run-make/issue-26006/in/time/lib.rs
new file mode 100644 (file)
index 0000000..b1d07d5
--- /dev/null
@@ -0,0 +1,13 @@
+// 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(libc)]
+extern crate libc;
+
+fn main(){}
diff --git a/src/test/run-make/issue-26092/Makefile b/src/test/run-make/issue-26092/Makefile
new file mode 100644 (file)
index 0000000..1e66e3a
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+               $(RUSTC) -o "" blank.rs 2>&1 | \
+                       grep 'No such file or directory'
diff --git a/src/test/run-make/issue-26092/blank.rs b/src/test/run-make/issue-26092/blank.rs
new file mode 100644 (file)
index 0000000..8ae3d07
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {}
index d325f54d36515bc5622fb4aa6e6b33a75a876d9f..ba4860be91d66457c42ceb46f513f4efdc3e601f 100644 (file)
@@ -28,7 +28,7 @@ fn main() {
     }).join().err().unwrap();
 
     unsafe {
-        assert!(lib::statik == 1);
-        assert!(statik == 1);
+        assert_eq!(lib::statik, 1);
+        assert_eq!(statik, 1);
     }
 }
index 217dee4b881c7a92ac13ea61cc97c9c26b6d8908..6c6afdc13030ca19dfe596927992ae3cac2d7975 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(core_intrinsics)]
 
 use std::intrinsics::{volatile_load, volatile_store};
 
index 1cf36dab395fd3f1091014239be44fa40264d3b5..0805bc5dcb35955b1ca833d9c0cc62f5180d4cd5 100644 (file)
@@ -78,5 +78,5 @@ fn main() {
     // we should never get use this filename, but lets make sure they are valid args.
     let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
     rustc_driver::run_compiler(&args, &mut tc);
-    assert!(tc.count == 30);
+    assert_eq!(tc.count, 30);
 }
index ea7e959a73ce82dc5605e58c76eaf09dd6d8e45d..c0ed7165afecac903a1c08258eccec8cf5953bb0 100644 (file)
@@ -52,7 +52,7 @@ fn test() {
     let path = {
         let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect();
         paths.push(child_dir.to_path_buf());
-        env::join_paths(paths.iter()).unwrap()
+        env::join_paths(paths).unwrap()
     };
 
     let child_output = process::Command::new("mytest").env("PATH", &path)
@@ -64,6 +64,10 @@ fn test() {
                     str::from_utf8(&child_output.stdout).unwrap(),
                     str::from_utf8(&child_output.stderr).unwrap()));
 
-    fs::remove_dir_all(&child_dir).unwrap();
-
+    let res = fs::remove_dir_all(&child_dir);
+    if res.is_err() {
+        // On Windows deleting just executed mytest.exe can fail because it's still locked
+        std::thread::sleep_ms(1000);
+        fs::remove_dir_all(&child_dir).unwrap();
+    }
 }
index ceface384847fe540c917a3c985776c129d88a2a..6670f200ba71ed37ef90f0d7e65c034ebe7de5c4 100644 (file)
@@ -18,7 +18,7 @@ use syntax::codemap::DUMMY_SP;
 use syntax::print::pprust::*;
 
 fn main() {
-    let ps = syntax::parse::new_parse_sess();
+    let ps = syntax::parse::ParseSess::new();
     let mut cx = syntax::ext::base::ExtCtxt::new(
         &ps, vec![],
         syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
new file mode 100644 (file)
index 0000000..b13e342
--- /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.
+
+#![allow(dead_code)]
+#![feature(const_fn)]
+
+// check dtor calling order when casting enums.
+
+use std::sync::atomic;
+use std::sync::atomic::Ordering;
+use std::mem;
+
+enum E {
+    A = 0,
+    B = 1,
+    C = 2
+}
+
+static FLAG: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
+
+impl Drop for E {
+    fn drop(&mut self) {
+        // avoid dtor loop
+        unsafe { mem::forget(mem::replace(self, E::B)) };
+
+        FLAG.store(FLAG.load(Ordering::SeqCst)+1, Ordering::SeqCst);
+    }
+}
+
+fn main() {
+    assert_eq!(FLAG.load(Ordering::SeqCst), 0);
+    {
+        let e = E::C;
+        assert_eq!(e as u32, 2);
+        assert_eq!(FLAG.load(Ordering::SeqCst), 0);
+    }
+    assert_eq!(FLAG.load(Ordering::SeqCst), 1);
+}
index 59b593b1ab3f604d0d0ca08fd36fabd6de7ce21b..a89873b1277e0fcadb5b1198fdba2eef6e9d4225 100644 (file)
@@ -27,6 +27,6 @@ pub fn main() {
         let _x: Box<Fat<[Foo]>> = Box::<Fat<[Foo; 3]>>::new(Fat { f: [Foo, Foo, Foo] });
     }
     unsafe {
-        assert!(DROP_RAN == 3);
+        assert_eq!(DROP_RAN, 3);
     }
 }
index c93049b87a76483473ef35c46fd0570dba5b9d4f..48e834cf54dd10cad00bd7a3ac29d738f854e1bb 100644 (file)
@@ -13,6 +13,6 @@
 
 pub fn main() {
     let i32_c: isize = 0x10101010;
-    assert!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3) ==
+    assert_eq!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
                  i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3));
 }
index 53eec3c28c0de7580e9e60b1a3fbd77786b4cb13..de946d94d07b9cbd233fae314004ac29e4e098e9 100644 (file)
@@ -11,4 +11,4 @@
 
 fn f() -> isize { { return 3; } }
 
-pub fn main() { assert!((f() == 3)); }
+pub fn main() { assert_eq!(f(), 3); }
index 3eebc7acb0fd55f2b43507b4a13b443603569bd8..243ecf86e9c46599c5977369aed4e827df2fdacd 100644 (file)
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(asm)]
 
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 unsafe fn next_power_of_2(n: u32) -> u32 {
     let mut tmp = n;
     asm!("dec $0" : "+rm"(tmp) :: "cc");
-    let mut shift = 1_usize;
+    let mut shift = 1_u32;
     while shift <= 16 {
         asm!(
             "shr %cl, $2
index f05a1520b8ef88e173465d8b1b0985e860333932..0ee460052c73f73865ae76a86b205dda9d794abc 100644 (file)
@@ -43,7 +43,7 @@ fn length<A, T: iterable<A>>(x: T) -> usize {
 pub fn main() {
     let x: Vec<isize> = vec!(0,1,2,3);
     // Call a method
-    x.iterate(|y| { assert!(x[*y as usize] == *y); true });
+    x.iterate(|y| { assert_eq!(x[*y as usize], *y); true });
     // Call a parameterized function
     assert_eq!(length(x.clone()), x.len());
     // Call a parameterized function, with type arguments that require
diff --git a/src/test/run-pass/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-const-range-match-patterns.rs
new file mode 100644 (file)
index 0000000..d38ccca
--- /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.
+
+#![feature(associated_consts)]
+
+struct Foo;
+
+trait HasNum {
+    const NUM: isize;
+}
+impl HasNum for Foo {
+    const NUM: isize = 1;
+}
+
+fn main() {
+    assert!(match 2 {
+        Foo::NUM ... 3 => true,
+        _ => false,
+    });
+    assert!(match 0 {
+        -1 ... <Foo as HasNum>::NUM => true,
+        _ => false,
+    });
+    assert!(match 1 {
+        <Foo as HasNum>::NUM ... <Foo>::NUM => true,
+        _ => false,
+    });
+}
index 1a8da6755588be0e41cb3f3f5e4551293dbce350..dbf975c6f2e882c7e4f6a0cd509110ad8ea9fcbf 100644 (file)
@@ -28,8 +28,7 @@ impl<A, B> MyEq<[B]> for [A]
 {
     fn eq(&self, other: &[B]) -> bool {
         self.len() == other.len() &&
-            self.iter().zip(other.iter())
-                       .all(|(a, b)| MyEq::eq(a, b))
+            self.iter().zip(other).all(|(a, b)| MyEq::eq(a, b))
     }
 }
 
index 181ce52eb4baf6fb2dcee6fa65d02f4f1e65b624..be854f820d4d6793cdb0059282999d24c70e21ae 100644 (file)
@@ -23,6 +23,6 @@ fn pairwise_sub<T:DoubleEndedIterator<Item=isize>>(mut t: T) -> isize {
 
 fn main() {
     let v = vec!(1, 2, 3, 4, 5, 6);
-    let r =pairwise_sub(v.into_iter());
+    let r = pairwise_sub(v.into_iter());
     assert_eq!(r, 9);
 }
diff --git a/src/test/run-pass/associated-types-method.rs b/src/test/run-pass/associated-types-method.rs
new file mode 100644 (file)
index 0000000..b57687a
--- /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.
+
+// Test that methods whose impl-trait-ref contains associated types
+// are supported.
+
+trait Device {
+    type Resources;
+}
+struct Foo<D, R>(D, R);
+
+trait Tr {
+    fn present(&self) {}
+}
+
+impl<D: Device> Tr for Foo<D, D::Resources> {
+    fn present(&self) {}
+}
+
+struct Res;
+struct Dev;
+impl Device for Dev {
+    type Resources = Res;
+}
+
+fn main() {
+    let foo = Foo(Dev, Res);
+    foo.present();
+}
index 1830b41d0b50681ee7a986b259ae0ca1d7e4655a..8dc7d79ec2a7772c5c6d4162cd767d94ac118a2f 100644 (file)
 // `Item` originates in a where-clause, not the declaration of
 // `T`. Issue #20300.
 
+#![feature(const_fn)]
+
 use std::marker::{PhantomData};
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::{AtomicUsize};
 use std::sync::atomic::Ordering::SeqCst;
 
-static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
+static COUNTER: AtomicUsize = AtomicUsize::new(0);
 
 // Preamble.
 trait Trait { type Item; }
index 5bba54e57b477ce5e334a14e7c5aecdc368364c9..f5434c9eb865ce4adaf964854eb0d1d13c3ce739 100644 (file)
@@ -16,7 +16,7 @@ pub trait Foo {
     fn boo(&self) -> <Self as Foo>::A;
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 pub struct Bar;
 
 impl Foo for isize {
@@ -44,12 +44,12 @@ fn foo2<I: Foo>(x: I) -> <I as Foo>::A {
 
 pub fn main() {
     let a = 42;
-    assert!(foo2(a) == 42);
+    assert_eq!(foo2(a), 42);
 
     let a = Bar;
-    assert!(foo2(a) == 43);
+    assert_eq!(foo2(a), 43);
 
     let a = 'a';
     foo1(a);
-    assert!(foo2(a) == Bar);
+    assert_eq!(foo2(a), Bar);
 }
diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs
deleted file mode 100644 (file)
index 2df0bb3..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test FIXME(#5121)
-
-extern crate rbml;
-extern crate serialize;
-extern crate time;
-
-// These tests used to be separate files, but I wanted to refactor all
-// the common code.
-
-use std::collections::{HashMap, HashSet};
-
-use rbml::reader as EBReader;
-use rbml::writer as EBWriter;
-use std::cmp::Eq;
-use std::cmp;
-use std::io;
-use serialize::{Decodable, Encodable};
-
-fn test_rbml<'a, 'b, A:
-    Eq +
-    Encodable<EBWriter::Encoder<'a>> +
-    Decodable<EBReader::Decoder<'b>>
->(a1: &A) {
-    let mut wr = Vec::new();
-    let mut rbml_w = EBwriter::Encoder::new(&mut wr);
-    a1.encode(&mut rbml_w);
-
-    let d: serialize::rbml::Doc<'a> = EBDoc::new(&wr);
-    let mut decoder: EBReader::Decoder<'a> = EBreader::Decoder::new(d);
-    let a2: A = Decodable::decode(&mut decoder);
-    assert!(*a1 == a2);
-}
-
-#[derive(Decodable, Encodable)]
-enum Expr {
-    Val(usize),
-    Plus(@Expr, @Expr),
-    Minus(@Expr, @Expr)
-}
-
-impl cmp::Eq for Expr {
-    fn eq(&self, other: &Expr) -> bool {
-        match *self {
-            Val(e0a) => {
-                match *other {
-                    Val(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            Plus(e0a, e1a) => {
-                match *other {
-                    Plus(e0b, e1b) => e0a == e0b && e1a == e1b,
-                    _ => false
-                }
-            }
-            Minus(e0a, e1a) => {
-                match *other {
-                    Minus(e0b, e1b) => e0a == e0b && e1a == e1b,
-                    _ => false
-                }
-            }
-        }
-    }
-    fn ne(&self, other: &Expr) -> bool { !(*self).eq(other) }
-}
-
-impl cmp::Eq for Point {
-    fn eq(&self, other: &Point) -> bool {
-        self.x == other.x && self.y == other.y
-    }
-    fn ne(&self, other: &Point) -> bool { !(*self).eq(other) }
-}
-
-impl<T:cmp::Eq> cmp::Eq for Quark<T> {
-    fn eq(&self, other: &Quark<T>) -> bool {
-        match *self {
-            Top(ref q) => {
-                match *other {
-                    Top(ref r) => q == r,
-                    Bottom(_) => false
-                }
-            },
-            Bottom(ref q) => {
-                match *other {
-                    Top(_) => false,
-                    Bottom(ref r) => q == r
-                }
-            },
-        }
-    }
-    fn ne(&self, other: &Quark<T>) -> bool { !(*self).eq(other) }
-}
-
-impl cmp::Eq for CLike {
-    fn eq(&self, other: &CLike) -> bool {
-        (*self) as isize == *other as isize
-    }
-    fn ne(&self, other: &CLike) -> bool { !self.eq(other) }
-}
-
-#[derive(Decodable, Encodable, Eq)]
-struct Spanned<T> {
-    lo: usize,
-    hi: usize,
-    node: T,
-}
-
-#[derive(Decodable, Encodable)]
-struct SomeStruct { v: Vec<usize> }
-
-#[derive(Decodable, Encodable)]
-struct Point {x: usize, y: usize}
-
-#[derive(Decodable, Encodable)]
-enum Quark<T> {
-    Top(T),
-    Bottom(T)
-}
-
-#[derive(Decodable, Encodable)]
-enum CLike { A, B, C }
-
-pub fn main() {
-    let a = &Plus(@Minus(@Val(3), @Val(10)), @Plus(@Val(22), @Val(5)));
-    test_rbml(a);
-
-    let a = &Spanned {lo: 0, hi: 5, node: 22};
-    test_rbml(a);
-
-    let a = &Point {x: 3, y: 5};
-    test_rbml(a);
-
-    let a = &Top(22);
-    test_rbml(a);
-
-    let a = &Bottom(222);
-    test_rbml(a);
-
-    let a = &A;
-    test_rbml(a);
-
-    let a = &B;
-    test_rbml(a);
-
-    let a = &time::now();
-    test_rbml(a);
-
-    test_rbml(&1.0f32);
-    test_rbml(&1.0f64);
-    test_rbml(&'a');
-
-    let mut a = HashMap::new();
-    test_rbml(&a);
-    a.insert(1, 2);
-    test_rbml(&a);
-
-    let mut a = HashSet::new();
-    test_rbml(&a);
-    a.insert(1);
-    test_rbml(&a);
-}
index 2a74e36aff3ddd8f34beb5dd2b8ad0a2b7f33e26..8f41c68b0473fb4759d818e8a1460702f80a088b 100644 (file)
@@ -97,10 +97,6 @@ fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
     let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
         check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
     });
-
-    // this tests a distinction between two independent calls to the inlined function.
-    // (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
-    inner_further_inlined(counter, main_pos, outer_pos, pos!());
 }
 
 #[inline(never)]
index 4888a8b84fc42a55eccea9d032d82604d1994fc3..61a7fab130928493054a016d8c3414206ed8fa14 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_misc, collections, catch_panic, rand)]
+#![feature(std_misc, collections, catch_panic, rand, sync_poison)]
 
 use std::__rand::{thread_rng, Rng};
 use std::thread;
index c9a2e07dd8398eb3a1445f7ca5136e64e3d86792..3ab154356c4b6c23e5c6b52f3ca2a4b2120cb8e4 100644 (file)
 
 // pretty-expanded FIXME #23616
 
-#![allow(unknown_features)]
-#![feature(box_syntax, collections)]
+#![feature(bitvec)]
 
-extern crate collections;
 use std::collections::BitVec;
 
 fn bitv_test() {
-    let mut v1: Box<_> = box BitVec::from_elem(31, false);
-    let v2: Box<_> = box BitVec::from_elem(31, true);
-    v1.union(&*v2);
+    let mut v1 = BitVec::from_elem(31, false);
+    let v2 = BitVec::from_elem(31, true);
+    v1.union(&v2);
 }
 
 pub fn main() {
index 53b568b06b5b6a16546cdcb52c290828ae7d6feb..1152574d069424d85106ac24f91fa3db0f1066ff 100644 (file)
@@ -74,8 +74,8 @@ fn main() {
     assert!(true >= false);
     assert!(!(true <= false));
 
-    assert!(true.cmp(&true) == Equal);
-    assert!(false.cmp(&false) == Equal);
-    assert!(true.cmp(&false) == Greater);
-    assert!(false.cmp(&true) == Less);
+    assert_eq!(true.cmp(&true), Equal);
+    assert_eq!(false.cmp(&false), Equal);
+    assert_eq!(true.cmp(&false), Greater);
+    assert_eq!(false.cmp(&true), Less);
 }
diff --git a/src/test/run-pass/borrowck-nested-calls.rs b/src/test/run-pass/borrowck-nested-calls.rs
deleted file mode 100644 (file)
index fa50eaa..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test FIXME (#6268) nested method calls
-
-// Test that (safe) nested calls with `&mut` receivers are permitted.
-
-struct Foo {a: usize, b: usize}
-
-impl Foo {
-    pub fn inc_a(&mut self, v: usize) { self.a += v; }
-
-    pub fn next_b(&mut self) -> usize {
-        let b = self.b;
-        self.b += 1;
-        b
-    }
-}
-
-pub fn main() {
-    let mut f = Foo {a: 22, b: 23};
-    f.inc_a(f.next_b());
-    assert_eq!(f.a, 22+23);
-    assert_eq!(f.b, 24);
-}
index a93a488c1b5fd1a6d7dd01b9a8432e0bea4c99ac..e889d74c7ccc4e85be6317f0087bc3bf66e34c69 100644 (file)
 // Test that we cleanup a fixed size Box<[D; k]> properly when D has a
 // destructor.
 
+#![feature(const_fn)]
+
 use std::thread;
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 struct D(u8);
 
index 715571364c8def8e7a2ee389af3e7751a5629ed3..f108ef4f5d22de94deefff812dc0ceca310bb88c 100644 (file)
 // Test that we cleanup dynamic sized Box<[D]> properly when D has a
 // destructor.
 
+#![feature(const_fn)]
+
 use std::thread;
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 struct D(u8);
 
index c5064d56ca1233502c64e6d21e9be352f4534cb8..e028c3b9d4b30bedc4302d34a05debfe046a4da3 100644 (file)
@@ -30,5 +30,5 @@ fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
 pub fn main() {
     let (tx, rx) = channel();
     foo(31337, tx);
-    assert!(rx.recv().unwrap() == 31337);
+    assert_eq!(rx.recv().unwrap(), 31337);
 }
index 183e6fe232cd39e7c9533f3edf56ea53960ce598..1a27eae19432846c1b1143543fb0bd3b354e65ee 100644 (file)
@@ -20,7 +20,7 @@ extern crate trait_superkinds_in_metadata;
 use std::sync::mpsc::{channel, Sender, Receiver};
 use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 struct X<T>(T);
 
 impl <T: Sync> RequiresShare for X<T> { }
@@ -33,5 +33,5 @@ fn foo<T: RequiresRequiresShareAndSend + 'static>(val: T, chan: Sender<T>) {
 pub fn main() {
     let (tx, rx): (Sender<X<isize>>, Receiver<X<isize>>) = channel();
     foo(X(31337), tx);
-    assert!(rx.recv().unwrap() == X(31337));
+    assert_eq!(rx.recv().unwrap(), X(31337));
 }
index a4d5c943b1f68b81458bef1ca9c1ab2d1dde7f67..99a68790e76e91d34d006927dc4b72d5eed22d86 100644 (file)
@@ -26,5 +26,5 @@ fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
 pub fn main() {
     let (tx, rx): (Sender<isize>, Receiver<isize>) = channel();
     foo(31337, tx);
-    assert!(rx.recv().unwrap() == 31337);
+    assert_eq!(rx.recv().unwrap(), 31337);
 }
index c4dc7d78b06d52df49518d17cebf8690d8a55ae3..9b8893b0762fdbc69e53e36f2c132f01138c6a7e 100644 (file)
@@ -25,5 +25,5 @@ impl <T: Send + 'static> Foo for T { }
 pub fn main() {
     let (tx, rx) = channel();
     1193182.foo(tx);
-    assert!(rx.recv().unwrap() == 1193182);
+    assert_eq!(rx.recv().unwrap(), 1193182);
 }
index d6b35f5385a4221012e413a1d35b8dfdca600ce9..84f22025a1d7ac529f28ce9020dc0f81c29e11aa 100644 (file)
@@ -37,6 +37,6 @@ fn atoll(s: String) -> i64 {
 
 pub fn main() {
     assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
-    assert!((atoll("11111111111111111".to_string()) * 10) ==
+    assert_eq!((atoll("11111111111111111".to_string()) * 10),
              atoll("111111111111111110".to_string()));
 }
diff --git a/src/test/run-pass/cast-rfc0401-vtable-kinds.rs b/src/test/run-pass/cast-rfc0401-vtable-kinds.rs
new file mode 100644 (file)
index 0000000..3a9f24a
--- /dev/null
@@ -0,0 +1,54 @@
+// 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 you can cast between different pointers to trait objects
+// whose vtable have the same kind (both lengths, or both trait pointers).
+
+trait Foo<T> {
+    fn foo(&self, _: T) -> u32 { 42 }
+}
+
+trait Bar {
+    fn bar(&self) { println!("Bar!"); }
+}
+
+impl<T> Foo<T> for () {}
+impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
+impl Bar for () {}
+
+unsafe fn round_trip_and_call<'a>(t: *const (Foo<u32>+'a)) -> u32 {
+    let foo_e : *const Foo<u16> = t as *const _;
+    let r_1 = foo_e as *mut Foo<u32>;
+
+    (&*r_1).foo(0)
+}
+
+#[repr(C)]
+struct FooS<T:?Sized>(T);
+#[repr(C)]
+struct BarS<T:?Sized>(T);
+
+fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
+    u as *const BarS<T>
+}
+
+fn main() {
+    let x = 4u32;
+    let y : &Foo<u32> = &x;
+    let fl = unsafe { round_trip_and_call(y as *const Foo<u32>) };
+    assert_eq!(fl, (43+4));
+
+    let s = FooS([0,1,2]);
+    let u: &FooS<[u32]> = &s;
+    let u: *const FooS<[u32]> = u;
+    let bar_ref : *const BarS<[u32]> = foo_to_bar(u);
+    let z : &BarS<[u32]> = unsafe{&*bar_ref};
+    assert_eq!(&z.0, &[0,1,2]);
+}
diff --git a/src/test/run-pass/cast-rfc0401.rs b/src/test/run-pass/cast-rfc0401.rs
new file mode 100644 (file)
index 0000000..5b6f6cc
--- /dev/null
@@ -0,0 +1,176 @@
+// 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)]
+
+use std::vec;
+
+enum Simple {
+    A,
+    B,
+    C
+}
+
+enum Valued {
+    H8=163,
+    Z=0,
+    X=256,
+    H7=67,
+}
+
+enum ValuedSigned {
+    M1=-1,
+    P1=1
+}
+
+fn main()
+{
+    // coercion-cast
+    let mut it = vec![137].into_iter();
+    let itr: &mut vec::IntoIter<u32> = &mut it;
+    assert_eq!((itr as &mut Iterator<Item=u32>).next(), Some(137));
+    assert_eq!((itr as &mut Iterator<Item=u32>).next(), None);
+
+    assert_eq!(Some(4u32) as Option<u32>, Some(4u32));
+    assert_eq!((1u32,2u32) as (u32,u32), (1,2));
+
+    // this isn't prim-int-cast. Check that it works.
+    assert_eq!(false as bool, false);
+    assert_eq!(true as bool, true);
+
+    // numeric-cast
+    let l: u64 = 0x8090a0b0c0d0e0f0;
+    let lsz: usize = l as usize;
+    assert_eq!(l as u32, 0xc0d0e0f0);
+
+    // numeric-cast
+    assert_eq!(l as u8, 0xf0);
+    assert_eq!(l as i8,-0x10);
+    assert_eq!(l as u32, 0xc0d0e0f0);
+    assert_eq!(l as u32 as usize as u32, l as u32);
+    assert_eq!(l as i32,-0x3f2f1f10);
+    assert_eq!(l as i32 as isize as i32, l as i32);
+    assert_eq!(l as i64,-0x7f6f5f4f3f2f1f10);
+
+    assert_eq!(0 as f64, 0f64);
+    assert_eq!(1 as f64, 1f64);
+
+    assert_eq!(l as f64, 9264081114510712022f64);
+
+    assert_eq!(l as i64 as f64, -9182662959198838444f64);
+//  float overflow : needs fixing
+//  assert_eq!(l as f32 as i64 as u64, 9264082620822882088u64);
+//  assert_eq!(l as i64 as f32 as i64, 9182664080220408446i64);
+
+    assert_eq!(4294967040f32 as u32, 0xffffff00u32);
+    assert_eq!(1.844674407370955e19f64 as u64, 0xfffffffffffff800u64);
+
+    assert_eq!(9.223372036854775e18f64 as i64, 0x7ffffffffffffc00i64);
+    assert_eq!(-9.223372036854776e18f64 as i64, 0x8000000000000000u64 as i64);
+
+    // addr-ptr-cast/ptr-addr-cast (thin ptr)
+    let p: *const [u8; 1] = lsz as *const [u8; 1];
+    assert_eq!(p as usize, lsz);
+
+    // ptr-ptr-cast (thin ptr)
+    let w: *const () = p as *const ();
+    assert_eq!(w as usize, lsz);
+
+    // ptr-ptr-cast (fat->thin)
+    let u: *const [u8] = unsafe{&*p};
+    assert_eq!(u as *const u8, p as *const u8);
+    assert_eq!(u as *const u16, p as *const u16);
+
+    // ptr-ptr-cast (Length vtables)
+    let mut l : [u8; 2] = [0,1];
+    let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _;
+    let w: *mut [u16] = unsafe {&mut *w};
+    let w_u8 : *const [u8] = w as *const [u8];
+    assert_eq!(unsafe{&*w_u8}, &l);
+
+    let s: *mut str = w as *mut str;
+    let l_via_str = unsafe{&*(s as *const [u8])};
+    assert_eq!(&l, l_via_str);
+
+    // ptr-ptr-cast (Length vtables, check length is preserved)
+    let l: [[u8; 3]; 2] = [[3, 2, 6], [4, 5, 1]];
+    let p: *const [[u8; 3]] = &l;
+    let p: &[[u8; 2]] = unsafe {&*(p as *const [[u8; 2]])};
+    assert_eq!(p, [[3, 2], [6, 4]]);
+
+    // enum-cast
+    assert_eq!(Simple::A as u8, 0);
+    assert_eq!(Simple::B as u8, 1);
+
+    assert_eq!(Valued::H8 as i8, -93);
+    assert_eq!(Valued::H7 as i8, 67);
+    assert_eq!(Valued::Z as i8, 0);
+
+    assert_eq!(Valued::H8 as u8, 163);
+    assert_eq!(Valued::H7 as u8, 67);
+    assert_eq!(Valued::Z as u8, 0);
+
+    assert_eq!(Valued::H8 as u16, 163);
+    assert_eq!(Valued::Z as u16, 0);
+    assert_eq!(Valued::H8 as u16, 163);
+    assert_eq!(Valued::Z as u16, 0);
+
+    assert_eq!(ValuedSigned::M1 as u16, 65535);
+    assert_eq!(ValuedSigned::M1 as i16, -1);
+    assert_eq!(ValuedSigned::P1 as u16, 1);
+    assert_eq!(ValuedSigned::P1 as i16, 1);
+
+    // prim-int-cast
+    assert_eq!(false as u16, 0);
+    assert_eq!(true as u16, 1);
+    assert_eq!(false as i64, 0);
+    assert_eq!(true as i64, 1);
+    assert_eq!('a' as u32, 0x61);
+    assert_eq!('a' as u16, 0x61);
+    assert_eq!('a' as u8, 0x61);
+    assert_eq!('א' as u8, 0xd0);
+    assert_eq!('א' as u16, 0x5d0);
+    assert_eq!('א' as u32, 0x5d0);
+    assert_eq!('🐵' as u8, 0x35);
+    assert_eq!('🐵' as u16, 0xf435);
+    assert_eq!('🐵' as u32, 0x1f435);
+    assert_eq!('英' as i16, -0x7d0f);
+    assert_eq!('英' as u16, 0x82f1);
+
+    // u8-char-cast
+    assert_eq!(0x61 as char, 'a');
+    assert_eq!(0u8 as char, '\0');
+    assert_eq!(0xd7 as char, '×');
+
+    // array-ptr-cast
+    let x = [1,2,3];
+    let first : *const u32 = &x[0];
+
+    assert_eq!(first, &x as *const _);
+    assert_eq!(first, &x as *const u32);
+
+    // fptr-addr-cast
+    fn foo() {
+        println!("foo!");
+    }
+    fn bar() {
+        println!("bar!");
+    }
+
+    assert!(foo as usize != bar as usize);
+
+    assert_eq!(foo as i16, foo as usize as i16);
+
+    // fptr-ptr-cast
+
+    assert_eq!(foo as *const u8 as usize, foo as usize);
+    assert!(foo as *const u32 != first);
+}
+fn foo() { }
index bda3b73e29c4927a3e7908253771e45732c40eb7..998f41259777111b2a96bf6c09cf55a10d3f91ad 100644 (file)
@@ -22,6 +22,6 @@ pub fn main() {
 
         //let bt1 = sys::frame_address();
         //println!("%?", bt1);
-        //assert!(bt0 == bt1);
+        //assert_eq!(bt0, bt1);
     })
 }
index 5b91af7a19431b2e364c48bf0e6bbc739aefdb18..4d9646522749cfe8b2f2321372c2754b39a189c0 100644 (file)
@@ -17,6 +17,6 @@ pub fn main() {
     //println!("%?", bt0);
     cci_iter_lib::iter(&[1, 2, 3], |i| {
         println!("{}", *i);
-        //assert!(bt0 == sys::rusti::frame_address(2));
+        //assert_eq!(bt0, sys::rusti::frame_address(2));
     })
 }
index 8408597f3540995a5cd19bd9d8c8e52c2659f869..9286991a4a38ac5a6cc77fc5f37b95c0a1db988b 100644 (file)
@@ -28,14 +28,14 @@ static cf: isize = af[2];
 
 fn main () {
     let b: &[isize] = &[1, 2, 3];
-    assert!(ac == b);
-    assert!(ad == b);
-    assert!(af == b);
+    assert_eq!(ac, b);
+    assert_eq!(ad, b);
+    assert_eq!(af, b);
 
-    assert!(ca == 1);
-    assert!(cb == 2);
-    assert!(cc == 3);
-    assert!(cd == 1);
-    assert!(ce == 2);
-    assert!(cf == 3);
+    assert_eq!(ca, 1);
+    assert_eq!(cb, 2);
+    assert_eq!(cc, 3);
+    assert_eq!(cd, 1);
+    assert_eq!(ce, 2);
+    assert_eq!(cf, 3);
 }
index 4c494293b517edbf83ca7de7439ebf42347a4844..27a57a888591556955e86166cc56aa6d0140f28c 100644 (file)
@@ -104,7 +104,7 @@ impl<T> cat<T> {
 pub fn main() {
     let mut nyan: cat<String> = cat::new(0, 2, "nyan".to_string());
     for _ in 1_usize..5 { nyan.speak(); }
-    assert!(*nyan.find(&1).unwrap() == "nyan".to_string());
+    assert_eq!(*nyan.find(&1).unwrap(), "nyan".to_string());
     assert_eq!(nyan.find(&10), None);
     let mut spotty: cat<cat_type> = cat::new(2, 57, cat_type::tuxedo);
     for _ in 0_usize..6 { spotty.speak(); }
index cd3f556864e64ae2c372d74c33e2005a3d50e8db..d4b570a4db654b41f07b6bff096d36834d9d6cbd 100644 (file)
@@ -13,6 +13,7 @@ use std::cmp::Ordering;
 
 // Test default methods in PartialOrd and PartialEq
 //
+#[derive(Debug)]
 struct Fool(bool);
 
 impl PartialEq for Fool {
@@ -74,8 +75,8 @@ pub fn main() {
     assert!(RevInt(1) >= RevInt(2));
     assert!(RevInt(1) >= RevInt(1));
 
-    assert!(Fool(true)  == Fool(false));
+    assert_eq!(Fool(true), Fool(false));
     assert!(Fool(true)  != Fool(true));
     assert!(Fool(false) != Fool(false));
-    assert!(Fool(false) == Fool(true));
+    assert_eq!(Fool(false), Fool(true));
 }
index 125aefe036dc621307a475926ac2997d7dd97483..33e5e054650005416c7cc928b4772b38790e2f48 100644 (file)
@@ -23,7 +23,7 @@ pub fn main() {
         _ => panic!()
     }
     match Y {
-        Foo::Bar(s) => assert!(s == 2654435769),
+        Foo::Bar(s) => assert_eq!(s, 2654435769),
         _ => panic!()
     }
     match Z {
index 6c8786dee6782b7feca49254121a56943b4aa1c3..a526e0be3da41378e95c833a075f9a35bf239e76 100644 (file)
@@ -19,6 +19,6 @@ static C: E = E::S1 { u: 23 };
 pub fn main() {
     match C {
         E::S0 { .. } => panic!(),
-        E::S1 { u } => assert!(u == 23)
+        E::S1 { u } => assert_eq!(u, 23)
     }
 }
index 2f1cd8dbf9b1213cd3f2fd68ec7a2c48f51050f6..56aec867f9d6bcefef7a01713038d6724d7925a4 100644 (file)
@@ -23,7 +23,7 @@ pub fn main() {
         _ => panic!()
     }
     match C1 {
-        E::V1(n) => assert!(n == 0xDEADBEE),
+        E::V1(n) => assert_eq!(n, 0xDEADBEE),
         _ => panic!()
     }
 
@@ -32,7 +32,7 @@ pub fn main() {
         _ => panic!()
     }
     match D1 {
-        E::V1(n) => assert!(n == 0xDEADBEE),
+        E::V1(n) => assert_eq!(n, 0xDEADBEE),
         _ => panic!()
     }
 }
index de94527a604867dd7ed87932f56f852e2f4a8c9a..0bd18a02e4a2da5cd6529d4bfb5ffd6e2c426fab 100644 (file)
@@ -14,7 +14,7 @@ static C: &'static [E] = &[E::V0, E::V1(0xDEADBEE), E::V0];
 
 pub fn main() {
     match C[1] {
-        E::V1(n) => assert!(n == 0xDEADBEE),
+        E::V1(n) => assert_eq!(n, 0xDEADBEE),
         _ => panic!()
     }
     match C[2] {
index 8d43a76bc28c314deaa1ea8ea82634d3f425fcf0..e7a6f520a9924a50c16ddf87901cd4e527aad6af 100644 (file)
@@ -14,7 +14,7 @@ static C: [E; 3] = [E::V0, E::V1(0xDEADBEE), E::V0];
 
 pub fn main() {
     match C[1] {
-        E::V1(n) => assert!(n == 0xDEADBEE),
+        E::V1(n) => assert_eq!(n, 0xDEADBEE),
         _ => panic!()
     }
     match C[2] {
diff --git a/src/test/run-pass/const-fn-cross-crate.rs b/src/test/run-pass/const-fn-cross-crate.rs
new file mode 100644 (file)
index 0000000..5d0c17a
--- /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:const_fn_lib.rs
+
+// A very basic test of const fn functionality.
+
+#![feature(const_fn)]
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+const FOO: usize = foo();
+
+fn main() {
+    assert_eq!(FOO, 22);
+}
diff --git a/src/test/run-pass/const-fn-method.rs b/src/test/run-pass/const-fn-method.rs
new file mode 100644 (file)
index 0000000..42c7a47
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#![feature(const_fn)]
+
+struct Foo { value: u32 }
+
+impl Foo {
+    const fn new() -> Foo {
+        Foo { value: 22 }
+    }
+}
+
+const FOO: Foo = Foo::new();
+
+pub fn main() {
+    assert_eq!(FOO.value, 22);
+}
diff --git a/src/test/run-pass/const-fn-nested.rs b/src/test/run-pass/const-fn-nested.rs
new file mode 100644 (file)
index 0000000..86f5ded
--- /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.
+
+// Test a call whose argument is the result of another call.
+
+#![feature(const_fn)]
+
+const fn sub(x: u32, y: u32) -> u32 {
+    x - y
+}
+
+const X: u32 = sub(sub(88, 44), 22);
+
+fn main() {
+    assert_eq!(X, 22);
+}
diff --git a/src/test/run-pass/const-fn.rs b/src/test/run-pass/const-fn.rs
new file mode 100644 (file)
index 0000000..9bd8eb5
--- /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.
+
+// A very basic test of const fn functionality.
+
+#![feature(const_fn)]
+
+const fn add(x: u32, y: u32) -> u32 {
+    x + y
+}
+
+const fn sub(x: u32, y: u32) -> u32 {
+    x - y
+}
+
+const SUM: u32 = add(44, 22);
+const DIFF: u32 = sub(44, 22);
+
+fn main() {
+    assert_eq!(SUM, 66);
+    assert!(SUM != 88);
+
+    assert_eq!(DIFF, 22);
+
+}
index 1cdb98a8bc05b36a65045594eca0e4117a1b1adc..93cae04a933010ae790723b1362e57501140eb64 100644 (file)
@@ -19,7 +19,7 @@ pub fn main() {
     unsafe {
         let foo = &A as *const u8;
         assert_eq!(str::from_utf8_unchecked(&A), "hi");
-        assert!(*C == A[0]);
-        assert!(*(&B[0] as *const u8) == A[0]);
+        assert_eq!(*C, A[0]);
+        assert_eq!(*(&B[0] as *const u8), A[0]);
     }
 }
diff --git a/src/test/run-pass/const-trait-to-trait.rs b/src/test/run-pass/const-trait-to-trait.rs
new file mode 100644 (file)
index 0000000..4b53e11
--- /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.
+
+// Issue #24644 - block causes a &Trait -> &Trait coercion:
+trait Trait {}
+
+struct Bar;
+impl Trait for Bar {}
+
+fn main() {
+    let x: &[&Trait] = &[{ &Bar }];
+}
+
+// Issue #25748 - the cast causes an &Encoding -> &Encoding coercion:
+pub struct UTF8Encoding;
+pub const UTF_8: &'static UTF8Encoding = &UTF8Encoding;
+pub trait Encoding {}
+impl Encoding for UTF8Encoding {}
+pub fn f() -> &'static Encoding { UTF_8 as &'static Encoding }
+
+// Root of the problem: &Trait -> &Trait coercions:
+const FOO: &'static Trait = &Bar;
+const BAR: &'static Trait = FOO;
+fn foo() { let _x = BAR; }
diff --git a/src/test/run-pass/deep-vector.rs b/src/test/run-pass/deep-vector.rs
deleted file mode 100644 (file)
index 2078578..0000000
+++ /dev/null
@@ -1,2016 +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.
-
-// ignore-test
-//
-// Too big for our poor macro infrastructure.
-
-pub fn main() {
-    let _x = vec!(
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    );
-}
diff --git a/src/test/run-pass/deep-vector2.rs b/src/test/run-pass/deep-vector2.rs
deleted file mode 100644 (file)
index 27258ed..0000000
+++ /dev/null
@@ -1,8016 +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.
-
-// ignore-test
-//
-// Too big for our poor macro infrastructure.
-
-pub fn main() {
-    let _x = vec!(
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    );
-}
index f8e690cf29e077f996a97895b11a1dd363053f2e..9ae4f2c1e70853cf887cab3b13e280e5b3adfdeb 100644 (file)
@@ -16,4 +16,4 @@ fn f(x: isize) -> isize {
     if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; }
 }
 
-pub fn main() { assert!((f(5000) == 5000)); }
+pub fn main() { assert_eq!(f(5000), 5000); }
diff --git a/src/test/run-pass/default-associated-types.rs b/src/test/run-pass/default-associated-types.rs
new file mode 100644 (file)
index 0000000..3e6c72c
--- /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.
+
+#![feature(associated_type_defaults)]
+
+trait Foo<T> {
+    type Out = T;
+    fn foo(&self) -> Self::Out;
+}
+
+impl Foo<u32> for () {
+    fn foo(&self) -> u32 {
+        4u32
+    }
+}
+
+impl Foo<u64> for bool {
+    type Out = ();
+    fn foo(&self) {}
+}
+
+fn main() {
+    assert_eq!(<() as Foo<u32>>::foo(&()), 4u32);
+    assert_eq!(<bool as Foo<u64>>::foo(&true), ());
+}
index b84d78b4f4fbdde76885fc30da909978d5246809..fa50e3144ed843d7413e6dadd43b127393f1eb8b 100644 (file)
@@ -13,5 +13,5 @@ use std::rc::Rc;
 
 fn main() {
     let x = Rc::new([1, 2, 3, 4]);
-    assert!(*x == [1, 2, 3, 4]);
+    assert_eq!(*x, [1, 2, 3, 4]);
 }
index 59eb5506c45c784184c0e88e2453dcb7d5b552f7..632ef5e0c8ad6b1eba099a638329304422b4a371 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core, debug_builders)]
+#![feature(core)]
 
 pub trait DeclaredTrait {
     type Type;
index db5a1f3f000a87e4946d432efd7b8f80f247ff9e..328cc134f3b1fdf17da835c24c68ad925169d447 100644 (file)
@@ -28,5 +28,5 @@ fn main() {
     let obj = A { foo: Box::new([true, false]) };
     let s = json::encode(&obj).unwrap();
     let obj2: A = json::decode(&s).unwrap();
-    assert!(obj.foo == obj2.foo);
+    assert_eq!(obj.foo, obj2.foo);
 }
index 7cc59edfcab0e98b9a86b8e16ba14740779de1ce..6e5eb86c584116ab287768b69d112726ebc516a7 100644 (file)
@@ -38,6 +38,6 @@ fn main() {
     };
     let s = json::encode(&obj).unwrap();
     let obj2: B = json::decode(&s).unwrap();
-    assert!(obj.foo.get() == obj2.foo.get());
-    assert!(obj.bar.borrow().baz == obj2.bar.borrow().baz);
+    assert_eq!(obj.foo.get(), obj2.foo.get());
+    assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz);
 }
diff --git a/src/test/run-pass/deriving-encodable-decodable.rs b/src/test/run-pass/deriving-encodable-decodable.rs
deleted file mode 100644 (file)
index cc6b88c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This actually tests a lot more than just encodable/decodable, but it gets the
-// job done at least
-
-// ignore-test FIXME(#5121)
-
-extern crate rand;
-extern crate rbml;
-extern crate serialize;
-
-use rand::{random, Rand};
-use rbml;
-use rbml::Doc;
-use rbml::writer::Encoder;
-use rbml::reader::Decoder;
-use serialize::{Encodable, Decodable};
-
-#[derive(Encodable, Decodable, Eq, Rand)]
-struct A;
-#[derive(Encodable, Decodable, Eq, Rand)]
-struct B(isize);
-#[derive(Encodable, Decodable, Eq, Rand)]
-struct C(isize, isize, usize);
-
-#[derive(Encodable, Decodable, Eq, Rand)]
-struct D {
-    a: isize,
-    b: usize,
-}
-
-#[derive(Encodable, Decodable, Eq, Rand)]
-enum E {
-    E1,
-    E2(usize),
-    E3(D),
-    E4{ x: usize },
-}
-
-#[derive(Encodable, Decodable, Eq, Rand)]
-enum F { F1 }
-
-#[derive(Encodable, Decodable, Eq, Rand)]
-struct G<T> {
-    t: T
-}
-
-fn roundtrip<'a, T: Rand + Eq + Encodable<Encoder<'a>> +
-                    Decodable<Decoder<'a>>>() {
-    let obj: T = random();
-    let mut w = Vec::new();
-    let mut e = Encoder::new(&mut w);
-    obj.encode(&mut e);
-    let doc = rbml::Doc::new(&w);
-    let mut dec = Decoder::new(doc);
-    let obj2 = Decodable::decode(&mut dec);
-    assert!(obj == obj2);
-}
-
-pub fn main() {
-    roundtrip::<A>();
-    roundtrip::<B>();
-    roundtrip::<C>();
-    roundtrip::<D>();
-
-    for _ in 0..20 {
-        roundtrip::<E>();
-        roundtrip::<F>();
-        roundtrip::<G<isize>>();
-    }
-}
index 03c93d3ab949b1efa06265c00e3989819f0b0bb1..f490cca6a699d7000ef578c4b6e4e58a666ffaec 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(PartialEq, PartialOrd, Eq, Ord)]
+#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)]
 struct Foo(Box<[u8]>);
 
 pub fn main() {
     // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
     let a = Foo(Box::new([0, 1, 2]));
     let b = Foo(Box::new([0, 1, 2]));
-    assert!(a == b);
+    assert_eq!(a, b);
     println!("{}", a != b);
     println!("{}", a < b);
     println!("{}", a <= b);
index 287750e5051c7b5a219e1d4c12f326d548600892..ba1d8228863ad6562a682ad5efbb902b1184622a 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-#![feature(hash)]
+#![feature(hash_default)]
 
 use std::hash::{Hash, SipHasher};
 
@@ -35,6 +35,6 @@ fn main() {
         name: "Bob".to_string(),
         phone: 555_666_7777
     };
-    assert!(hash(&person1) == hash(&person1));
+    assert_eq!(hash(&person1), hash(&person1));
     assert!(hash(&person1) != hash(&person2));
 }
diff --git a/src/test/run-pass/deriving-self-lifetime.rs b/src/test/run-pass/deriving-self-lifetime.rs
deleted file mode 100644 (file)
index 89771ed..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test FIXME #11820: & is unreliable in deriving
-
-#[derive(Eq,Ord)]
-struct A<'a> {
-    x: &'a isize
-}
-
-pub fn main() {
-    let a = A { x: &1 };
-    let b = A { x: &2 };
-
-    assert_eq!(a, a);
-    assert_eq!(b, b);
-
-
-    assert!(a < b);
-    assert!(b > a);
-
-    assert!(a <= b);
-    assert!(a <= a);
-    assert!(b <= b);
-
-    assert!(b >= a);
-    assert!(b >= b);
-    assert!(a >= a);
-}
index f9e1ea4a62384f979e17f625052a4272abe22a12..9dffac00a2274c26a47aa287bbeb7013e41661ee 100644 (file)
@@ -16,8 +16,8 @@ pub fn main() {
   let a2 = Foo(5, 6, "abc".to_string());
   let b = Foo(5, 7, "def".to_string());
 
-  assert!(a1 == a1);
-  assert!(a2 == a1);
+  assert_eq!(a1, a1);
+  assert_eq!(a2, a1);
   assert!(!(a1 == b));
 
   assert!(a1 != b);
index 217e696f0953884879229a36d46857bd5c66053e..13257529ed9f860eaaae4d975ef1b7f552f492f2 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(core, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::discriminant_value;
index aa28ae00e2772e4ffff21518b8f9cbe023bfad7d..6eb01e879df5735ec133e763a04e7b0c3c20f3af 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test a very simple custom DST coercion.
 
-#![feature(core)]
+#![feature(unsize, coerce_unsized)]
 
 use std::ops::CoerceUnsized;
 use std::marker::Unsize;
index 32e7a6279c858a197970d9c7b6310094d25bf796..67dd4021cb5c8dd65ae347ec635c2858c4bbc6a6 100644 (file)
@@ -12,6 +12,7 @@
 
 #![feature(core)]
 
+use std::cell::RefCell;
 use std::rc::Rc;
 
 trait Baz {
@@ -36,4 +37,8 @@ fn main() {
     assert_eq!(b.get(), 42);
 
     let _c = b.clone();
+
+    let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
+    let b: Rc<RefCell<Baz>> = a.clone();
+    assert_eq!(b.borrow().get(), 42);
 }
index b031c82a07f3dec35d9d9f147dda252ada8fc9e2..0666e41738e3c88410e3702300d2cc12615999ff 100644 (file)
@@ -33,9 +33,9 @@ impl DerefMut for Arr {
 
 pub fn foo(arr: &mut Arr) {
     let x: &mut [usize] = &mut **arr;
-    assert!(x[0] == 1);
-    assert!(x[1] == 2);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 2);
+    assert_eq!(x[2], 3);
 }
 
 fn main() {
index c4666d05fbfe36758b7fccb867c6764aa34a7ff2..957ed13a3d8175009f2563dce6269afd5675c504 100644 (file)
@@ -26,11 +26,11 @@ impl Deref for Arr {
 }
 
 pub fn foo(arr: &Arr) {
-    assert!(arr.len() == 3);
+    assert_eq!(arr.len(), 3);
     let x: &[usize] = &**arr;
-    assert!(x[0] == 1);
-    assert!(x[1] == 2);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 2);
+    assert_eq!(x[2], 3);
 }
 
 fn main() {
index d899de9164071f23adfb7b3b4a500810fa4a3536..3a74626b0299f2be8af8229e70da2ad5ded479db 100644 (file)
@@ -35,7 +35,7 @@ pub fn main() {
     let r = unsafe {
         (&*z).foo()
     };
-    assert!(r == 42);
+    assert_eq!(r, 42);
 
     // raw DST struct
     let p = Foo {f: A { f: 42 }};
@@ -43,33 +43,33 @@ pub fn main() {
     let r = unsafe {
         (&*o).f.foo()
     };
-    assert!(r == 42);
+    assert_eq!(r, 42);
 
     // raw slice
     let a: *const [_] = &[1, 2, 3];
     unsafe {
         let b = (*a)[2];
-        assert!(b == 3);
+        assert_eq!(b, 3);
         let len = (*a).len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 
     // raw slice with explicit cast
     let a = &[1, 2, 3] as *const [i32];
     unsafe {
         let b = (*a)[2];
-        assert!(b == 3);
+        assert_eq!(b, 3);
         let len = (*a).len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 
     // raw DST struct with slice
     let c: *const Foo<[_]> = &Foo {f: [1, 2, 3]};
     unsafe {
         let b = (&*c).f[0];
-        assert!(b == 1);
+        assert_eq!(b, 1);
         let len = (&*c).f.len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 
     // all of the above with *mut
@@ -78,36 +78,36 @@ pub fn main() {
     let r = unsafe {
         (&*z).foo()
     };
-    assert!(r == 42);
+    assert_eq!(r, 42);
 
     let mut p = Foo {f: A { f: 42 }};
     let o: *mut Foo<Trait> = &mut p;
     let r = unsafe {
         (&*o).f.foo()
     };
-    assert!(r == 42);
+    assert_eq!(r, 42);
 
     let a: *mut [_] = &mut [1, 2, 3];
     unsafe {
         let b = (*a)[2];
-        assert!(b == 3);
+        assert_eq!(b, 3);
         let len = (*a).len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 
     let a = &mut [1, 2, 3] as *mut [i32];
     unsafe {
         let b = (*a)[2];
-        assert!(b == 3);
+        assert_eq!(b, 3);
         let len = (*a).len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 
     let c: *mut Foo<[_]> = &mut Foo {f: [1, 2, 3]};
     unsafe {
         let b = (&*c).f[0];
-        assert!(b == 1);
+        assert_eq!(b, 1);
         let len = (&*c).f.len();
-        assert!(len == 3);
+        assert_eq!(len, 3);
     }
 }
index c5da5fc0c1a5e620fff5a1bf5e7e608ac3d331fe..58d7b35a5275cc2de0351d2e97ecd6342818c05d 100644 (file)
@@ -18,20 +18,20 @@ struct Fat<T: ?Sized> {
 // x is a fat pointer
 fn foo(x: &Fat<[isize]>) {
     let y = &x.ptr;
-    assert!(x.ptr.len() == 3);
-    assert!(y[0] == 1);
-    assert!(x.ptr[1] == 2);
+    assert_eq!(x.ptr.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!(x.ptr[1], 2);
 }
 
 fn foo2<T:ToBar>(x: &Fat<[T]>) {
     let y = &x.ptr;
     let bar = Bar;
-    assert!(x.ptr.len() == 3);
-    assert!(y[0].to_bar() == bar);
-    assert!(x.ptr[1].to_bar() == bar);
+    assert_eq!(x.ptr.len(), 3);
+    assert_eq!(y[0].to_bar(), bar);
+    assert_eq!(x.ptr[1].to_bar(), bar);
 }
 
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 struct Bar;
 
 trait ToBar {
@@ -73,9 +73,9 @@ pub fn main() {
     // Assignment.
     let f5: &mut Fat<[isize]> = &mut Fat { ptr: [1, 2, 3] };
     f5.ptr[1] = 34;
-    assert!(f5.ptr[0] == 1);
-    assert!(f5.ptr[1] == 34);
-    assert!(f5.ptr[2] == 3);
+    assert_eq!(f5.ptr[0], 1);
+    assert_eq!(f5.ptr[1], 34);
+    assert_eq!(f5.ptr[2], 3);
 
     // Zero size vec.
     let f5: &Fat<[isize]> = &Fat { ptr: [] };
index 92253d815958d0e223c869b182fdeb51e6c6e2bd..94efa7a256b4d0cf0c1d6c638ad5611aaa001763 100644 (file)
@@ -21,36 +21,36 @@ struct Fat<T: ?Sized> {
 // x is a fat pointer
 fn foo(x: &Fat<[isize]>) {
     let y = &x.ptr;
-    assert!(x.ptr.len() == 3);
-    assert!(y[0] == 1);
-    assert!(x.ptr[1] == 2);
-    assert!(x.f1 == 5);
-    assert!(x.f2 == "some str");
+    assert_eq!(x.ptr.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!(x.ptr[1], 2);
+    assert_eq!(x.f1, 5);
+    assert_eq!(x.f2, "some str");
 }
 
 fn foo2<T:ToBar>(x: &Fat<[T]>) {
     let y = &x.ptr;
     let bar = Bar;
-    assert!(x.ptr.len() == 3);
-    assert!(y[0].to_bar() == bar);
-    assert!(x.ptr[1].to_bar() == bar);
-    assert!(x.f1 == 5);
-    assert!(x.f2 == "some str");
+    assert_eq!(x.ptr.len(), 3);
+    assert_eq!(y[0].to_bar(), bar);
+    assert_eq!(x.ptr[1].to_bar(), bar);
+    assert_eq!(x.f1, 5);
+    assert_eq!(x.f2, "some str");
 }
 
 fn foo3(x: &Fat<Fat<[isize]>>) {
     let y = &x.ptr.ptr;
-    assert!(x.f1 == 5);
-    assert!(x.f2 == "some str");
-    assert!(x.ptr.f1 == 8);
-    assert!(x.ptr.f2 == "deep str");
-    assert!(x.ptr.ptr.len() == 3);
-    assert!(y[0] == 1);
-    assert!(x.ptr.ptr[1] == 2);
+    assert_eq!(x.f1, 5);
+    assert_eq!(x.f2, "some str");
+    assert_eq!(x.ptr.f1, 8);
+    assert_eq!(x.ptr.f2, "deep str");
+    assert_eq!(x.ptr.ptr.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!(x.ptr.ptr[1], 2);
 }
 
 
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 struct Bar;
 
 trait ToBar {
@@ -92,9 +92,9 @@ pub fn main() {
     // Assignment.
     let f5: &mut Fat<[isize]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
     f5.ptr[1] = 34;
-    assert!(f5.ptr[0] == 1);
-    assert!(f5.ptr[1] == 34);
-    assert!(f5.ptr[2] == 3);
+    assert_eq!(f5.ptr[0], 1);
+    assert_eq!(f5.ptr[1], 34);
+    assert_eq!(f5.ptr[2], 3);
 
     // Zero size vec.
     let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [] };
@@ -117,9 +117,9 @@ pub fn main() {
 
     // Box.
     let f1 = Box::new([1, 2, 3]);
-    assert!((*f1)[1] == 2);
+    assert_eq!((*f1)[1], 2);
     let f2: Box<[isize]> = f1;
-    assert!((*f2)[1] == 2);
+    assert_eq!((*f2)[1], 2);
 
     // Nested Box.
     let f1 : Box<Fat<[isize; 3]>> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
index 4d2b50c08e2f508e2b03ed7e1426a6586e0e4e9b..9d12a4a34b7d4a1c5ca7c688ba5e019b0d94b529 100644 (file)
@@ -18,7 +18,7 @@ struct Fat<T: ?Sized> {
     ptr: T
 }
 
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 struct Bar;
 
 #[derive(Copy, Clone, PartialEq, Eq)]
@@ -50,32 +50,32 @@ impl ToBar for Bar1 {
 
 // x is a fat pointer
 fn foo(x: &Fat<ToBar>) {
-    assert!(x.f1 == 5);
-    assert!(x.f2 == "some str");
-    assert!(x.ptr.to_bar() == Bar);
-    assert!(x.ptr.to_val() == 42);
+    assert_eq!(x.f1, 5);
+    assert_eq!(x.f2, "some str");
+    assert_eq!(x.ptr.to_bar(), Bar);
+    assert_eq!(x.ptr.to_val(), 42);
 
     let y = &x.ptr;
-    assert!(y.to_bar() == Bar);
-    assert!(y.to_val() == 42);
+    assert_eq!(y.to_bar(), Bar);
+    assert_eq!(y.to_val(), 42);
 }
 
 fn bar(x: &ToBar) {
-    assert!(x.to_bar() == Bar);
-    assert!(x.to_val() == 42);
+    assert_eq!(x.to_bar(), Bar);
+    assert_eq!(x.to_val(), 42);
 }
 
 fn baz(x: &Fat<Fat<ToBar>>) {
-    assert!(x.f1 == 5);
-    assert!(x.f2 == "some str");
-    assert!(x.ptr.f1 == 8);
-    assert!(x.ptr.f2 == "deep str");
-    assert!(x.ptr.ptr.to_bar() == Bar);
-    assert!(x.ptr.ptr.to_val() == 42);
+    assert_eq!(x.f1, 5);
+    assert_eq!(x.f2, "some str");
+    assert_eq!(x.ptr.f1, 8);
+    assert_eq!(x.ptr.f2, "deep str");
+    assert_eq!(x.ptr.ptr.to_bar(), Bar);
+    assert_eq!(x.ptr.ptr.to_val(), 42);
 
     let y = &x.ptr.ptr;
-    assert!(y.to_bar() == Bar);
-    assert!(y.to_val() == 42);
+    assert_eq!(y.to_bar(), Bar);
+    assert_eq!(y.to_val(), 42);
 
 }
 
@@ -93,7 +93,7 @@ pub fn main() {
 
     // Zero size object.
     let f6: &Fat<ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar };
-    assert!(f6.ptr.to_bar() == Bar);
+    assert_eq!(f6.ptr.to_bar(), Bar);
 
     // &*
     //
index 1ff6370136076e76e800ce68c773a6f9ebdabc95..fafd8b576ff0fc467ee274678f4ef01cdba2b3c9 100644 (file)
@@ -26,6 +26,6 @@ enum Hero {
 pub fn main() {
     let pet: Animal = Animal::Snake;
     let hero: Hero = Hero::Superman;
-    assert!(pet as usize == 3);
-    assert!(hero as isize == -2);
+    assert_eq!(pet as usize, 3);
+    assert_eq!(hero as isize, -2);
 }
index cf66725178011f4521cdbbe1c96990785d079471..425d8f6d651ccab3023dc55895e22495ff12d4fb 100644 (file)
@@ -21,5 +21,5 @@ pub fn main() {
 }
 
 fn test_color(color: color, val: isize, _name: String) {
-    assert!(color as isize == val);
+    assert_eq!(color as isize , val);
 }
index 499d131947a38027d210bf4df73653aa7ac4563a..dd88dc11ea70e47a11dd25b8c11970f4716cac23 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(core)]
+#![feature(nonzero, core)]
 
 extern crate core;
 
index efe72729817e8fb9da9b31eb0ebebf23a3d26903..2110f0b3bf9d607caef7cae98c8532033e41340d 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
     let oldhome = var("HOME");
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
+    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
     remove_var("HOME");
     if cfg!(target_os = "android") {
@@ -40,14 +40,14 @@ fn main() {
     assert!(home_dir().is_some());
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
+    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
     remove_var("HOME");
 
     set_var("USERPROFILE", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
+    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 
     set_var("HOME", "/home/MountainView");
     set_var("USERPROFILE", "/home/PaloAlto");
-    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
+    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
 }
index bf8b089a830c2c662eb2d9dcbe253950679b704e..ca37ee28bcbc2ea11a9bcd7d4133a6338aef090a 100644 (file)
@@ -9,10 +9,13 @@
 // except according to those terms.
 
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 struct Bar;
+#[derive(Debug)]
 struct Baz;
+#[derive(Debug)]
 struct Foo;
+#[derive(Debug)]
 struct Fu;
 
 impl PartialEq for Baz { fn eq(&self, _: &Baz) -> bool  { true } }
@@ -27,10 +30,10 @@ fn main() {
     assert!(Bar != Foo);
     assert!(Foo != Bar);
 
-    assert!(Bar == Bar);
+    assert_eq!(Bar, Bar);
 
-    assert!(Baz == Baz);
+    assert_eq!(Baz, Baz);
 
-    assert!(Foo == Fu);
-    assert!(Fu == Foo);
+    assert_eq!(Foo, Fu);
+    assert_eq!(Fu, Foo);
 }
diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs
deleted file mode 100644 (file)
index b3771f3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-
-// Doesn't work; needs a design decision.
-
-pub fn main() {
-    let x : [isize; 5] = [1,2,3,4,5];
-    let _y : [isize; 5] = [1,2,3,4,5];
-    let mut z = [1,2,3,4,5];
-    z = x;
-    assert_eq!(z[0], 1);
-    assert_eq!(z[4], 5);
-
-    let a : [isize; 5] = [1,1,1,1,1];
-    let b : [isize; 5] = [2,2,2,2,2];
-    let c : [isize; 5] = [2,2,2,2,3];
-
-    log(debug, a);
-
-    assert!(a < b);
-    assert!(a <= b);
-    assert!(a != b);
-    assert!(b >= a);
-    assert!(b > a);
-
-    log(debug, b);
-
-    assert!(b < c);
-    assert!(b <= c);
-    assert!(b != c);
-    assert!(c >= b);
-    assert!(c > b);
-
-    assert!(a < c);
-    assert!(a <= c);
-    assert!(a != c);
-    assert!(c >= a);
-    assert!(c > a);
-
-    log(debug, c);
-
-
-}
index 67e41aad6971b63f4d217071bff2fa83afe2b5ad..32641c4a3f2c968127a16cfc756f2bf4953cf723 100644 (file)
@@ -14,7 +14,7 @@
 fn test_fn() {
     fn ten() -> isize { return 10; }
     let rs = ten;
-    assert!((rs() == 10));
+    assert_eq!(rs(), 10);
 }
 
 pub fn main() { test_fn(); }
index 7ad024186015b70c600cf7ddcb76a45ea5078d80..eb24d70de90f6c5d6fa14c503bb70723f941f90d 100644 (file)
@@ -13,4 +13,4 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-pub fn main() { let x: Box<_> = { box 100 }; assert!((*x == 100)); }
+pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); }
index 38be041938b3c3875762b31207f059c7a5823748..664555caf26bb944163e88cd2e9e7bc5f9ad7468 100644 (file)
@@ -18,7 +18,7 @@ fn test_basic() { let rs: bool = { true }; assert!((rs)); }
 
 struct RS { v1: isize, v2: isize }
 
-fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert!((rs.v2 == 20)); }
+fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert_eq!(rs.v2, 20); }
 
 fn test_filled_with_stuff() {
     let rs = { let mut a = 0; while a < 10 { a += 1; } a };
index c7f10b66ca3c77489fee58d3e755816c27f53970..1bedc2a5a17073810f7876ef1b924ad6b4d9c202 100644 (file)
@@ -11,7 +11,7 @@
 
 fn test_if_panic() {
     let x = if false { panic!() } else { 10 };
-    assert!((x == 10));
+    assert_eq!(x, 10);
 }
 
 fn test_else_panic() {
index 3474e2eefb7c7cba8933faafe3b538914125c542..5ab6c7774d55cf3a83c3012fe4ef9a8db6f9393f 100644 (file)
@@ -16,9 +16,9 @@ use std::cell::Cell;
 struct Point {x: isize, y: isize, z: isize}
 
 fn f(p: &Cell<Point>) {
-    assert!((p.get().z == 12));
+    assert_eq!(p.get().z, 12);
     p.set(Point {x: 10, y: 11, z: 13});
-    assert!((p.get().z == 13));
+    assert_eq!(p.get().z, 13);
 }
 
 pub fn main() {
index b7513da99c806eb26372abe6a77c6d1ae1e419f0..58296c3f95ef923be7397c58f13bdc35b91e4172 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(raw)]
 
 use std::mem;
 use std::raw;
@@ -26,24 +26,24 @@ fn main() {
     let a: *const [i32] = &[1, 2, 3];
     let b = a as *const [i32; 2];
     unsafe {
-        assert!(*b == [1, 2]);
+        assert_eq!(*b, [1, 2]);
     }
 
     // Test conversion to an address (usize).
     let a: *const [i32; 3] = &[1, 2, 3];
     let b: *const [i32] = a;
-    assert!(a as usize == b as usize);
+    assert_eq!(a as usize, b as *const () as usize);
 
     // And conversion to a void pointer/address for trait objects too.
     let a: *mut Foo = &mut Bar;
     let b = a as *mut ();
-    let c = a as usize;
-
+    let c = a as *const () as usize;
     let d = unsafe {
         let r: raw::TraitObject = mem::transmute(a);
         r.data
     };
 
-    assert!(b == d);
-    assert!(c == d as usize);
+    assert_eq!(b, d);
+    assert_eq!(c, d as usize);
+
 }
index 6deaec1905960abf1d8fb1ecf7e4bd4dd4fe8cba..a1bd77a74f725593f790465714c52d9f81765341 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(lang_items, start, no_std, core, collections)]
+#![feature(lang_items, start, no_std, core_slice_ext, core, collections)]
 #![no_std]
 
 extern crate std as other;
index bfc0d6cf9d542729ff573db0751746f6e8fb3e12..e63c29eb0173a6f6f0086cb307bc1aaf4edbfbd3 100644 (file)
@@ -18,5 +18,5 @@ pub fn main() {
         }
         y += *i;
     }
-    assert!(y == 11);
+    assert_eq!(y, 11);
 }
index 87aa3d84003c527d7f751605889264d1871db977..ea55c90bdf12db1dce0df7ae9db1c3cf8940c9cd 100644 (file)
@@ -20,5 +20,5 @@ pub fn main() {
         }
         q += *i + p;
     }
-    assert!(q == 1010100);
+    assert_eq!(q, 1010100);
 }
index d1fe98f5431f751d7b8f3b93dd36725f49c202e4..9b847517ec8fb9536f6fde982eb62b58903fcc54 100644 (file)
@@ -15,5 +15,5 @@ pub fn main() {
     for i in &x[..] {
         y += *i
     }
-    assert!(y == 100);
+    assert_eq!(y, 100);
 }
index 9204cdfd755b63ab552a85b88e8e1782b0274ca4..1452cefbd5c2ba18e70435025232ac4417504df5 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
 #![feature(lang_items, start, no_std, core, collections)]
 #![no_std]
 
index 181e05183d2ec0dde117b4c29473cd4616f8ffaf..bff86207f7862f841255d8571b442ee854a58da3 100644 (file)
@@ -16,4 +16,4 @@
 
 fn id<T>(x: T) -> T { return x; }
 
-pub fn main() { let x: isize = 42; let y: isize = id(x); assert!((x == y)); }
+pub fn main() { let x: isize = 42; let y: isize = id(x); assert_eq!(x, y); }
index fef26593eac873dba06a4249883d7fee61f2d4a0..1acb23209009eabdad6db4e8d409a96e7b5d6a43 100644 (file)
@@ -14,7 +14,7 @@ struct Pair { x: isize, y: isize }
 
 pub fn main() {
     let nop: noption<isize> = noption::some::<isize>(5);
-    match nop { noption::some::<isize>(n) => { println!("{}", n); assert!((n == 5)); } }
+    match nop { noption::some::<isize>(n) => { println!("{}", n); assert_eq!(n, 5); } }
     let nop2: noption<Pair> = noption::some(Pair{x: 17, y: 42});
     match nop2 {
       noption::some(t) => {
index 8b63fb94b52ee1af23fde8b630ac737fc622de92..80a6efe7a0ef9e13ecf5746473b63a52e4536e88 100644 (file)
@@ -11,7 +11,7 @@
 
 fn mk() -> isize { return 1; }
 
-fn chk(a: isize) { println!("{}", a); assert!((a == 1)); }
+fn chk(a: isize) { println!("{}", a); assert_eq!(a, 1); }
 
 fn apply<T>(produce: fn() -> T,
             consume: fn(T)) {
index 13da404c253b34e855bc45a11eda3ae65b46dee2..8e155c459965db3fe56f53bf7f1efac560a14ed8 100644 (file)
@@ -14,7 +14,10 @@ pub fn f() -> isize { return 1; }
 
 pub mod foo {
     pub fn f() -> isize { return 2; }
-    pub fn g() { assert!((f() == 2)); assert!((::f() == 1)); }
+    pub fn g() {
+        assert_eq!(f(), 2);
+        assert_eq!(::f(), 1);
+    }
 }
 
 pub fn main() { return foo::g(); }
index 23970af957655f88019c3e924409535f93c936eb..a9cfe7a38026189e473d6ff94edc5b7c22e1acd8 100644 (file)
@@ -10,8 +10,6 @@
 
 // A test of the macro system. Can we do HTML literals?
 
-// ignore-test FIXME #20673
-
 /*
 
 This is an HTML parser written as a macro. It's all CPS, and we have
index 075faba2fcb85fd1b57bc0a2f7166b7a740b886e..143787a466b80ebadc4a32be051350c46b968961 100644 (file)
@@ -12,4 +12,4 @@
 
 
 
-pub fn main() { let mut x: i32 = -400; x = 0 - x; assert!((x == 400)); }
+pub fn main() { let mut x: i32 = -400; x = 0 - x; assert_eq!(x, 400); }
index 240b6286c8cfc64d43f03d3c9cad0b3b96dc0660..c8adb6ccc0ab8598379bbf2388d27c04d206871c 100644 (file)
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-use std::fmt;
+use std::fmt::{self, Write};
 use std::usize;
 
 struct A;
 struct B;
 struct C;
+struct D;
 
 impl fmt::LowerHex for A {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -37,6 +38,13 @@ impl fmt::Display for C {
         f.pad_integral(true, "☃", "123")
     }
 }
+impl fmt::Binary for D {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(f.write_str("aa"));
+        try!(f.write_char('☃'));
+        f.write_str("bb")
+    }
+}
 
 macro_rules! t {
     ($a:expr, $b:expr) => { assert_eq!($a, $b) }
@@ -90,6 +98,7 @@ pub fn main() {
     t!(format!("{foo_bar}", foo_bar=1), "1");
     t!(format!("{}", 5 + 5), "10");
     t!(format!("{:#4}", C), "☃123");
+    t!(format!("{:b}", D), "aa☃bb");
 
     let a: &fmt::Debug = &1;
     t!(format!("{:?}", a), "1");
diff --git a/src/test/run-pass/infinite-loops.rs b/src/test/run-pass/infinite-loops.rs
deleted file mode 100644 (file)
index e8c5996..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*
-  A simple way to make sure threading works. This should use all the
-  CPU cycles an any machines that we're likely to see for a while.
-*/
-// ignore-test
-
-fn loopy(n: isize) {
-    if n > 0 { spawn(move|| { loopy(n - 1) }); spawn(move|| { loopy(n - 1) }); }
-    loop { }
-}
-
-pub fn main() {
-    // Commenting this out, as this will hang forever otherwise.
-    // Even after seeing the comment above, I'm not sure what the
-    // intention of this test is.
-    // spawn(move|| { loopy(5) });
-}
index 9ccf1c3bbb80381be78e003fcc9e477a8f2ac33d..7ec18ef127690645382d8983f062ec8a6bf6c171 100644 (file)
 
 // pretty-expanded FIXME #23616
 
-#![feature(core)]
-
-use std::u8;
-
 trait IntoIterator {
     type Iter: Iterator;
 
@@ -35,7 +31,7 @@ impl<I> IntoIterator for I where I: Iterator {
 
 fn desugared_for_loop_bad(byte: u8) -> u8 {
     let mut result = 0;
-    let mut x = IntoIterator::into_iter(0..u8::BITS);
+    let mut x = IntoIterator::into_iter(0..8);
     let mut y = Iterator::next(&mut x);
     let mut z = y.unwrap();
     byte >> z;
index ff7d799f64c5f3dbfa634ba781259efd51736ea7..41ef62b0ced3d7e24285e50513ca44ce0bf06b26 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(core)]
+#![feature(core_intrinsics)]
 
 use std::intrinsics::assume;
 
diff --git a/src/test/run-pass/intrinsic-move-val-cleanups.rs b/src/test/run-pass/intrinsic-move-val-cleanups.rs
new file mode 100644 (file)
index 0000000..9fd4f21
--- /dev/null
@@ -0,0 +1,194 @@
+// 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 is checking that the move_val_init intrinsic is
+// respecting cleanups for both of its argument expressions.
+//
+// In other words, if either DEST or SOURCE in
+//
+//   `intrinsics::move_val_init(DEST, SOURCE)
+//
+// introduce temporaries that require cleanup, and SOURCE panics, then
+// make sure the cleanups still occur.
+
+#![feature(core_intrinsics, sync_poison)]
+
+use std::cell::RefCell;
+use std::intrinsics;
+use std::sync::{Arc, LockResult, Mutex, MutexGuard};
+use std::thread;
+
+type LogEntry = (&'static str, i32);
+type Guarded = RefCell<Vec<LogEntry>>;
+#[derive(Clone)]
+struct Log(Arc<Mutex<Guarded>>);
+struct Acquired<'a>(MutexGuard<'a, Guarded>);
+type LogState = (MutexWas, &'static [LogEntry]);
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum MutexWas { Poisoned, NotPoisoned }
+
+impl Log {
+    fn lock(&self) -> LockResult<MutexGuard<RefCell<Vec<LogEntry>>>> { self.0.lock() }
+    fn acquire(&self) -> Acquired { Acquired(self.0.lock().unwrap()) }
+}
+
+impl<'a> Acquired<'a> {
+    fn log(&self, s: &'static str, i: i32) { self.0.borrow_mut().push((s, i)); }
+}
+
+const TEST1_EXPECT: LogState = (MutexWas::NotPoisoned,
+                                &[("double-check non-poisoning path", 1)
+                                  ]);
+
+fn test1(log: Log) {
+    {
+        let acq = log.acquire();
+        acq.log("double-check non-poisoning path", 1);
+    }
+    panic!("every test ends in a panic");
+}
+
+const TEST2_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("double-check poisoning path", 1),
+                                  ("and multiple log entries", 2),
+                                  ]);
+fn test2(log: Log) {
+    let acq = log.acquire();
+    acq.log("double-check poisoning path", 1);
+    acq.log("and multiple log entries", 2);
+    panic!("every test ends in a panic");
+}
+
+struct LogOnDrop<'a>(&'a Acquired<'a>, &'static str, i32);
+impl<'a> Drop for LogOnDrop<'a> {
+    fn drop(&mut self) {
+        self.0.log(self.1, self.2);
+    }
+}
+
+const TEST3_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("double-check destructors can log", 1),
+                                  ("drop d2", 2),
+                                  ("drop d1", 3),
+                                  ]);
+fn test3(log: Log) {
+    let acq = log.acquire();
+    acq.log("double-check destructors can log", 1);
+    let _d1 = LogOnDrop(&acq, "drop d1", 3);
+    let _d2 = LogOnDrop(&acq, "drop d2", 2);
+    panic!("every test ends in a panic");
+}
+
+// The *real* tests of panic-handling for move_val_init intrinsic
+// start here.
+
+const TEST4_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("neither arg panics", 1),
+                                  ("drop temp LOD", 2),
+                                  ("drop temp LOD", 3),
+                                  ("drop dest_b", 4),
+                                  ("drop dest_a", 5),
+                                  ]);
+fn test4(log: Log) {
+    let acq = log.acquire();
+    acq.log("neither arg panics", 1);
+    let mut dest_a = LogOnDrop(&acq, "a will be overwritten, not dropped", 0);
+    let mut dest_b = LogOnDrop(&acq, "b will be overwritten, not dropped", 0);
+    unsafe {
+        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
+                                  LogOnDrop(&acq, "drop dest_a", 5));
+        intrinsics::move_val_init(&mut dest_b, { LogOnDrop(&acq, "drop temp LOD", 3);
+                                                 LogOnDrop(&acq, "drop dest_b", 4) });
+    }
+    panic!("every test ends in a panic");
+}
+
+
+// Check that move_val_init(PANIC, SOURCE_EXPR) never evaluates SOURCE_EXPR
+const TEST5_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("first arg panics", 1),
+                                  ("drop orig dest_a", 2),
+                                  ]);
+fn test5(log: Log) {
+    let acq = log.acquire();
+    acq.log("first arg panics", 1);
+    let mut _dest_a = LogOnDrop(&acq, "drop orig dest_a", 2);
+    unsafe {
+        intrinsics::move_val_init({ panic!("every test ends in a panic") },
+                                  LogOnDrop(&acq, "we never get here", 0));
+    }
+}
+
+// Check that move_val_init(DEST_EXPR, PANIC) cleans up temps from DEST_EXPR.
+const TEST6_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("second arg panics", 1),
+                                  ("drop temp LOD", 2),
+                                  ("drop orig dest_a", 3),
+                                  ]);
+fn test6(log: Log) {
+    let acq = log.acquire();
+    acq.log("second arg panics", 1);
+    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 3);
+    unsafe {
+        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
+                                  { panic!("every test ends in a panic"); });
+    }
+}
+
+// Check that move_val_init(DEST_EXPR, COMPLEX_PANIC) cleans up temps from COMPLEX_PANIC.
+const TEST7_EXPECT: LogState = (MutexWas::Poisoned,
+                                &[("second arg panics", 1),
+                                  ("drop temp LOD", 2),
+                                  ("drop temp LOD", 3),
+                                  ("drop orig dest_a", 4),
+                                  ]);
+fn test7(log: Log) {
+    let acq = log.acquire();
+    acq.log("second arg panics", 1);
+    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 4);
+    unsafe {
+        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
+                                  { LogOnDrop(&acq, "drop temp LOD", 3);
+                                    panic!("every test ends in a panic"); });
+    }
+}
+
+const TEST_SUITE: &'static [(&'static str, fn (Log), LogState)] =
+    &[("test1", test1, TEST1_EXPECT),
+      ("test2", test2, TEST2_EXPECT),
+      ("test3", test3, TEST3_EXPECT),
+      ("test4", test4, TEST4_EXPECT),
+      ("test5", test5, TEST5_EXPECT),
+      ("test6", test6, TEST6_EXPECT),
+      ("test7", test7, TEST7_EXPECT),
+      ];
+
+fn main() {
+    for &(name, test, expect) in TEST_SUITE {
+        let log = Log(Arc::new(Mutex::new(RefCell::new(Vec::new()))));
+        let ret = { let log = log.clone(); thread::spawn(move || test(log)).join() };
+        assert!(ret.is_err(), "{} must end with panic", name);
+        {
+            let l = log.lock();
+            match l {
+                Ok(acq) => {
+                    assert_eq!((MutexWas::NotPoisoned, &acq.borrow()[..]), expect);
+                    println!("{} (unpoisoned) log: {:?}", name, *acq);
+                }
+                Err(e) => {
+                    let acq = e.into_inner();
+                    assert_eq!((MutexWas::Poisoned, &acq.borrow()[..]), expect);
+                    println!("{} (poisoned) log: {:?}", name, *acq);
+                }
+            }
+        }
+    }
+}
index a86fc110ae4eba4a085d216e54f488864ebf4c56..0ce446e445c73d9565c000f90a6013739e3630ea 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(core)]
+#![feature(core_intrinsics)]
 
 use std::intrinsics;
 
index 37ceaae373b9468a0c6392493be126d533b372af..f547519b671f1e28e04f16fb59f7a664287f0548 100644 (file)
@@ -102,13 +102,13 @@ pub fn main() {
 
         // Causes linker error
         // undefined reference to llvm.ceil.f32/64
-        //assert!((ceilf32(-2.3f32) == -2.0f32));
-        //assert!((ceilf64(3.8f64) == 4.0f64));
+        //assert_eq!(ceilf32(-2.3f32), -2.0f32);
+        //assert_eq!(ceilf64(3.8f64), 4.0f64);
 
         // Causes linker error
         // undefined reference to llvm.trunc.f32/64
-        //assert!((truncf32(0.1f32) == 0.0f32));
-        //assert!((truncf64(-0.1f64) == 0.0f64));
+        //assert_eq!(truncf32(0.1f32), 0.0f32);
+        //assert_eq!(truncf64(-0.1f64), 0.0f64);
     }
 
 }
index c99cad85ccb39a80119338d82b622204fcb64dd0..3dc96ecde1c0769b84d32dadea417104537fd485 100644 (file)
@@ -34,7 +34,7 @@ pub fn main() {
         let _a = Foo{ dropped: false };
     }
     // Check that we dropped already (as expected from a `{ expr }`).
-    unsafe { assert!(drop_count == 1); }
+    unsafe { assert_eq!(drop_count, 1); }
 
     // An `if false {} else { expr }` statement should compile the same as `{ expr }`.
     if false {
@@ -43,5 +43,5 @@ pub fn main() {
         let _a = Foo{ dropped: false };
     }
     // Check that we dropped already (as expected from a `{ expr }`).
-    unsafe { assert!(drop_count == 2); }
+    unsafe { assert_eq!(drop_count, 2); }
 }
index 3ad78f088f9c9f5fe26e92187f40e0cee21218d7..3eaa5632395b72ea8c32ef59d89c153ba94433f6 100644 (file)
@@ -15,7 +15,7 @@
 // when this bug was opened. The cases where the compiler
 // panics before the fix have a comment.
 
-#![feature(std_misc)]
+#![feature(thunk)]
 
 use std::thunk::Thunk;
 
index b4621a2d053b1de4dae9e8d12d889575b2b75115..9b30305a1969de924c287b97475e94bdbb32f616 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(collections)]
+#![feature(bitvec)]
 
 use std::collections::BitVec;
 
index def85b4766783ff499e58efd9a8859a995968c03..05de69cb966ad6590962c723b26db607b0ee6f77 100644 (file)
@@ -8,19 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
 #![forbid(warnings)]
-#![feature(std_misc)]
-
-// Pretty printing tests complain about `use std::predule::*`
-#![allow(unused_imports)]
 
 // We shouldn't need to rebind a moved upvar as mut if it's already
 // marked as mut
 
-use std::thunk::Thunk;
-
 pub fn main() {
     let mut x = 1;
     let _thunk = Box::new(move|| { x = 2; });
index 9ebbddf5141b7209dc0b9852ba7101e6221ba977..2e03a9a7244202b118f00158df8a5dc464e6e06d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
 #![feature(libc, std_misc)]
 
 extern crate libc;
index 71897ea68c209b39358e5ca678a632e1978584ca..e94368925abee2b261c0d6d0ac9cc104e59cb54b 100644 (file)
@@ -11,9 +11,7 @@
 // This test may not always fail, but it can be flaky if the race it used to
 // expose is still present.
 
-// pretty-expanded FIXME #23616
-
-#![feature(std_misc)]
+#![feature(mpsc_select)]
 
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread;
index e11270c94ca546dc980578b8c2eff4e987d92bc9..0ea38596335d8c8f0deb9e85011a23ea4a1b2d52 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(core)]
+#![feature(num_bits_bytes)]
 
 use std::u8;
 
index ecb83cca6f273bb7cdc0575641bcd2a3954ba440..7b00ea4a520cddb5f3be7c429073c855af69004b 100644 (file)
@@ -29,5 +29,5 @@ fn main() {
                 break
         }
     }
-    assert!(result == [2, 4]);
+    assert_eq!(result, [2, 4]);
 }
index c478ca041148a31d07795c7c97b50717df8ce4f5..ff9a17323e43322aa2e2875e5d07fb8a1979d227 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(core)]
+#![feature(iter_arith)]
 
 fn main() {
     let x: [u64; 3] = [1, 2, 3];
index e3c16793c19cb0212feee50223048872ef95c94b..20d66cd8176e72d474ea39612bdfa5a795b7880c 100644 (file)
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 enum Test<'a> {
     Slice(&'a isize)
 }
 
 fn main() {
-    assert!(Test::Slice(&1) == Test::Slice(&1))
+    assert_eq!(Test::Slice(&1), Test::Slice(&1))
 }
index 7f44c5a84cbafe9d37ee865478c638febdd2a75e..66b0aeeb988d74f51ef9939e131a486edb476c9a 100644 (file)
@@ -57,14 +57,14 @@ fn main() {
     let m = Mat::new(vec!(1, 2, 3, 4, 5, 6), 3);
     let r = m.row(1);
 
-    assert!(r.index(2) == &6);
-    assert!(r[2] == 6);
-    assert!(r[2] == 6);
-    assert!(6 == r[2]);
+    assert_eq!(r.index(2), &6);
+    assert_eq!(r[2], 6);
+    assert_eq!(r[2], 6);
+    assert_eq!(6, r[2]);
 
     let e = r[2];
-    assert!(e == 6);
+    assert_eq!(e, 6);
 
     let e: usize = r[2];
-    assert!(e == 6);
+    assert_eq!(e, 6);
 }
index 77ec44161ea72d46190183be3299cc050df9eef8..1f96f071e9d111ea3ce2389296503ddd1ea18c6a 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(hash)]
+#![feature(hash_default)]
 
 use std::hash::{SipHasher, hash};
 
@@ -17,5 +16,5 @@ use std::hash::{SipHasher, hash};
 struct Empty;
 
 pub fn main() {
-    assert!(hash::<_, SipHasher>(&Empty) == hash::<_, SipHasher>(&Empty));
+    assert_eq!(hash::<_, SipHasher>(&Empty), hash::<_, SipHasher>(&Empty));
 }
index 29d72000d07cc0271fd70c7510d2565ef7f6a215..993e5e1c1e6e90f0eaa8f0f96f79de320ae0634c 100644 (file)
@@ -11,6 +11,8 @@
 // pretty-expanded FIXME #23616
 
 #![feature(core)]
+#![feature(const_fn)]
+
 
 use std::marker;
 use std::cell::UnsafeCell;
@@ -38,8 +40,8 @@ unsafe impl<T: Send> Sync for UnsafeEnum<T> {}
 
 static STATIC1: UnsafeEnum<isize> = UnsafeEnum::VariantSafe;
 
-static STATIC2: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell { value: 1 });
-const CONST: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell { value: 1 });
+static STATIC2: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell::new(1));
+const CONST: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell::new(1));
 static STATIC3: MyUnsafe<isize> = MyUnsafe{value: CONST};
 
 static STATIC4: &'static MyUnsafePack<isize> = &STATIC2;
@@ -50,7 +52,7 @@ struct Wrap<T> {
 
 unsafe impl<T: Send> Sync for Wrap<T> {}
 
-static UNSAFE: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell{value: 2});
+static UNSAFE: MyUnsafePack<isize> = MyUnsafePack(UnsafeCell::new(2));
 static WRAPPED_UNSAFE: Wrap<&'static MyUnsafePack<isize>> = Wrap { value: &UNSAFE };
 
 fn main() {
index 2b84ce71dd2a29e7c41225193bb309eab6a863be..2bb69d105ff5d8c50b05836f29e9e330f3a26e90 100644 (file)
 
 
 #![feature(core)]
+#![feature(const_fn)]
 
 extern crate issue_17718 as other;
 
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 
 const C1: usize = 1;
-const C2: AtomicUsize = ATOMIC_USIZE_INIT;
+const C2: AtomicUsize = AtomicUsize::new(0);
 const C3: fn() = foo;
 const C4: usize = C1 * C1 + C1 / C1;
 const C5: &'static usize = &C4;
@@ -28,7 +29,7 @@ const C6: usize = {
 };
 
 static S1: usize = 3;
-static S2: AtomicUsize = ATOMIC_USIZE_INIT;
+static S2: AtomicUsize = AtomicUsize::new(0);
 
 mod test {
     static A: usize = 4;
index cf8c54fdd808667afc3262f7791369e8746e8ec6..227c81e2766fdccc6e3347a591c2a387c90ef444 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures, std_misc)]
+#![feature(thunk)]
 
 use std::thunk::Thunk;
 
index 059d25173c2ad75e57f88fa3f2b979a13092eeb2..5bcb052282c19b8257ea47fc37adccd387a589e4 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unboxed_closures, std_misc)]
+#![feature(thunk)]
 
 use std::thunk::Thunk;
 
diff --git a/src/test/run-pass/issue-18655.rs b/src/test/run-pass/issue-18655.rs
new file mode 100644 (file)
index 0000000..cdb83ae
--- /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 Factory {
+    type Product;
+    fn create(&self) -> <Self as Factory>::Product;
+}
+
+impl Factory for f64 {
+    type Product = f64;
+    fn create(&self) -> f64 { *self * *self }
+}
+
+impl<A: Factory, B: Factory> Factory for (A, B) {
+    type Product = (<A as Factory>::Product, <B as Factory>::Product);
+    fn create(&self) -> (<A as Factory>::Product, <B as Factory>::Product) {
+        let (ref a, ref b) = *self;
+        (a.create(), b.create())
+    }
+}
+
+fn main() {
+    assert_eq!((16., 25.), (4., 5.).create());
+}
diff --git a/src/test/run-pass/issue-18809.rs b/src/test/run-pass/issue-18809.rs
new file mode 100644 (file)
index 0000000..b646fa9
--- /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.
+
+trait Tup {
+    type T0;
+    type T1;
+}
+
+impl Tup for isize {
+    type T0 = f32;
+    type T1 = ();
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-18845.rs b/src/test/run-pass/issue-18845.rs
new file mode 100644 (file)
index 0000000..3d8e055
--- /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.
+
+// This used to generate invalid IR in that even if we took the
+// `false` branch we'd still try to free the Box from the other
+// arm. This was due to treating `*Box::new(9)` as an rvalue datum
+// instead of as an lvalue.
+
+fn test(foo: bool) -> u8 {
+    match foo {
+        true => *Box::new(9),
+        false => 0
+    }
+}
+
+fn main() {
+    assert_eq!(9, test(true));
+}
diff --git a/src/test/run-pass/issue-18913.rs b/src/test/run-pass/issue-18913.rs
new file mode 100644 (file)
index 0000000..9bb1371
--- /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.
+
+// aux-build:issue-18913-1.rs
+// aux-build:issue-18913-2.rs
+
+extern crate foo;
+
+fn main() {
+    assert_eq!(foo::foo(), 1);
+}
diff --git a/src/test/run-pass/issue-18988.rs b/src/test/run-pass/issue-18988.rs
new file mode 100644 (file)
index 0000000..e41ac6b
--- /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 Foo : Send { }
+
+pub struct MyFoo {
+    children: Vec<Box<Foo>>,
+}
+
+impl Foo for MyFoo { }
+
+pub fn main() { }
index e6e9bf6e6367fabf04e5340592982b3938824b3d..cff431065ffedc951206df31122a9355b17a4043 100644 (file)
@@ -12,7 +12,7 @@
 #![feature(collections)]
 
 fn main() {
-    let mut escaped = String::from_str("");
+    let mut escaped = String::from("");
     for c in '\u{10401}'.escape_unicode() {
         escaped.push(c);
     }
index 8b5e6f837d852f070591e1591ba25f302c6cb866..2772fc8787528b20f20a040860706e8ea28ec177 100644 (file)
@@ -85,7 +85,7 @@ impl<S: Strategy> Iterator for Subpaths<S> {
                 if path.is_dir() {
                     let result = self.strategy.get_more(&path);
                     match result {
-                        Ok(dirs) => { self.stack.extend(dirs.into_iter()); },
+                        Ok(dirs) => { self.stack.extend(dirs); },
                         Err(..) => { }
                     }
                 }
index c384757c5e4fb56cba9d94281b94dba992778afd..5fe3434e499e12a7f14fda13296795dda0fb433a 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(core)]
+#![feature(core_intrinsics)]
 
 struct NT(str);
 struct DST { a: u32, b: str }
@@ -27,5 +26,5 @@ fn main() {
         std::intrinsics::type_name::<NT>(),
         // DST
         std::intrinsics::type_name::<DST>()
-    )}, ("[u8]", "str", "core::marker::Copy", "NT", "DST"));
+    )}, ("[u8]", "str", "core::marker::Copy + 'static", "NT", "DST"));
 }
index e10fcd30b9961d666baeff1cc645787bdc8f95c9..2ef66809a8d80ba0680af27246bad0e3ce2f6e8c 100644 (file)
@@ -15,16 +15,16 @@ fn test<T : Clone>(arg: T) -> T {
     arg.clone()
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Debug)]
 struct Test(isize);
 
 fn main() {
     // Check that ranges implement clone
-    assert!(test(1..5) == (1..5));
-    assert!(test(..5) == (..5));
-    assert!(test(1..) == (1..));
-    assert!(test(RangeFull) == (RangeFull));
+    assert_eq!(test(1..5), (1..5));
+    assert_eq!(test(..5), (..5));
+    assert_eq!(test(1..), (1..));
+    assert_eq!(test(RangeFull), (RangeFull));
 
     // Check that ranges can still be used with non-clone limits
-    assert!((Test(1)..Test(5)) == (Test(1)..Test(5)));
+    assert_eq!((Test(1)..Test(5)), (Test(1)..Test(5)));
 }
index 7f8bd7a95f7a7e5e48f5aaaf9e8c43c06d62b462..699189a4e6aedd88657acc9e56aedbb1b121e14e 100644 (file)
@@ -12,8 +12,9 @@
 // created via FRU and control-flow breaks in the middle of
 // construction.
 
+#![feature(const_fn)]
 
-use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::{Ordering, AtomicUsize};
 
 #[derive(Debug)]
 struct Noisy(u8);
@@ -69,7 +70,7 @@ pub fn main() {
     assert_eq!(0x03_04, event_log());
 }
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 fn reset_log() {
     LOG.store(0, Ordering::SeqCst);
diff --git a/src/test/run-pass/issue-21622.rs b/src/test/run-pass/issue-21622.rs
new file mode 100644 (file)
index 0000000..32f5230
--- /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.
+
+
+struct Index;
+
+impl Index {
+    fn new() -> Self { Index }
+}
+
+fn user() {
+    let new = Index::new;
+
+    fn inner() {
+        let index = Index::new();
+    }
+
+    let index2 = new();
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs
deleted file mode 100644 (file)
index fb0d2f0..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-
-// notes on this test case:
-// On Thu, Apr 18, 2013-2014 at 6:30 PM, John Clements <clements@brinckerhoff.org> wrote:
-// the "issue-2185.rs" test was ignored with a ref to #2263. Issue #2263 is now fixed,
-// so I tried it again, and after adding some &self parameters, I got this error:
-//
-// Running /usr/local/bin/rustc:
-// issue-2185.rs:24:0: 26:1 error: conflicting implementations for a trait
-// issue-2185.rs:24 impl iterable<usize> for 'static ||usize|| {
-// issue-2185.rs:25     fn iter(&self, blk: |v: usize|) { self( |i| blk(i) ) }
-// issue-2185.rs:26 }
-// issue-2185.rs:20:0: 22:1 note: note conflicting implementation here
-// issue-2185.rs:20 impl<A> iterable<A> for 'static ||A|| {
-// issue-2185.rs:21     fn iter(&self, blk: |A|) { self(blk); }
-// issue-2185.rs:22 }
-//
-// … so it looks like it's just not possible to implement both
-// the generic iterable<usize> and iterable<A> for the type iterable<usize>.
-// Is it okay if I just remove this test?
-//
-// but Niko responded:
-// think it's fine to remove this test, just because it's old and cruft and not hard to reproduce.
-// *However* it should eventually be possible to implement the same interface for the same type
-// multiple times with different type parameters, it's just that our current trait implementation
-// has accidental limitations.
-
-// so I'm leaving it in.
-// actually, it looks like this is related to bug #3429. I'll rename this bug.
-
-// This test had to do with an outdated version of the iterable trait.
-// However, the condition it was testing seemed complex enough to
-// warrant still having a test, so I inlined the old definitions.
-
-trait iterable<A> {
-    fn iter(&self, blk: |A|);
-}
-
-impl<A> iterable<A> for 'static ||A|| {
-    fn iter(&self, blk: |A|) { self(blk); }
-}
-
-impl iterable<usize> for 'static ||usize|| {
-    fn iter(&self, blk: |v: usize|) { self( |i| blk(i) ) }
-}
-
-fn filter<A,IA:iterable<A>>(self: IA, prd: 'static |A| -> bool, blk: |A|) {
-    self.iter(|a| {
-        if prd(a) { blk(a) }
-    });
-}
-
-fn foldl<A,B,IA:iterable<A>>(self: IA, b0: B, blk: |B, A| -> B) -> B {
-    let mut b = b0;
-    self.iter(|a| {
-        b = blk(b, a);
-    });
-    b
-}
-
-fn range(lo: usize, hi: usize, it: |usize|) {
-    let mut i = lo;
-    while i < hi {
-        it(i);
-        i += 1;
-    }
-}
-
-pub fn main() {
-    let range: 'static ||usize|| = |a| range(0, 1000, a);
-    let filt: 'static ||v: usize|| = |a| filter(
-        range,
-        |&&n: usize| n % 3 != 0 && n % 5 != 0,
-        a);
-    let sum = foldl(filt, 0, |accum, &&n: usize| accum + n );
-
-    println!("{}", sum);
-}
index 5c84c30aa7fa3631a7fc277f4697f3cb8def9f1e..eeca4498328d36bbba7c6df54eec275dc999afa8 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(std_misc)]
+#![feature(thunk)]
 
 use std::thread::Builder;
 use std::thunk::Thunk;
diff --git a/src/test/run-pass/issue-2190-2.rs b/src/test/run-pass/issue-2190-2.rs
deleted file mode 100644 (file)
index 39a97b0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test FIXME #2190
-
-mod a {
-    fn foo(f: ||) { f() }
-    fn bar() {}
-    pub fn main() { foo(||bar()); }
-}
-
-mod b {
-    fn foo(f: Option<||>) { f.map(|x|x()); }
-    fn bar() {}
-    pub fn main() { foo(Some(bar)); }
-}
-
-mod c {
-    fn foo(f: Option<||>) { f.map(|x|x()); }
-    fn bar() {}
-    pub fn main() { foo(Some(||bar())); }
-}
-
-pub fn main() {
-}
diff --git a/src/test/run-pass/issue-22864-1.rs b/src/test/run-pass/issue-22864-1.rs
new file mode 100644 (file)
index 0000000..df1e3c5
--- /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.
+
+pub fn main() {
+    struct Fun<F>(F);
+    let f = Fun(|x| 3*x);
+    let Fun(g) = f;
+    println!("{:?}",g(4));
+}
diff --git a/src/test/run-pass/issue-22864-2.rs b/src/test/run-pass/issue-22864-2.rs
new file mode 100644 (file)
index 0000000..da78578
--- /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.
+
+pub fn main() {
+    let f = || || 0;
+    std::thread::spawn(f());
+}
index 5257daa047af8b1f1d99be86e7fc7256fe136a76..a8abbda32bdfc23a24915783aa2088c6212a04c7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(core_simd)]
 
 use std::simd::i32x4;
 fn main() {
index 9b5ca23565e0d7710edf2d28806bae2809d750a3..4b6d593f592d970b812bc0ca043e17ebd50849f4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(core_intrinsics)]
 #![allow(warnings)]
 
 use std::intrinsics;
diff --git a/src/test/run-pass/issue-23649-1.rs b/src/test/run-pass/issue-23649-1.rs
new file mode 100644 (file)
index 0000000..a631898
--- /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.
+
+use std::mem;
+
+pub struct X([u8]);
+
+fn _f(x: &X) -> usize { match *x { X(ref x) =>  { x.len() } } }
+
+fn main() {
+    let b: &[u8] = &[11; 42];
+    let v: &X = unsafe { mem::transmute(b) };
+    assert_eq!(_f(v), 42);
+}
diff --git a/src/test/run-pass/issue-23649-2.rs b/src/test/run-pass/issue-23649-2.rs
new file mode 100644 (file)
index 0000000..018c069
--- /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, PathBuf};
+
+fn main() {
+    let m: HashMap<PathBuf, ()> = HashMap::new();
+    let k = Path::new("foo");
+    println!("{:?}", m.get(k));
+}
diff --git a/src/test/run-pass/issue-23649-3.rs b/src/test/run-pass/issue-23649-3.rs
new file mode 100644 (file)
index 0000000..4aa6c53
--- /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.
+
+#[derive(PartialEq)]
+struct Slice { slice: [u8] }
+
+fn main() {}
diff --git a/src/test/run-pass/issue-23968-const-not-overflow.rs b/src/test/run-pass/issue-23968-const-not-overflow.rs
new file mode 100644 (file)
index 0000000..95f6591
--- /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.
+
+const U8_MAX_HALF: u8 = !0u8 / 2;
+const U16_MAX_HALF: u16 = !0u16 / 2;
+const U32_MAX_HALF: u32 = !0u32 / 2;
+const U64_MAX_HALF: u64 = !0u64 / 2;
+
+fn main() {
+    assert_eq!(U8_MAX_HALF, 0x7f);
+    assert_eq!(U16_MAX_HALF, 0x7fff);
+    assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
+    assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
+}
diff --git a/src/test/run-pass/issue-24085.rs b/src/test/run-pass/issue-24085.rs
new file mode 100644 (file)
index 0000000..3617b0d
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #24085. Errors were occuring in region
+// inference due to the requirement that `'a:b'`, which was getting
+// incorrectly translated in connection with the closure below.
+
+#[derive(Copy,Clone)]
+struct Path<'a:'b, 'b> {
+    x: &'a i32,
+    tail: Option<&'b Path<'a, 'b>>
+}
+
+#[allow(dead_code, unconditional_recursion)]
+fn foo<'a,'b,F>(p: Path<'a, 'b>, mut f: F)
+                where F: for<'c> FnMut(Path<'a, 'c>) {
+    foo(p, |x| f(x))
+}
+
+fn main() { }
diff --git a/src/test/run-pass/issue-24227.rs b/src/test/run-pass/issue-24227.rs
new file mode 100644 (file)
index 0000000..34c16bd
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+// This resulted in an ICE. Test for future-proofing
+// Issue #24227
+
+#![allow(unused)]
+
+struct Foo<'a> {
+    x: &'a u8
+}
+
+impl<'a> Foo<'a> {
+    fn foo() {
+        let mut tmp: Self;
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-24258.rs b/src/test/run-pass/issue-24258.rs
new file mode 100644 (file)
index 0000000..f56c3fe
--- /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.
+
+// compile-flags: -C debug-assertions
+
+#![feature(core_simd)]
+
+use std::simd::u32x4;
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn eq_u32x4(u32x4(x0, x1, x2, x3): u32x4, u32x4(y0, y1, y2, y3): u32x4) -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+}
+
+fn main() {
+    assert!(eq_u32x4(u32x4(1, 1, 1, 1) << id(u32x4(1, 1, 1, 1)), u32x4(2, 2, 2, 2)));
+}
diff --git a/src/test/run-pass/issue-24308.rs b/src/test/run-pass/issue-24308.rs
new file mode 100644 (file)
index 0000000..0a483fc
--- /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.
+
+pub trait Foo {
+    fn method1() {}
+    fn method2();
+}
+
+struct Slice<'a, T: 'a>(&'a [T]);
+
+impl<'a, T: 'a> Foo for Slice<'a, T> {
+    fn method2() {
+        <Self as Foo>::method1();
+    }
+}
+
+fn main() {
+    <Slice<()> as Foo>::method2();
+}
diff --git a/src/test/run-pass/issue-24589.rs b/src/test/run-pass/issue-24589.rs
new file mode 100644 (file)
index 0000000..2fa8c8e
--- /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.
+
+pub struct _X([u8]);
+
+impl std::ops::Deref for _X {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+pub fn _g(x: &_X) -> &[u8] {
+    x
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-24779.rs b/src/test/run-pass/issue-24779.rs
new file mode 100644 (file)
index 0000000..4f13b91
--- /dev/null
@@ -0,0 +1,13 @@
+// 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() {
+    assert_eq!((||||42)()(), 42);
+}
diff --git a/src/test/run-pass/issue-25180.rs b/src/test/run-pass/issue-25180.rs
new file mode 100644 (file)
index 0000000..4e6f9b3
--- /dev/null
@@ -0,0 +1,13 @@
+// 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 x: &'static Fn() = &|| println!("ICE here");
+
+fn main() {}
diff --git a/src/test/run-pass/issue-25279.rs b/src/test/run-pass/issue-25279.rs
new file mode 100644 (file)
index 0000000..e483866
--- /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.
+
+struct S<'a>(&'a ());
+
+impl<'a> S<'a> {
+    fn foo(self) -> &'a () {
+        <Self>::bar(self)
+    }
+
+    fn bar(self) -> &'a () {
+        self.0
+    }
+}
+
+fn main() {
+    S(&()).foo();
+}
diff --git a/src/test/run-pass/issue-25339.rs b/src/test/run-pass/issue-25339.rs
new file mode 100644 (file)
index 0000000..381df7c
--- /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.
+
+#![feature(associated_type_defaults)]
+
+use std::marker::PhantomData;
+
+pub trait Routing<I> {
+    type Output;
+    fn resolve(&self, input: I);
+}
+
+pub trait ToRouting {
+    type Input;
+    type Routing : ?Sized = Routing<Self::Input, Output=()>;
+    fn to_routing(self) -> Self::Routing;
+}
+
+pub struct Mount<I, R: Routing<I>> {
+    action: R,
+    _marker: PhantomData<I>
+}
+
+impl<I, R: Routing<I>> Mount<I, R> {
+    pub fn create<T: ToRouting<Routing=R>>(mount: &str, input: T) {
+        input.to_routing();
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-25394.rs b/src/test/run-pass/issue-25394.rs
new file mode 100644 (file)
index 0000000..c42de6f
--- /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.
+
+#[derive(Debug)]
+struct Row<T>([T]);
+
+fn main() {}
diff --git a/src/test/run-pass/issue-25497.rs b/src/test/run-pass/issue-25497.rs
new file mode 100644 (file)
index 0000000..730b0a2
--- /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.
+
+#[derive(Clone, Debug, PartialEq)]
+enum Expression {
+    Dummy,
+    Add(Box<Expression>),
+}
+
+use Expression::*;
+
+fn simplify(exp: Expression) -> Expression {
+    match exp {
+        Add(n) => *n.clone(),
+        _ => Dummy
+    }
+}
+
+fn main() {
+    assert_eq!(simplify(Add(Box::new(Dummy))), Dummy);
+}
diff --git a/src/test/run-pass/issue-25515.rs b/src/test/run-pass/issue-25515.rs
new file mode 100644 (file)
index 0000000..d1746ec
--- /dev/null
@@ -0,0 +1,29 @@
+// 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;
+
+struct Foo<'r>(&'r mut i32);
+
+impl<'r> Drop for Foo<'r> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+fn main() {
+    let mut drops = 0;
+
+    {
+        let _: Rc<Send> = Rc::new(Foo(&mut drops));
+    }
+
+    assert_eq!(1, drops);
+}
diff --git a/src/test/run-pass/issue-25549-multiple-drop.rs b/src/test/run-pass/issue-25549-multiple-drop.rs
new file mode 100644 (file)
index 0000000..5280891
--- /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.
+
+struct Foo<'r>(&'r mut i32);
+
+impl<'r> Drop for Foo<'r> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+trait Trait {}
+impl<'r> Trait for Foo<'r> {}
+
+struct Holder<T: ?Sized>(T);
+
+fn main() {
+    let mut drops = 0;
+
+    {
+        let y = &Holder([Foo(&mut drops)]) as &Holder<[Foo]>;
+        // this used to cause an extra drop of the Foo instance
+        let x = &y.0;
+    }
+    assert_eq!(1, drops);
+
+    drops = 0;
+    {
+        let y = &Holder(Foo(&mut drops)) as &Holder<Trait>;
+        // this used to cause an extra drop of the Foo instance
+        let x = &y.0;
+    }
+    assert_eq!(1, drops);
+}
diff --git a/src/test/run-pass/issue-25679.rs b/src/test/run-pass/issue-25679.rs
new file mode 100644 (file)
index 0000000..0ba7fee
--- /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.
+
+trait Device {
+    type Resources;
+}
+struct Foo<D, R>(D, R);
+
+impl<D: Device> Foo<D, D::Resources> {
+    fn present(&self) {}
+}
+
+struct Res;
+struct Dev;
+
+impl Device for Dev { type Resources = Res; }
+
+fn main() {
+    let foo = Foo(Dev, Res);
+    foo.present();
+}
diff --git a/src/test/run-pass/issue-25700-1.rs b/src/test/run-pass/issue-25700-1.rs
new file mode 100644 (file)
index 0000000..57f5b84
--- /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.
+
+struct S<T: 'static>(Option<&'static T>);
+
+trait Tr { type Out; }
+impl<T> Tr for T { type Out = T; }
+
+impl<T: 'static> Copy for S<T> where S<T>: Tr<Out=T> {}
+impl<T: 'static> Clone for S<T> where S<T>: Tr<Out=T> {
+    fn clone(&self) -> Self { *self }
+}
+fn main() {
+    S::<()>(None);
+}
diff --git a/src/test/run-pass/issue-25700-2.rs b/src/test/run-pass/issue-25700-2.rs
new file mode 100644 (file)
index 0000000..3117e6f
--- /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.
+
+pub trait Parser {
+    type Input;
+}
+
+pub struct Iter<P: Parser>(P, P::Input);
+
+pub struct Map<P, F>(P, F);
+impl<P, F> Parser for Map<P, F> where F: FnMut(P) {
+    type Input = u8;
+}
+
+trait AstId { type Untyped; }
+impl AstId for u32 { type Untyped = u32; }
+
+fn record_type<Id: AstId>(i: Id::Untyped) -> u8 {
+    Iter(Map(i, |_: Id::Untyped| {}), 42).1
+}
+
+pub fn main() {
+   assert_eq!(record_type::<u32>(3), 42);
+}
diff --git a/src/test/run-pass/issue-25746-bool-transmute.rs b/src/test/run-pass/issue-25746-bool-transmute.rs
new file mode 100644 (file)
index 0000000..434e019
--- /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.
+
+use std::mem::transmute;
+
+fn main() {
+    unsafe {
+        let _: i8 = transmute(false);
+        let _: i8 = transmute(true);
+        let _: bool = transmute(0u8);
+        let _: bool = transmute(1u8);
+    }
+}
diff --git a/src/test/run-pass/issue-25757.rs b/src/test/run-pass/issue-25757.rs
new file mode 100644 (file)
index 0000000..8deb2e2
--- /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.
+
+struct Foo {
+    a: u32
+}
+
+impl Foo {
+    fn x(&mut self) {
+        self.a = 5;
+    }
+}
+
+const FUNC: &'static Fn(&mut Foo) -> () = &Foo::x;
+
+fn main() {
+    let mut foo = Foo { a: 137 };
+    FUNC(&mut foo); //~ ERROR bad
+    assert_eq!(foo.a, 5);
+}
index 2c45d664d894e402450d19da32f7d476b8c97fe6..d82fce97c41dc52707c899516d1e751bb9bff55e 100644 (file)
@@ -70,14 +70,14 @@ fn read_board_grid<rdr:'static + Read>(mut input: rdr)
     }
     grid.push(row);
     let width = grid[0].len();
-    for row in &grid { assert!(row.len() == width) }
+    for row in &grid { assert_eq!(row.len(), width) }
     grid
 }
 
 mod test {
     #[test]
     pub fn trivial_to_string() {
-        assert!(lambda.to_string() == "\\")
+        assert_eq!(lambda.to_string(), "\\")
     }
 }
 
index 592ff0b02a4ad406133977fdaa31cfaca311814a..bdd0a535303951d258a5a5c6800c4cce7292a123 100644 (file)
@@ -13,4 +13,4 @@ fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
 
 fn id<T>(x: T) -> T { return x; }
 
-pub fn main() { assert!((quux(10) == 10)); }
+pub fn main() { assert_eq!(quux(10), 10); }
diff --git a/src/test/run-pass/issue-4120.rs b/src/test/run-pass/issue-4120.rs
deleted file mode 100644 (file)
index 8722376..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-
-// ignored due to Valgrind complaining about TLS loss.
-
-pub fn main()
-{
-    unsafe {
-        libc::exit(0);
-    }
-    println!("ack");
-}
diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs
deleted file mode 100644 (file)
index ab75c20..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test needs networking
-
-extern crate extra;
-
-use extra::net::tcp::TcpSocketBuf;
-
-use std::io;
-use std::isize;
-
-use std::io::{ReaderUtil,WriterUtil};
-
-enum Result {
-  Nil,
-  Int(isize),
-  Data(Vec<u8>),
-  List(Vec<Result>),
-  Error(String),
-  Status(String)
-}
-
-fn parse_data(len: usize, io: @io::Reader) -> Result {
-  let res =
-      if (len > 0) {
-      let bytes = io.read_bytes(len as usize);
-      assert_eq!(bytes.len(), len);
-      Data(bytes)
-  } else {
-      Data(vec![])
-  };
-  assert_eq!(io.read_char(), '\r');
-  assert_eq!(io.read_char(), '\n');
-  return res;
-}
-
-fn parse_list(len: usize, io: @io::Reader) -> Result {
-    let mut list: Vec<Result> = vec![];
-    for _ in 0..len {
-        let v = match io.read_char() {
-            '$' => parse_bulk(io),
-            ':' => parse_int(io),
-             _ => panic!()
-        };
-        list.push(v);
-    }
-    return List(list);
-}
-
-fn chop(s: String) -> String {
-  s.slice(0, s.len() - 1).to_string()
-}
-
-fn parse_bulk(io: @io::Reader) -> Result {
-    match from_str::<isize>(chop(io.read_line())) {
-    None => panic!(),
-    Some(-1) => Nil,
-    Some(len) if len >= 0 => parse_data(len as usize, io),
-    Some(_) => panic!()
-    }
-}
-
-fn parse_multi(io: @io::Reader) -> Result {
-    match from_str::<isize>(chop(io.read_line())) {
-    None => panic!(),
-    Some(-1) => Nil,
-    Some(0) => List(vec![]),
-    Some(len) if len >= 0 => parse_list(len as usize, io),
-    Some(_) => panic!()
-    }
-}
-
-fn parse_int(io: @io::Reader) -> Result {
-    match from_str::<isize>(chop(io.read_line())) {
-    None => panic!(),
-    Some(i) => Int(i)
-    }
-}
-
-fn parse_response(io: @io::Reader) -> Result {
-    match io.read_char() {
-    '$' => parse_bulk(io),
-    '*' => parse_multi(io),
-    '+' => Status(chop(io.read_line())),
-    '-' => Error(chop(io.read_line())),
-    ':' => parse_int(io),
-    _ => panic!()
-    }
-}
-
-fn cmd_to_string(cmd: Vec<String>) -> String {
-  let mut res = "*".to_string();
-  res.push_str(cmd.len().to_string());
-  res.push_str("\r\n");
-    for s in &cmd {
-    res.push_str(["$".to_string(), s.len().to_string(), "\r\n".to_string(),
-                  (*s).clone(), "\r\n".to_string()].concat() );
-    }
-  res
-}
-
-fn query(cmd: Vec<String>, sb: TcpSocketBuf) -> Result {
-  let cmd = cmd_to_string(cmd);
-  //println!("{}", cmd);
-  sb.write_str(cmd);
-  let res = parse_response(@sb as @io::Reader);
-  res
-}
-
-fn query2(cmd: Vec<String>) -> Result {
-  let _cmd = cmd_to_string(cmd);
-    io::with_str_reader("$3\r\nXXX\r\n".to_string())(|sb| {
-    let res = parse_response(@sb as @io::Reader);
-    println!("{}", res);
-    res
-    });
-}
-
-
-pub fn main() {
-}
index 5e58d76d5e0ff81072660a6949fb87bbae58a620..406746ab8c54cfba4d1a84ed463f2870e7212b26 100644 (file)
@@ -14,5 +14,5 @@
 pub fn main() {
     let _f = |ref x: isize| { *x };
     let foo = 10;
-    assert!(_f(foo) == 10);
+    assert_eq!(_f(foo), 10);
 }
index 3138aad2c8cc9b5778e34a65717272301b35d2ab..8ea0804af18bf5499cf3bb4c11df8dbddb3c8c65 100644 (file)
@@ -10,9 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(core)]
-
-use std::intrinsics;
+use std::mem;
 
 /// Returns the size of a type
 pub fn size_of<T>() -> usize {
@@ -32,7 +30,7 @@ pub trait TypeInfo {
 impl<T> TypeInfo for T {
     /// The size of the type in bytes.
     fn size_of(_lame_type_hint: Option<T>) -> usize {
-        unsafe { intrinsics::size_of::<T>() }
+        mem::size_of::<T>()
     }
 
     /// Returns the size of the type of `self` in bytes.
index 7aac8d4456334c64b182bbe1109bdb2bb8dc0acf..87e0799f634612a3aabf3144cfca6169555aba70 100644 (file)
@@ -19,7 +19,7 @@ mod test1 {
     pub mod baz {
         use test1::bar::p;
 
-        pub fn my_main() { assert!(p() == 2); }
+        pub fn my_main() { assert_eq!(p(), 2); }
     }
 }
 
@@ -31,7 +31,7 @@ mod test2 {
     pub mod baz {
         use test2::bar::p;
 
-        pub fn my_main() { assert!(p() == 2); }
+        pub fn my_main() { assert_eq!(p(), 2); }
     }
 }
 
index 224fe627e32d9d199eb5af02a54e20f7b49367c1..badc013cd621f6297af82991af69264dc35b0073 100644 (file)
@@ -37,6 +37,6 @@ fn main() {
     let out = bar("baz", "foo");
     let [a, xs.., d] = out;
     assert_eq!(a, "baz");
-    assert!(xs == ["foo", "foo"]);
+    assert_eq!(xs, ["foo", "foo"]);
     assert_eq!(d, "baz");
 }
index fae3352f9cc5fcc3df59fe12e22ea121fd6e0d0d..d57b2a3236895727b8a3186ee8cee582267092ba 100644 (file)
@@ -13,14 +13,14 @@ pub fn main() {
     match &[(Box::new(5),Box::new(7))] {
         ps => {
            let (ref y, _) = ps[0];
-           assert!(**y == 5);
+           assert_eq!(**y, 5);
         }
     }
 
     match Some(&[(Box::new(5),)]) {
         Some(ps) => {
            let (ref y,) = ps[0];
-           assert!(**y == 5);
+           assert_eq!(**y, 5);
         }
         None => ()
     }
@@ -28,8 +28,8 @@ pub fn main() {
     match Some(&[(Box::new(5),Box::new(7))]) {
         Some(ps) => {
            let (ref y, ref z) = ps[0];
-           assert!(**y == 5);
-           assert!(**z == 7);
+           assert_eq!(**y, 5);
+           assert_eq!(**z, 7);
         }
         None => ()
     }
index e5a287d01491939f3818c3702b2d82632063c715..5e1fd87b57a1317e8dc0cf348d630fe4a2fce360 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test #9737
-
 macro_rules! f {
     (v: $x:expr) => ( println!("{}", $x) )
 }
diff --git a/src/test/run-pass/issue18173.rs b/src/test/run-pass/issue18173.rs
new file mode 100644 (file)
index 0000000..f4266fa
--- /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.
+
+trait Foo {
+    type T;
+}
+
+// should be able to use a trait with an associated type without specifying it as an argument
+trait Bar<F: Foo> {
+    fn bar(foo: &F);
+}
+
+pub fn main() {
+}
diff --git a/src/test/run-pass/issue26127.rs b/src/test/run-pass/issue26127.rs
new file mode 100644 (file)
index 0000000..75cbcc8
--- /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.
+
+trait Tr { type T; }
+impl Tr for u8 { type T=(); }
+struct S<I: Tr>(I::T);
+
+fn foo<I: Tr>(i: I::T) {
+    S::<I>(i);
+}
+
+fn main() {
+    foo::<u8>(());
+}
index 0013cb292e1c7d87c4914b711910be61dfc55d52..3197d7f0160a67151175e8c46be6e207898ec83c 100644 (file)
@@ -16,7 +16,7 @@ fn test_stack_assign() {
     let s: String = "a".to_string();
     println!("{}", s.clone());
     let t: String = "a".to_string();
-    assert!(s == t);
+    assert_eq!(s, t);
     let u: String = "b".to_string();
     assert!((s != u));
 }
@@ -26,7 +26,7 @@ fn test_heap_lit() { "a big string".to_string(); }
 fn test_heap_assign() {
     let s: String = "a big ol' string".to_string();
     let t: String = "a big ol' string".to_string();
-    assert!(s == t);
+    assert_eq!(s, t);
     let u: String = "a bad ol' string".to_string();
     assert!((s != u));
 }
@@ -41,17 +41,17 @@ fn test_append() {
     s.push_str("a");
     assert_eq!(s, "a");
 
-    let mut s = String::from_str("a");
+    let mut s = String::from("a");
     s.push_str("b");
     println!("{}", s.clone());
     assert_eq!(s, "ab");
 
-    let mut s = String::from_str("c");
+    let mut s = String::from("c");
     s.push_str("offee");
-    assert!(s == "coffee");
+    assert_eq!(s, "coffee");
 
     s.push_str("&tea");
-    assert!(s == "coffee&tea");
+    assert_eq!(s, "coffee&tea");
 }
 
 pub fn main() {
index 59f7569d8c62bf009a2c400bdc925d26350cd8ce..e3351bda3354d93bc124bb2d423d20d920adccc8 100644 (file)
@@ -11,8 +11,7 @@
 // Test to see that the element type of .cloned() can be inferred
 // properly. Previously this would fail to deduce the type of `sum`.
 
-
-#![feature(core)]
+#![feature(iter_arith)]
 
 fn square_sum(v: &[i64]) -> i64 {
     let sum: i64 = v.iter().cloned().sum();
index 80bd15578d1152d56d6d738ac385b2f7a5cc2d91..ddb4e40aea6332a9b772efb71a346dad3b939a39 100644 (file)
@@ -19,11 +19,11 @@ pub fn main() {
     let s = "hello there".to_string();
     let mut i: isize = 0;
     for c in s.bytes() {
-        if i == 0 { assert!((c == 'h' as u8)); }
-        if i == 1 { assert!((c == 'e' as u8)); }
-        if i == 2 { assert!((c == 'l' as u8)); }
-        if i == 3 { assert!((c == 'l' as u8)); }
-        if i == 4 { assert!((c == 'o' as u8)); }
+        if i == 0 { assert_eq!(c, 'h' as u8); }
+        if i == 1 { assert_eq!(c, 'e' as u8); }
+        if i == 2 { assert_eq!(c, 'l' as u8); }
+        if i == 3 { assert_eq!(c, 'l' as u8); }
+        if i == 4 { assert_eq!(c, 'o' as u8); }
         // ...
 
         i += 1;
index b8ad7162d286811c3b5fc6395ed45b0b4eb5b8f8..e6eaefb0490806e7c4c653cc5472c8f5ac10ef8d 100644 (file)
@@ -13,8 +13,6 @@
 // ignore-windows: std::dynamic_lib does not work on Windows well
 // ignore-musl
 
-#![feature(std_misc)]
-
 extern crate linkage_visibility as foo;
 
 pub fn main() {
diff --git a/src/test/run-pass/lint-dead-code-variant.rs b/src/test/run-pass/lint-dead-code-variant.rs
new file mode 100644 (file)
index 0000000..074c69d
--- /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.
+
+#![deny(dead_code)]
+
+enum Foo {
+    A,
+    B,
+}
+
+pub fn main() {
+    match Foo::A {
+        Foo::A | Foo::B => Foo::B
+    };
+}
index 575f087d8335f1b865c2c25fab6a0c4bcd5c1cc4..1b1cdcb1102a2d3015e772388af3e32799254e92 100644 (file)
@@ -20,7 +20,7 @@ struct Foo(Cell<isize>);
 impl fmt::Debug for Foo {
     fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result {
         let Foo(ref f) = *self;
-        assert!(f.get() == 0);
+        assert_eq!(f.get(), 0);
         f.set(1);
         Ok(())
     }
@@ -31,6 +31,6 @@ pub fn main() {
         let mut f = Foo(Cell::new(0));
         println!("{:?}", f);
         let Foo(ref mut f) = f;
-        assert!(f.get() == 1);
+        assert_eq!(f.get(), 1);
     }).join().ok().unwrap();
 }
index d582fc3b721b4d0fc7cb3892908f415205e18233..2cac9226117a29ae91e412f97d105c0039fd390a 100644 (file)
@@ -19,5 +19,5 @@ pub fn main() {
         })
     }
 
-    assert!(mylambda_tt!(y, y * 2)(8) == 16);
+    assert_eq!(mylambda_tt!(y, y * 2)(8), 16);
 }
diff --git a/src/test/run-pass/macro-followed-by-seq.rs b/src/test/run-pass/macro-followed-by-seq.rs
new file mode 100644 (file)
index 0000000..1522493
--- /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.
+
+// Regression test for issue #25436: check that things which can be
+// followed by any token also permit X* to come afterwards.
+
+macro_rules! foo {
+  ( $a:tt $($b:tt)* ) => { };
+  ( $a:ident $($b:tt)* ) => { };
+  ( $a:item $($b:tt)* ) => { };
+  ( $a:block $($b:tt)* ) => { };
+  ( $a:meta $($b:tt)* ) => { }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/macro-pat-follow.rs b/src/test/run-pass/macro-pat-follow.rs
new file mode 100644 (file)
index 0000000..77c6ed4
--- /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.
+
+macro_rules! pat_in {
+    ($p:pat in $e:expr) => {{
+        let mut iter = $e.into_iter();
+        while let $p = iter.next() {}
+    }}
+}
+
+macro_rules! pat_if {
+    ($p:pat if $e:expr) => {{
+        match Some(1u8) {
+            $p if $e => {},
+            _ => {}
+        }
+    }}
+}
+
+fn main() {
+    pat_in!(Some(_) in 0..10);
+    pat_if!(Some(x) if x > 0);
+}
diff --git a/src/test/run-pass/macro-tt-followed-by-seq.rs b/src/test/run-pass/macro-tt-followed-by-seq.rs
new file mode 100644 (file)
index 0000000..cdb1f86
--- /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.
+
+// Regression test for issue #25436: permit token-trees to be followed
+// by sequences, enabling more general parsing.
+
+use self::Join::*;
+
+#[derive(Debug)]
+enum Join<A,B> {
+  Keep(A,B),
+  Skip(A,B),
+}
+
+macro_rules! parse_list {
+  ( < $a:expr; > $($b:tt)* ) => { Keep(parse_item!($a),parse_list!($($b)*)) };
+  ( $a:tt $($b:tt)* ) => { Skip(parse_item!($a), parse_list!($($b)*)) };
+  ( ) => { () };
+}
+
+macro_rules! parse_item {
+  ( $x:expr ) => { $x }
+}
+
+fn main() {
+    let list = parse_list!(<1;> 2 <3;> 4);
+    assert_eq!("Keep(1, Skip(2, Keep(3, Skip(4, ()))))",
+               format!("{:?}", list));
+}
index 4881a5ab647ec0996efde72f97ad3c368aae8120..326d1cafe6c782fe47ba3a2bf62af3516dd01c2f 100644 (file)
@@ -8,15 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_misc)]
-
 use std::thread;
 
 macro_rules! expr { ($e: expr) => { $e } }
 
 macro_rules! spawn {
     ($($code: tt)*) => {
-        expr!(thread::spawn(move|| {$($code)*}))
+        expr!(thread::spawn(move|| {$($code)*}).join())
     }
 }
 
index d75bdaf4da8ea70155320c763e4b5b9caaa6984b..caf76b3ab2fe177e8ef538334ff3edeba5595b9f 100644 (file)
@@ -19,7 +19,9 @@ pub fn main() {
     let x_internal = &mut *x;
     match *x_internal {
       Pair {a: ref mut a, b: ref mut _b} => {
-        assert!(**a == 10); *a = box 30; assert!(**a == 30);
+        assert_eq!(**a, 10);
+        *a = box 30;
+        assert_eq!(**a, 30);
       }
     }
 }
index 33c77f33c44bdabf139a1f4284c4af34f1f3788b..32de1c6c6742747a9fc77d2727926d2deea4e820 100644 (file)
@@ -18,4 +18,7 @@ fn altlit(f: isize) -> isize {
     }
 }
 
-pub fn main() { assert!((altlit(10) == 20)); assert!((altlit(11) == 22)); }
+pub fn main() {
+    assert_eq!(altlit(10), 20);
+    assert_eq!(altlit(11), 22);
+}
diff --git a/src/test/run-pass/match-range-infer.rs b/src/test/run-pass/match-range-infer.rs
new file mode 100644 (file)
index 0000000..74f513e
--- /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.
+
+// Test that type inference for range patterns works correctly (is bi-directional).
+
+pub fn main() {
+    match 1 {
+        1 ... 3 => {}
+        _ => panic!("should match range")
+    }
+    match 1 {
+        1 ... 3u16 => {}
+        _ => panic!("should match range with inferred start type")
+    }
+    match 1 {
+        1u16 ... 3 => {}
+        _ => panic!("should match range with inferred end type")
+    }
+}
index 08f3182900fc2bba9fdd135c319b34c4e8e1c0c7..77e3b724cbe777fd71567a4640263a3b3ea36e37 100644 (file)
@@ -26,12 +26,12 @@ fn f() {
         (0, A) => 0,
         (x, y) => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
     let r = match (0,97) {
         (0, A) => 0,
         (x, y) => 1 + x + y,
     };
-    assert!(r == 0);
+    assert_eq!(r, 0);
 }
 
 mod m {
@@ -45,12 +45,12 @@ fn g() {
         (0, AHA) => 0,
         (x, y)   => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
     let r = match (0,7) {
         (0, AHA) => 0,
         (x, y)   => 1 + x + y,
     };
-    assert!(r == 0);
+    assert_eq!(r, 0);
 }
 
 fn h() {
@@ -58,12 +58,12 @@ fn h() {
         (0, self::m::aha) => 0,
         (x, y)      => 1 + x + y,
     };
-    assert!(r == 1);
+    assert_eq!(r, 1);
     let r = match (0,7) {
         (0, self::m::aha) => 0,
         (x, y)      => 1 + x + y,
     };
-    assert!(r == 0);
+    assert_eq!(r, 0);
 }
 
 pub fn main () {
index 984f675b4dc7ddab5e0ba6183ebcc25d4ca74d2b..dfb23aabf191d4253a065a0f0e3848e46d8df84f 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test #9384
-
 // shouldn't affect evaluation of $ex.
 macro_rules! bad_macro { ($ex:expr) => (
     {match 9 {_x => $ex}}
index 5eecf27db677bec2f0ec87f4add5a46ff439710e..405a3549cf18c762522cc1638a1f188888f61fbd 100644 (file)
 // temporary. Issue #19147.
 
 
-#![feature(core)]
+#![feature(slice_bytes)]
 
 use std::slice;
 
-pub type IoResult<T> = Result<T, ()>;
-
 trait MyWriter {
-    fn my_write(&mut self, buf: &[u8]) -> IoResult<()>;
+    fn my_write(&mut self, buf: &[u8]) -> Result<(), ()>;
 }
 
 impl<'a> MyWriter for &'a mut [u8] {
-    fn my_write(&mut self, buf: &[u8]) -> IoResult<()> {
+    fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> {
         slice::bytes::copy_memory(buf, *self);
 
         let write_len = buf.len();
index acda78af5c32d299baed7401677b5e0bfb2f3ba0..e7615711b4cfdb66c06b2fd472846326856caf5c 100644 (file)
@@ -27,5 +27,5 @@ fn main() {
 
     x.foo(&x);
 
-    assert!(method_self_arg1::get_count() == 2*3*3*3*5*5*5*7*7*7);
+    assert_eq!(method_self_arg1::get_count(), 2*3*3*3*5*5*5*7*7*7);
 }
index 0aea4139b0c37922843a8294144023cd82c8f046..0a1efc96fcfee5a4e7c58ed0b21a45a3d695b2ca 100644 (file)
@@ -31,5 +31,5 @@ fn main() {
 
     x.run_trait();
 
-    assert!(method_self_arg2::get_count() == 2*2*3*3*5*5*7*7*11*11*13*13*17);
+    assert_eq!(method_self_arg2::get_count(), 2*2*3*3*5*5*7*7*11*11*13*13*17);
 }
index 2ba3e78ef1504273dcea8dcde4754fed783e9534..d93cf2b0983ee85730c68881730d0323d508f582 100644 (file)
@@ -76,5 +76,5 @@ fn main() {
 
     x.baz();
 
-    unsafe { assert!(COUNT == 2*2*3*3*5*5*7*7*11*11*13*13*17); }
+    unsafe { assert_eq!(COUNT, 2*2*3*3*5*5*7*7*11*11*13*13*17); }
 }
index 543133a3268f8074e525899e3428510c24c8ab1c..4361c9b05635c74affb1f005f2692ce98c68f9e4 100644 (file)
@@ -55,5 +55,5 @@ fn main() {
 
     x.foo(&x);
 
-    unsafe { assert!(COUNT == 2*3*3*3*5*5*5*7*7*7); }
+    unsafe { assert_eq!(COUNT, 2*3*3*3*5*5*5*7*7*7); }
 }
index 86dd1a04532b47b83b9e0a542117e9eaeb3df58f..62bde45cd3dc0c8675c6577d7c23d24ab8110970 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(iter_min_max, cmp_partial, iter_cmp)]
+
 use std::fmt::Debug;
 use std::cmp::{self, PartialOrd, Ordering};
 use std::iter::MinMaxResult::MinMax;
index e309fa14302ca8911c930c93d3d51eff16b63f88..b28e5ec64de345d1d8942d8721b2d1cae8f060db 100644 (file)
@@ -19,7 +19,7 @@ impl<A> vec_monad<A> for Vec<A> {
     fn bind<B, F>(&self, mut f: F) -> Vec<B> where F: FnMut(&A) -> Vec<B> {
         let mut r = Vec::new();
         for elt in self {
-            r.extend(f(elt).into_iter());
+            r.extend(f(elt));
         }
         r
     }
index e4dc82f9801d1d498cba14c1c2a98248efdd4e1b..2babf19e164784ec6d5c9c62607ba694f3e969ed 100644 (file)
@@ -17,5 +17,5 @@ struct X { x: isize, y: isize, z: isize }
 pub fn main() {
     let x: Box<_> = box X{x: 1, y: 2, z: 3};
     let y = x;
-    assert!((y.y == 2));
+    assert_eq!(y.y, 2);
 }
index 0c89c89eb8aa04f23311965e338ac51045e0abd1..926e28ed155f55c77688c564ad8b1ff5245458b9 100644 (file)
@@ -14,4 +14,4 @@
 
 struct X { x: isize, y: isize, z: isize }
 
-pub fn main() { let x: Box<_> = box X {x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); }
+pub fn main() { let x: Box<_> = box X {x: 1, y: 2, z: 3}; let y = x; assert_eq!(y.y, 2); }
index 9f80ecf29793553b631e530a04e24907fb055bdc..153da8e1339a6f56fd3edd1125c6be75a1e45ee7 100644 (file)
@@ -25,5 +25,5 @@ fn test(foo: Box<Triple>) -> Box<Triple> {
 pub fn main() {
     let x = box Triple{a: 1, b: 2, c: 3};
     let y = test(x);
-    assert!((y.c == 3));
+    assert_eq!(y.c, 3);
 }
index fa69731963a30fa0d0f61c14292b5dc1fd1b7296..bed339e158637e9ae658c9c482a72c141c66e115 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-fn test(foo: Box<Vec<isize>> ) { assert!(((*foo)[0] == 10)); }
+fn test(foo: Box<Vec<isize>> ) { assert_eq!((*foo)[0], 10); }
 
 pub fn main() {
     let x = box vec!(10);
index 6e22deed269da9fb4eb1598e64dd6d120cc771b9..a6a26ab357876c85ac4e7da281fed148b5c8a33f 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-fn test(foo: Box<Vec<isize>>) { assert!(((*foo)[0] == 10)); }
+fn test(foo: Box<Vec<isize>>) { assert_eq!((*foo)[0], 10); }
 
 pub fn main() {
     let x = box vec!(10);
index 0ff9a35874bfc9b82f8e98edbd3ac820e513d57a..1883c66987e00517b6a0a15ab65083d5f2033d32 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 
-fn test(foo: isize) { assert!((foo == 10)); }
+fn test(foo: isize) { assert_eq!(foo, 10); }
 
 pub fn main() { let x = 10; test(x); }
index 1079857c1b387a6114199cb95aa7a606e4a719e8..3b060bb18868b3f30d9247bbf77ca310e83788e0 100644 (file)
@@ -12,5 +12,5 @@
 pub fn main() {
     let x = 10;
     let y = x;
-    assert!((y == 10));
+    assert_eq!(y, 10);
 }
index f415a7f2d668c8815130d0e440d63a5a9ffe6e23..010f656d53141521cbead35054a0d0abd5b3b1ca 100644 (file)
@@ -18,7 +18,7 @@ fn f(mut y: Box<isize>) {
 }
 
 fn g() {
-    let frob = |mut q: Box<isize>| { *q = 2; assert!(*q == 2); };
+    let frob = |mut q: Box<isize>| { *q = 2; assert_eq!(*q, 2); };
     let w = box 37;
     frob(w);
 
index 1766e65b9c7346813f58a3204bfa7f112a022d69..8b5b290aa6fb4cd83acdf12ffea8ac6dde89a943 100644 (file)
@@ -18,7 +18,7 @@ fn test1() {
 fn test2() {
     let mut ints = [0; 32];
     for i in &mut ints { *i += 22; }
-    for i in &ints { assert!(*i == 22); }
+    for i in &ints { assert_eq!(*i, 22); }
 }
 
 pub fn main() {
index 60cf795c918bb1692e5c749ff96b96cd92568808..89ac626158392f73f33da2da2c93039add3d0f0b 100644 (file)
 // the contents implement Drop and we hit a panic in the middle of
 // construction.
 
+#![feature(const_fn)]
 
 use std::thread;
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 struct D(u8);
 
index 95168b1bff7886a54df50f8b20f5d78c9baacfcb..b5a54a90ae758ef778d7ebbbdb372b45819f21b5 100644 (file)
@@ -13,8 +13,8 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-#![allow(unknown_features)]
-#![feature(box_syntax, alloc)]
+#![allow(warnings)]
+#![feature(box_syntax, box_heap)]
 
 // Tests that the new `box` syntax works with unique pointers.
 
index bfad79e92d2c2c71eb38343ae66d8e83ead6afba..83c2dadcd2f7c35a5d6772c7b3c3ca242c32709b 100644 (file)
@@ -19,7 +19,7 @@ pub fn main() {
     assert_eq!(s, "⨐⨁⪠");
 
     let s = "\\{20}";
-    let mut correct_s = String::from_str("\\");
+    let mut correct_s = String::from("\\");
     correct_s.push_str("{20}");
     assert_eq!(s, correct_s);
 }
diff --git a/src/test/run-pass/no-std-xcrate.rs b/src/test/run-pass/no-std-xcrate.rs
deleted file mode 100644 (file)
index f149b86..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test #9839
-// aux-build:no_std_crate.rs
-
-// This tests that crates which link to std can also be linked to crates with
-// #[no_std] that have no lang items.
-
-extern crate no_std_crate;
-
-pub fn main() {
-    no_std_crate::foo();
-}
diff --git a/src/test/run-pass/no-std-xcrate2.rs b/src/test/run-pass/no-std-xcrate2.rs
deleted file mode 100644 (file)
index 43f6b27..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test: this has weird linking problems on Linux, and it probably needs a
-//             solution along the lines of disabling segmented stacks and/or the
-//             stack checks.
-// aux-build:no_std_crate.rs
-
-// This tests that libraries built with #[no_std] can be linked to crates with
-// #[no_std] and actually run.
-
-#![feature(no_std)]
-#![no_std]
-
-extern crate no_std_crate;
-
-// This is an unfortunate thing to have to do on Linux :(
-#[cfg(target_os = "linux")]
-#[doc(hidden)]
-pub mod linkhack {
-    #[link_args="-lrustrt -lrt"]
-    extern {}
-}
-
-#[start]
-pub fn main(_: isize, _: **u8, _: *u8) -> isize {
-    no_std_crate::foo();
-    0
-}
index ced2b24f36cfe73eb7e120fecc104f9a5bcb37d3..cfd3bb49f34d45f9750e5888e704fedc8e619569 100644 (file)
@@ -40,7 +40,7 @@ impl<T> E<T> {
 
 macro_rules! check_option {
     ($e:expr, $T:ty) => {{
-        check_option!($e, $T, |ptr| assert!(*ptr == $e));
+        check_option!($e, $T, |ptr| assert_eq!(*ptr, $e));
     }};
     ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{
         assert!(option::Option::None::<$T>.is_none());
@@ -53,7 +53,7 @@ macro_rules! check_option {
 
 macro_rules! check_fancy {
     ($e:expr, $T:ty) => {{
-        check_fancy!($e, $T, |ptr| assert!(*ptr == $e));
+        check_fancy!($e, $T, |ptr| assert_eq!(*ptr, $e));
     }};
     ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{
         assert!(E::Nothing::<$T>((), ((), ()), [23; 0]).is_none());
@@ -81,6 +81,6 @@ pub fn main() {
     check_type!(vec!(20, 22), Vec<isize> );
     let mint: usize = unsafe { mem::transmute(main) };
     check_type!(main, fn(), |pthing| {
-        assert!(mint == unsafe { mem::transmute(*pthing) })
+        assert_eq!(mint, unsafe { mem::transmute(*pthing) })
     });
 }
index 78834ef914d5997ebd3d92da8fe47e664785fd29..86ca8f3325a82143a3ed38ed67aae0df9120e5d1 100644 (file)
@@ -13,4 +13,4 @@
 
 // Testcase for issue #130, operator associativity.
 
-pub fn main() { assert!((3 * 5 / 2 == 7)); }
+pub fn main() { assert_eq!(3 * 5 / 2, 7); }
index ed11c8c0baeccdb6cfb263e4d2733ec75ecb293b..38ed90a45471b3758d2bf4d726157118e3691e0b 100644 (file)
@@ -43,5 +43,5 @@ impl Foo {
 pub fn main() {
     let x: DerefWithHelper<Option<Foo>, Foo> =
         DerefWithHelper { helper: Some(Foo {x: 5}), value: Foo { x: 2 } };
-    assert!(x.foo() == 5);
+    assert_eq!(x.foo(), 5);
 }
index 5e924d015b619ca712aa6101f2c89794d21199a5..97da5fc8c09e9cf22da24252aa1dcae1a6cc7f76 100644 (file)
@@ -34,11 +34,11 @@ pub fn main() {
     let s = Rc::new("foo".to_string());
     assert_eq!(&**s, "foo");
 
-    let mut_s = Rc::new(RefCell::new(String::from_str("foo")));
+    let mut_s = Rc::new(RefCell::new(String::from("foo")));
     mut_s.borrow_mut().push_str("bar");
     // HACK assert_eq! would panic here because it stores the LHS and RHS in two locals.
-    assert!(&**mut_s.borrow() == "foobar");
-    assert!(&**mut_s.borrow_mut() == "foobar");
+    assert_eq!(&**mut_s.borrow(), "foobar");
+    assert_eq!(&**mut_s.borrow_mut(), "foobar");
 
     let p = Rc::new(RefCell::new(Point {x: 1, y: 2}));
     p.borrow_mut().x = 3;
index 6d8bb30c83755ffd37a5928d6f4ee5ec61ec53d2..8541c1c0a898684e75d81875c97310c77ebdfa73 100644 (file)
@@ -34,11 +34,11 @@ pub fn main() {
     assert_eq!(*s, "foo".to_string());
     assert_eq!((*s), "foo");
 
-    let mut_s = Rc::new(RefCell::new(String::from_str("foo")));
+    let mut_s = Rc::new(RefCell::new(String::from("foo")));
     (*(*mut_s).borrow_mut()).push_str("bar");
     // assert_eq! would panic here because it stores the LHS and RHS in two locals.
-    assert!((*(*mut_s).borrow()) == "foobar");
-    assert!((*(*mut_s).borrow_mut()) == "foobar");
+    assert_eq!((*(*mut_s).borrow()), "foobar");
+    assert_eq!((*(*mut_s).borrow_mut()), "foobar");
 
     let p = Rc::new(RefCell::new(Point {x: 1, y: 2}));
     (*(*p).borrow_mut()).x = 3;
index 455099f1eba8f747ee7ef0ef926f51be30b166c8..e0f61fd84974ae1ecf207b8792346d34be77b14d 100644 (file)
@@ -52,9 +52,9 @@ pub fn main() {
     list.push(foo.clone(), 22);
     list.push(bar.clone(), 44);
 
-    assert!(list[&foo] == 22);
-    assert!(list[&bar] == 44);
+    assert_eq!(list[&foo], 22);
+    assert_eq!(list[&bar], 44);
 
-    assert!(list[&foo] == 22);
-    assert!(list[&bar] == 44);
+    assert_eq!(list[&foo], 22);
+    assert_eq!(list[&bar], 44);
 }
diff --git a/src/test/run-pass/overloaded_deref_with_ref_pattern.rs b/src/test/run-pass/overloaded_deref_with_ref_pattern.rs
new file mode 100644 (file)
index 0000000..f72d496
--- /dev/null
@@ -0,0 +1,102 @@
+// 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 choose Deref or DerefMut appropriately based on mutability of ref bindings (#15609).
+
+use std::ops::{Deref, DerefMut};
+
+struct DerefOk<T>(T);
+struct DerefMutOk<T>(T);
+
+impl<T> Deref for DerefOk<T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for DerefOk<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        panic!()
+    }
+}
+
+impl<T> Deref for DerefMutOk<T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+impl<T> DerefMut for DerefMutOk<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+fn main() {
+    // Check that mutable ref binding in match picks DerefMut
+    let mut b = DerefMutOk(0);
+    match *b {
+        ref mut n => n,
+    };
+
+    // Check that mutable ref binding in let picks DerefMut
+    let mut y = DerefMutOk(1);
+    let ref mut z = *y;
+
+    // Check that immutable ref binding in match picks Deref
+    let mut b = DerefOk(2);
+    match *b {
+        ref n => n,
+    };
+
+    // Check that immutable ref binding in let picks Deref
+    let mut y = DerefOk(3);
+    let ref z = *y;
+
+    // Check that mixed mutable/immutable ref binding in match picks DerefMut
+    let mut b = DerefMutOk((0, 9));
+    match *b {
+        (ref mut n, ref m) => (n, m),
+    };
+
+    let mut b = DerefMutOk((0, 9));
+    match *b {
+        (ref n, ref mut m) => (n, m),
+    };
+
+    // Check that mixed mutable/immutable ref binding in let picks DerefMut
+    let mut y = DerefMutOk((1, 8));
+    let (ref mut z, ref a) = *y;
+
+    let mut y = DerefMutOk((1, 8));
+    let (ref z, ref mut a) = *y;
+
+    // Check that multiple immutable ref bindings in match picks Deref
+    let mut b = DerefOk((2, 7));
+    match *b {
+        (ref n, ref m) => (n, m),
+    };
+
+    // Check that multiple immutable ref bindings in let picks Deref
+    let mut y = DerefOk((3, 6));
+    let (ref z, ref a) = *y;
+
+    // Check that multiple mutable ref bindings in match picks DerefMut
+    let mut b = DerefMutOk((4, 5));
+    match *b {
+        (ref mut n, ref mut m) => (n, m),
+    };
+
+    // Check that multiple mutable ref bindings in let picks DerefMut
+    let mut y = DerefMutOk((5, 4));
+    let (ref mut z, ref mut a) = *y;
+}
diff --git a/src/test/run-pass/overloaded_deref_with_ref_pattern_issue15609.rs b/src/test/run-pass/overloaded_deref_with_ref_pattern_issue15609.rs
new file mode 100644 (file)
index 0000000..e5eb6ab
--- /dev/null
@@ -0,0 +1,44 @@
+// 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 choose Deref or DerefMut appropriately based on mutability of ref bindings (#15609).
+
+fn main() {
+    use std::cell::RefCell;
+
+    struct S {
+        node: E,
+    }
+
+    enum E {
+        Foo(u32),
+        Bar,
+    }
+
+    // Check match
+    let x = RefCell::new(S { node: E::Foo(0) });
+
+    let mut b = x.borrow_mut();
+    match b.node {
+        E::Foo(ref mut n) => *n += 1,
+        _ => (),
+    }
+
+    // Check let
+    let x = RefCell::new(0);
+    let mut y = x.borrow_mut();
+    let ref mut z = *y;
+
+    fn foo(a: &mut RefCell<Option<String>>) {
+        if let Some(ref mut s) = *a.borrow_mut() {
+            s.push('a')
+        }
+    }
+}
index e03772ddf9ff79d7ed95e6a3a9dcb2a62b223c16..b962a5c79338214ad24ba17de2ed1353a757a400 100644 (file)
@@ -23,7 +23,7 @@ pub fn main() {
         let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 };
         let transd : [u8; 9] = mem::transmute(s);
         // Don't worry about endianness, the numbers are palindromic.
-        assert!(transd ==
+        assert_eq!(transd,
                    [0xff, 0xff, 0xff, 0xff,
                     1,
                     0xaa, 0xaa, 0xaa, 0xaa]);
@@ -32,7 +32,7 @@ pub fn main() {
         let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16};
         let transd : [u8; 4] = mem::transmute(s);
         // Again, no endianness problems.
-        assert!(transd ==
+        assert_eq!(transd,
                    [1, 2, 0b10000001, 0b10000001]);
     }
 }
index 2ac07a5d7eafc873868e22554293c557f9d089ee..92308c9fc3e4e0eddebe36707b3cf215c32144fc 100644 (file)
@@ -27,11 +27,11 @@ pub fn main() {
     unsafe {
         let s4 = S4 { a: 1, b: [2,3,4] };
         let transd : [u8; 4] = mem::transmute(s4);
-        assert!(transd == [1, 2, 3, 4]);
+        assert_eq!(transd, [1, 2, 3, 4]);
 
         let s5 = S5 { a: 1, b: 0xff_00_00_ff };
         let transd : [u8; 5] = mem::transmute(s5);
         // Don't worry about endianness, the u32 is palindromic.
-        assert!(transd == [1, 0xff, 0, 0, 0xff]);
+        assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
     }
 }
index 376aadc735b60cc0e96723e3e85952a220e16d8c..411c1807a16b71491410c7c4bfedf810985dcd2f 100644 (file)
@@ -21,11 +21,11 @@ pub fn main() {
     unsafe {
         let s4 = S4(1, [2,3,4]);
         let transd : [u8; 4] = mem::transmute(s4);
-        assert!(transd == [1, 2, 3, 4]);
+        assert_eq!(transd, [1, 2, 3, 4]);
 
         let s5 = S5(1, 0xff_00_00_ff);
         let transd : [u8; 5] = mem::transmute(s5);
         // Don't worry about endianness, the u32 is palindromic.
-        assert!(transd == [1, 0xff, 0, 0, 0xff]);
+        assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
     }
 }
diff --git a/src/test/run-pass/parallel-codegen-closures.rs b/src/test/run-pass/parallel-codegen-closures.rs
new file mode 100644 (file)
index 0000000..5ba0fe0
--- /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.
+
+// Tests parallel codegen - this can fail if the symbol for the anonymous
+// closure in `sum` pollutes the second codegen unit from the first.
+
+// compile-flags: -C codegen_units=2
+
+#![feature(core)]
+#![feature(iter_arith)]
+
+mod a {
+    fn foo() {
+        let x = ["a", "bob", "c"];
+        let len: usize = x.iter().map(|s| s.len()).sum();
+    }
+}
+
+mod b {
+    fn bar() {
+        let x = ["a", "bob", "c"];
+        let len: usize = x.iter().map(|s| s.len()).sum();
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/preempt.rs b/src/test/run-pass/preempt.rs
deleted file mode 100644 (file)
index 7e5e418..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-// This checks that preemption works.
-
-// note: halfway done porting to modern rust
-use std::comm;
-
-fn starve_main(alive: Receiver<isize>) {
-    println!("signalling main");
-    alive.recv();
-    println!("starving main");
-    let mut i: isize = 0;
-    loop { i += 1; }
-}
-
-pub fn main() {
-    let (port, chan) = stream();
-
-    println!("main started");
-    spawn(move|| {
-        starve_main(port);
-    });
-    let mut i: isize = 0;
-    println!("main waiting for alive signal");
-    chan.send(i);
-    println!("main got alive signal");
-    while i < 50 { println!("main iterated"); i += 1; }
-    println!("main completed");
-}
diff --git a/src/test/run-pass/process-detach.rs b/src/test/run-pass/process-detach.rs
deleted file mode 100644 (file)
index 4c078a6..0000000
+++ /dev/null
@@ -1,49 +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.
-
-// ignore-test
-
-// FIXME: this test is being ignored until signals are implemented
-
-// This test ensures that the 'detach' field on processes does the right thing.
-// By detaching the child process, they should be put into a separate process
-// group. We test this by spawning a detached process, then killing our own
-// group with a signal.
-//
-// Note that the first thing we do is put ourselves in our own process group so
-// we don't interfere with other running tests.
-
-extern crate libc;
-
-use std::io::process;
-use std::io::process::Command;
-use std::io::signal::{Listener, Interrupt};
-
-fn main() {
-    unsafe { libc::setsid(); }
-
-    // we shouldn't die because of an interrupt
-    let mut l = Listener::new();
-    l.register(Interrupt).unwrap();
-
-    // spawn the child
-    let mut p = Command::new("/bin/sh").arg("-c").arg("read a").detached().spawn().unwrap();
-
-    // send an interrupt to everyone in our process group
-    unsafe { libc::funcs::posix88::signal::kill(0, libc::SIGINT); }
-
-    // Wait for the child process to die (terminate it's stdin and the read
-    // should fail).
-    drop(p.stdin.take());
-    match p.wait().unwrap() {
-        process::ExitStatus(..) => {}
-        process::ExitSignal(..) => panic!()
-    }
-}
diff --git a/src/test/run-pass/process-sigpipe.rs b/src/test/run-pass/process-sigpipe.rs
new file mode 100644 (file)
index 0000000..5bff4fa
--- /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.
+
+// ignore-android since the dynamic linker sets a SIGPIPE handler (to do
+// a crash report) so inheritance is moot on the entire platform
+
+// libstd ignores SIGPIPE, and other libraries may set signal masks.
+// Make sure that these behaviors don't get inherited to children
+// spawned via std::process, since they're needed for traditional UNIX
+// filter behavior. This test checks that `yes | head` terminates
+// (instead of running forever), and that it does not print an error
+// message about a broken pipe.
+
+use std::process;
+use std::thread;
+
+#[cfg(unix)]
+fn main() {
+    // Just in case `yes` doesn't check for EPIPE...
+    thread::spawn(|| {
+        thread::sleep_ms(5000);
+        process::exit(1);
+    });
+    let output = process::Command::new("sh").arg("-c").arg("yes | head").output().unwrap();
+    assert!(output.status.success());
+    assert!(output.stderr.len() == 0);
+}
+
+#[cfg(not(unix))]
+fn main() {
+    // Not worried about signal masks on other platforms
+}
index 03a8af319e81962efce63ba759c79fb4b467cfad..24261772add0353a3ecb25055132e5abe03b9142 100644 (file)
@@ -23,7 +23,7 @@ pub fn main() {
         assert!(i >= 0 && i < 10);
         count += i;
     }
-    assert!(count == 45);
+    assert_eq!(count, 45);
 
     let mut count = 0;
     let mut range = 0_usize..10;
@@ -31,7 +31,7 @@ pub fn main() {
         assert!(i >= 0 && i < 10);
         count += i;
     }
-    assert!(count == 45);
+    assert_eq!(count, 45);
 
     let mut count = 0;
     let mut rf = 3_usize..;
@@ -39,7 +39,7 @@ pub fn main() {
         assert!(i >= 3 && i < 13);
         count += i;
     }
-    assert!(count == 75);
+    assert_eq!(count, 75);
 
     let _ = 0_usize..4+4-3;
     let _ = 0..foo();
index 807e23c81cf4f699db227a209407dbb708d22183..eb404751ee6f99bc7ff579742c2e03a075fab59e 100644 (file)
@@ -22,30 +22,30 @@ impl Foo {
 
 fn main() {
     let x = 1+3..4+5;
-    assert!(x == (4..9));
+    assert_eq!(x, (4..9));
 
     let x = 1..4+5;
-    assert!(x == (1..9));
+    assert_eq!(x, (1..9));
 
     let x = 1+3..4;
-    assert!(x == (4..4));
+    assert_eq!(x, (4..4));
 
     let a = Foo { foo: 3 };
     let x = a.foo..a.bar();
-    assert!(x == (3..5));
+    assert_eq!(x, (3..5));
 
     let x = 1+3..;
-    assert!(x == (4..));
+    assert_eq!(x, (4..));
     let x = ..1+3;
-    assert!(x == (..4));
+    assert_eq!(x, (..4));
 
     let a = &[0, 1, 2, 3, 4, 5, 6];
     let x = &a[1+1..2+2];
-    assert!(x == &a[2..4]);
+    assert_eq!(x, &a[2..4]);
     let x = &a[..1+2];
-    assert!(x == &a[..3]);
+    assert_eq!(x, &a[..3]);
     let x = &a[1+2..];
-    assert!(x == &a[3..]);
+    assert_eq!(x, &a[3..]);
 
     for _i in 2+4..10-3 {}
 
@@ -54,8 +54,8 @@ fn main() {
     for _ in 1.. { break; }
 
     let x = [1]..[2];
-    assert!(x == (([1])..([2])));
+    assert_eq!(x, (([1])..([2])));
 
     let y = ..;
-    assert!(y == (..));
+    assert_eq!(y, (..));
 }
index 29e45ce8a9ad5e7e3c25e66e033539e555839ed8..56b15c243618f4d5b621659698d17efd33b60a67 100644 (file)
@@ -14,6 +14,6 @@
 
 struct Point {x: isize, y: isize, z: isize}
 
-fn f(p: Point) { assert!((p.z == 12)); }
+fn f(p: Point) { assert_eq!(p.z, 12); }
 
 pub fn main() { let x: Point = Point {x: 10, y: 11, z: 12}; f(x); }
index cd9cc0901202c45d6d061c449b8e9ec7481d7ba8..a9bd967ca765a61a335c012f26d223432cb7af1d 100644 (file)
@@ -13,7 +13,7 @@
 // Ideally this would be revised to use no_std, but for now it serves
 // well enough to reproduce (and illustrate) the bug from #16687.
 
-#![feature(alloc)]
+#![feature(heap_api, alloc, oom)]
 
 extern crate alloc;
 
index d1c1ec43b40f0c1ed97a75f0a932d2b4dc0745c9..df034df73624d55cdfeafbae1f6ea5b2fe09d3be 100644 (file)
@@ -14,8 +14,8 @@
 
 use std::cmp::PartialEq;
 
-fn f<T:PartialEq>(o: &mut Option<T>) {
-    assert!(*o == None);
+fn f<T:PartialEq+std::fmt::Debug>(o: &mut Option<T>) {
+    assert_eq!(*o, None);
 }
 
 pub fn main() {
index a040d680f9da890d05278f34f8f0a81d87033583..fc85aa8b51025a84446615531edf05a8e72b2f97 100644 (file)
@@ -13,5 +13,5 @@ static FOO: [isize; 4] = [32; 4];
 static BAR: [isize; 4] = [32, 32, 32, 32];
 
 pub fn main() {
-    assert!(FOO == BAR);
+    assert_eq!(FOO, BAR);
 }
index d3bdd54624239dcec40799964800f3c49f69227a..6159b24165e44db866e84c78cbc9fc49212b9071 100644 (file)
@@ -11,4 +11,4 @@
 
 const foo: isize = 4 >> 1;
 enum bs { thing = foo }
-pub fn main() { assert!((bs::thing as isize == foo)); }
+pub fn main() { assert_eq!(bs::thing as isize, foo); }
index 5b2b8655442c892ea5a4ef108b561f3c1c41821d..c92a9ca8480ca7c5fc979d813997196f5e2a4044 100644 (file)
@@ -32,7 +32,7 @@ fn shrinky_pointer(i: &Cell<isize>) -> shrinky_pointer {
 
 pub fn main() {
     let my_total = &Cell::new(10);
-    { let pt = shrinky_pointer(my_total); assert!((pt.look_at() == 10)); }
+    { let pt = shrinky_pointer(my_total); assert_eq!(pt.look_at(), 10); }
     println!("my_total = {}", my_total.get());
     assert_eq!(my_total.get(), 9);
 }
diff --git a/src/test/run-pass/rfc-1014-2.rs b/src/test/run-pass/rfc-1014-2.rs
new file mode 100644 (file)
index 0000000..ad76daa
--- /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.
+#![feature(libc)]
+
+extern crate libc;
+
+#[cfg(windows)]
+extern "system" {
+    fn SetStdHandle(nStdHandle: libc::DWORD, nHandle: libc::HANDLE) -> libc::BOOL;
+}
+
+#[cfg(windows)]
+fn close_stdout() {
+    const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
+    unsafe { SetStdHandle(STD_OUTPUT_HANDLE, 0 as libc::HANDLE); }
+}
+
+#[cfg(windows)]
+fn main() {
+    close_stdout();
+    println!("hello world");
+}
+
+#[cfg(not(windows))]
+fn main() {}
diff --git a/src/test/run-pass/rfc-1014.rs b/src/test/run-pass/rfc-1014.rs
new file mode 100644 (file)
index 0000000..98cad4e
--- /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(libc)]
+
+extern crate libc;
+
+#[cfg(windows)]
+extern "system" {
+    pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
+}
+
+#[cfg(windows)]
+fn close_stdout() {
+    const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
+    unsafe { libc::CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); }
+}
+
+#[cfg(not(windows))]
+fn close_stdout() {
+    unsafe { libc::close(libc::STDOUT_FILENO); }
+}
+
+fn main() {
+    close_stdout();
+    println!("hello world");
+}
index db543116d17a5c3c040574a6c5a1a2937f2372d0..2b2dcb6efb5d46af99a7c659d87b69e2e2085f56 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(start, std_misc)]
+#![feature(catch_panic, start)]
 
 use std::ffi::CStr;
 use std::process::{Command, Output};
-use std::rt::unwind::try;
+use std::thread;
 use std::str;
 
 #[start]
@@ -22,8 +22,8 @@ fn start(argc: isize, argv: *const *const u8) -> isize {
             match **argv.offset(1) as char {
                 '1' => {}
                 '2' => println!("foo"),
-                '3' => assert!(try(|| {}).is_ok()),
-                '4' => assert!(try(|| panic!()).is_err()),
+                '3' => assert!(thread::catch_panic(|| {}).is_ok()),
+                '4' => assert!(thread::catch_panic(|| panic!()).is_err()),
                 '5' => assert!(Command::new("test").spawn().is_err()),
                 _ => panic!()
             }
index 7314a65b60c0a6797bff185d886dc71423b87e86..a523340784c70bec746e5225627a29046394d84f 100644 (file)
@@ -20,9 +20,9 @@ use std::rc::Rc;
 pub fn main() {
    let mut x: Box<_> = box 3;
    x = x;
-   assert!(*x == 3);
+   assert_eq!(*x, 3);
 
    let mut x = Rc::new(3);
    x = x;
-   assert!(*x == 3);
+   assert_eq!(*x, 3);
 }
index cd47a0e86bda43497ddb6bdf8e0df7c005f511b0..5ef6e08f857c1609fff2a60c11941dadc6b3de43 100644 (file)
@@ -19,7 +19,7 @@ mod a {
 
 mod c {
     use a::b::a;
-    pub fn bar() { assert!((a::foo() == 1)); }
+    pub fn bar() { assert_eq!(a::foo(), 1); }
 }
 
 pub fn main() { c::bar(); }
index 5f0902d34d3e87a28a73fa8809742fca4bab9587..e40f4d30eb9785e080894856ba48670a10059e86 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
 #![feature(core, std_misc, scoped)]
 use std::thread;
 use std::sync::Mutex;
index 3b719d1806e1138b545de7f674c9ce40473d900a..b764fc6f1ec967143c1f00731debf9ba96ef8e73 100644 (file)
@@ -27,4 +27,4 @@ fn foo(c: Vec<isize> ) {
 
 enum t<T> { none, some(T), }
 
-pub fn main() { let x = 10; let x = x + 20; assert!((x == 30)); foo(Vec::new()); }
+pub fn main() { let x = 10; let x = x + 20; assert_eq!(x, 30); foo(Vec::new()); }
index 3ebf2a87361f6eccfbac5180ab2401d6d2ae78e2..4f5119f6a84e928e9a4b4a43aa2f95e3a1fbb0e3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-#![feature(core)]
+#![feature(core_simd)]
 
 use std::simd::{i32x4, f32x4, u32x4};
 
index 8dca78b28e802d686b1568373a2c04ac178a594e..c3eef0f9c3217a0e01fee6f2d7b921560a69eca4 100644 (file)
@@ -10,8 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(core)]
-#![feature(simd)]
+#![feature(core_simd)]
 
 pub fn main() {
     let _o = None::<std::simd::i32x4>;
diff --git a/src/test/run-pass/simd-shift-near-oflo.rs b/src/test/run-pass/simd-shift-near-oflo.rs
new file mode 100644 (file)
index 0000000..fee4637
--- /dev/null
@@ -0,0 +1,154 @@
+// 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 debug-assertions
+
+// Check that we do *not* overflow on a number of edge cases.
+// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
+
+#![feature(core_simd)]
+
+use std::simd::{i8x16, i16x8, i32x4, i64x2, u8x16, u16x8, u32x4, u64x2};
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn single_i8x16(x: i8) -> i8x16 { i8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x) }
+fn single_u8x16(x: u8) -> u8x16 { u8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x) }
+fn single_i16x8(x: i16) -> i16x8 { i16x8(0, 0, 0, 0, 0, 0, 0, x) }
+fn single_u16x8(x: u16) -> u16x8 { u16x8(0, 0, 0, 0, 0, 0, 0, x) }
+fn single_i32x4(x: i32) -> i32x4 { i32x4(0, 0, 0, x) }
+fn single_u32x4(x: u32) -> u32x4 { u32x4(0, 0, 0, x) }
+fn single_i64x2(x: i64) -> i64x2 { i64x2(0, x) }
+fn single_u64x2(x: u64) -> u64x2 { u64x2(0, x) }
+
+fn eq_i8x16(i8x16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15): i8x16,
+            i8x16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15): i8x16)
+            -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+        && (x8 == y8) && (x9 == y9) && (x10 == y10) && (x11 == y11)
+        && (x12 == y12) && (x13 == y13) && (x14 == y14) && (x15 == y15)
+}
+fn eq_u8x16(u8x16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15): u8x16,
+            u8x16(y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15): u8x16)
+            -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+        && (x8 == y8) && (x9 == y9) && (x10 == y10) && (x11 == y11)
+        && (x12 == y12) && (x13 == y13) && (x14 == y14) && (x15 == y15)
+}
+fn eq_i16x8(i16x8(x0, x1, x2, x3, x4, x5, x6, x7): i16x8,
+            i16x8(y0, y1, y2, y3, y4, y5, y6, y7): i16x8) -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+}
+fn eq_u16x8(u16x8(x0, x1, x2, x3, x4, x5, x6, x7): u16x8,
+            u16x8(y0, y1, y2, y3, y4, y5, y6, y7): u16x8) -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+        && (x4 == y4) && (x5 == y5) && (x6 == y6) && (x7 == y7)
+}
+fn eq_i32x4(i32x4(x0, x1, x2, x3): i32x4, i32x4(y0, y1, y2, y3): i32x4) -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+}
+fn eq_u32x4(u32x4(x0, x1, x2, x3): u32x4, u32x4(y0, y1, y2, y3): u32x4) -> bool {
+    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
+}
+fn eq_i64x2(i64x2(x0, x1): i64x2, i64x2(y0, y1): i64x2) -> bool {
+    (x0 == y0) && (x1 == y1)
+}
+fn eq_u64x2(u64x2(x0, x1): u64x2, u64x2(y0, y1): u64x2) -> bool {
+    (x0 == y0) && (x1 == y1)
+}
+
+fn main() {
+    test_left_shift();
+    test_right_shift();
+}
+
+fn test_left_shift() {
+    // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+    macro_rules! tests {
+        ($single:ident, $eq:ident, $max_rhs:expr, $expect:expr) => { {
+            let x = $single(1) << id($single(0));
+            assert!($eq(x, $single(1)));
+            let x = $single(1) << id($single($max_rhs));
+            assert!($eq(x, $single($expect)));
+            // high-order bits on LHS are silently discarded without panic.
+            let x = $single(3) << id($single($max_rhs));
+            assert!($eq(x, $single($expect)));
+        } }
+    }
+
+    let x = single_i8x16(1) << id(single_i8x16(0));
+    assert!(eq_i8x16(x, single_i8x16(1)));
+    let x = single_u8x16(1) << id(single_u8x16(0));
+    assert!(eq_u8x16(x, single_u8x16(1)));
+    let x = single_i8x16(1) << id(single_i8x16(7));
+    assert!(eq_i8x16(x, single_i8x16(std::i8::MIN)));
+    let x = single_u8x16(1) << id(single_u8x16(7));
+    assert!(eq_u8x16(x, single_u8x16(0x80)));
+    // high-order bits on LHS are silently discarded without panic.
+    let x = single_i8x16(3) << id(single_i8x16(7));
+    assert!(eq_i8x16(x, single_i8x16(std::i8::MIN)));
+    let x = single_u8x16(3) << id(single_u8x16(7));
+    assert!(eq_u8x16(x, single_u8x16(0x80)));
+
+    // above is (approximately) expanded from:
+    tests!(single_i8x16, eq_i8x16, 7, std::i8::MIN);
+    tests!(single_u8x16, eq_u8x16, 7, 0x80_u8);
+
+    tests!(single_i16x8, eq_i16x8, 15, std::i16::MIN);
+    tests!(single_u16x8, eq_u16x8, 15, 0x8000_u16);
+
+    tests!(single_i32x4, eq_i32x4, 31, std::i32::MIN);
+    tests!(single_u32x4, eq_u32x4, 31, 0x8000_0000_u32);
+
+    tests!(single_i64x2, eq_i64x2, 63, std::i64::MIN);
+    tests!(single_u64x2, eq_u64x2, 63, 0x8000_0000_0000_0000_u64);
+}
+
+fn test_right_shift() {
+    // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+    macro_rules! tests {
+        ($single_i:ident, $eq_i:ident, $single_u:ident, $eq_u:ident,
+         $max_rhs:expr, $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) => { {
+            let x = $single_i(1) >> id($single_i(0));
+            assert!($eq_i(x, $single_i(1)));
+            let x = $single_u(1) >> id($single_u(0));
+            assert!($eq_u(x, $single_u(1)));
+            let x = $single_u($highbit_i) >> id($single_u($max_rhs-1));
+            assert!($eq_u(x, $single_u(1)));
+            let x = $single_u($highbit_u) >> id($single_u($max_rhs));
+            assert!($eq_u(x, $single_u(1)));
+            // sign-bit is carried by arithmetic right shift
+            let x = $single_i($signbit_i) >> id($single_i($max_rhs));
+            assert!($eq_i(x, $single_i(-1)));
+            // low-order bits on LHS are silently discarded without panic.
+            let x = $single_u($highbit_i + 1) >> id($single_u($max_rhs-1));
+            assert!($eq_u(x, $single_u(1)));
+            let x = $single_u($highbit_u + 1) >> id($single_u($max_rhs));
+            assert!($eq_u(x, $single_u(1)));
+            let x = $single_i($signbit_i + 1) >> id($single_i($max_rhs));
+            assert!($eq_i(x, $single_i(-1)));
+        } }
+    }
+
+    tests!(single_i8x16, eq_i8x16, single_u8x16, eq_u8x16,
+           7, std::i8::MIN, 0x40_u8, 0x80_u8);
+    tests!(single_i16x8, eq_i16x8, single_u16x8, eq_u16x8,
+           15, std::i16::MIN, 0x4000_u16, 0x8000_u16);
+    tests!(single_i32x4, eq_i32x4, single_u32x4, eq_u32x4,
+           31, std::i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32);
+    tests!(single_i64x2, eq_i64x2, single_u64x2, eq_u64x2,
+           63, std::i64::MIN, 0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64);
+}
index 4762470a747351bf7405f456381452ae5f2c11b1..3a99fd9af932e9409d67463d7a6d9181e9f2a5c2 100644 (file)
 fn main() {
     let x: &[isize] = &[1, 2, 3, 4, 5];
     let cmp: &[isize] = &[1, 2, 3, 4, 5];
-    assert!(&x[..] == cmp);
+    assert_eq!(&x[..], cmp);
     let cmp: &[isize] = &[3, 4, 5];
-    assert!(&x[2..] == cmp);
+    assert_eq!(&x[2..], cmp);
     let cmp: &[isize] = &[1, 2, 3];
-    assert!(&x[..3] == cmp);
+    assert_eq!(&x[..3], cmp);
     let cmp: &[isize] = &[2, 3, 4];
-    assert!(&x[1..4] == cmp);
+    assert_eq!(&x[1..4], cmp);
 
     let x: Vec<isize> = vec![1, 2, 3, 4, 5];
     let cmp: &[isize] = &[1, 2, 3, 4, 5];
-    assert!(&x[..] == cmp);
+    assert_eq!(&x[..], cmp);
     let cmp: &[isize] = &[3, 4, 5];
-    assert!(&x[2..] == cmp);
+    assert_eq!(&x[2..], cmp);
     let cmp: &[isize] = &[1, 2, 3];
-    assert!(&x[..3] == cmp);
+    assert_eq!(&x[..3], cmp);
     let cmp: &[isize] = &[2, 3, 4];
-    assert!(&x[1..4] == cmp);
+    assert_eq!(&x[1..4], cmp);
 
     let x: &mut [isize] = &mut [1, 2, 3, 4, 5];
     {
         let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5];
-        assert!(&mut x[..] == cmp);
+        assert_eq!(&mut x[..], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [3, 4, 5];
-        assert!(&mut x[2..] == cmp);
+        assert_eq!(&mut x[2..], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [1, 2, 3];
-        assert!(&mut x[..3] == cmp);
+        assert_eq!(&mut x[..3], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [2, 3, 4];
-        assert!(&mut x[1..4] == cmp);
+        assert_eq!(&mut x[1..4], cmp);
     }
 
     let mut x: Vec<isize> = vec![1, 2, 3, 4, 5];
     {
         let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5];
-        assert!(&mut x[..] == cmp);
+        assert_eq!(&mut x[..], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [3, 4, 5];
-        assert!(&mut x[2..] == cmp);
+        assert_eq!(&mut x[2..], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [1, 2, 3];
-        assert!(&mut x[..3] == cmp);
+        assert_eq!(&mut x[..3], cmp);
     }
     {
         let cmp: &mut [isize] = &mut [2, 3, 4];
-        assert!(&mut x[1..4] == cmp);
+        assert_eq!(&mut x[1..4], cmp);
     }
 }
index 6fe510586c74822223e2da6790a2323b76a7ab60..ab22b820503af156b603fd5d619dc43ab4d6d717 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -C debug-assertions
 
-#![feature(core)]
+#![feature(iter_to_slice)]
 
 use std::slice;
 
index 854b03f917866464d8c0621de54e8e017a3fc9b1..ed949fe082877ae50c9d388d5ccff252227c85f0 100644 (file)
@@ -28,5 +28,5 @@ fn foo() {
 
 fn main() {
     let _ = thread::spawn(move|| foo()).join();
-    unsafe { assert!(DTOR_COUNT == 2); }
+    unsafe { assert_eq!(DTOR_COUNT, 2); }
 }
index 42a19342884b0176a7f67b5c7a6db03f3db97aea..4103c9495e102ca063b894a5713ec531968c0ed8 100644 (file)
@@ -32,5 +32,5 @@ fn foo() {
 
 fn main() {
     let _ = thread::spawn(move|| foo()).join();
-    unsafe { assert!(DTOR_COUNT == 2); }
+    unsafe { assert_eq!(DTOR_COUNT, 2); }
 }
index 60160bd668fa6d87aaccfa9f794c69b42e1a5b02..8e1d96d366973d3f894effaddb1107625e8d837b 100644 (file)
@@ -86,6 +86,6 @@ fn main() {
     &mut x[..Foo];
     &mut x[Foo..Foo];
     unsafe {
-        assert!(COUNT == 8);
+        assert_eq!(COUNT, 8);
     }
 }
index 1c34634c73da27990d689550c84964b95e511715..00be41a27d2c2727fa9e0c3880d3ebb2e5cc5740 100644 (file)
@@ -14,4 +14,4 @@ pub fn main() {
     thread::spawn(move|| child(10)).join().ok().unwrap();
 }
 
-fn child(i: isize) { println!("{}", i); assert!((i == 10)); }
+fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); }
diff --git a/src/test/run-pass/static-assert.rs b/src/test/run-pass/static-assert.rs
deleted file mode 100644 (file)
index e5583a3..0000000
+++ /dev/null
@@ -1,28 +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.
-
-// pretty-expanded FIXME #23616
-
-#![feature(static_assert)]
-
-#[static_assert]
-static b: bool = true;
-
-#[static_assert]
-static c: bool = 1 == 1;
-
-#[static_assert]
-static d: bool = 1 != 2;
-
-#[static_assert]
-static f: bool = (4/2) == 2;
-
-pub fn main() {
-}
index b916a1ae2be7d7760ce99bcc79de82b37f60a254..4dcb82c4b43b5c400557d6c387dd11e202419097 100644 (file)
@@ -30,16 +30,16 @@ fn static_bound_set(a: &'static mut libc::c_int) {
 }
 
 unsafe fn run() {
-    assert!(rust_dbg_static_mut == 3);
+    assert_eq!(rust_dbg_static_mut, 3);
     rust_dbg_static_mut = 4;
-    assert!(rust_dbg_static_mut == 4);
+    assert_eq!(rust_dbg_static_mut, 4);
     rust_dbg_static_mut_check_four();
     rust_dbg_static_mut += 1;
-    assert!(rust_dbg_static_mut == 5);
+    assert_eq!(rust_dbg_static_mut, 5);
     rust_dbg_static_mut *= 3;
-    assert!(rust_dbg_static_mut == 15);
+    assert_eq!(rust_dbg_static_mut, 15);
     rust_dbg_static_mut = -3;
-    assert!(rust_dbg_static_mut == -3);
+    assert_eq!(rust_dbg_static_mut, -3);
     static_bound(&rust_dbg_static_mut);
     static_bound_set(&mut rust_dbg_static_mut);
 }
index c819db94547962b515493cc816b86cd0f4b8c72a..5911b6cfa8504e4f22fd6b87517f6b84c92a14dd 100644 (file)
@@ -24,15 +24,15 @@ fn static_bound_set(a: &'static mut isize) {
 }
 
 unsafe fn run() {
-    assert!(static_mut_xc::a == 3);
+    assert_eq!(static_mut_xc::a, 3);
     static_mut_xc::a = 4;
-    assert!(static_mut_xc::a == 4);
+    assert_eq!(static_mut_xc::a, 4);
     static_mut_xc::a += 1;
-    assert!(static_mut_xc::a == 5);
+    assert_eq!(static_mut_xc::a, 5);
     static_mut_xc::a *= 3;
-    assert!(static_mut_xc::a == 15);
+    assert_eq!(static_mut_xc::a, 15);
     static_mut_xc::a = -3;
-    assert!(static_mut_xc::a == -3);
+    assert_eq!(static_mut_xc::a, -3);
     static_bound(&static_mut_xc::a);
     static_bound_set(&mut static_mut_xc::a);
 }
index 36314c5e14ac2d082a60094c5f04dfceb83bd4fb..b8e05c06c83b77387d4dfab97822ff6a2fff9f4d 100644 (file)
@@ -10,7 +10,8 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(std_misc, alloc, static_condvar)]
+#![feature(static_mutex, static_rwlock, static_condvar)]
+#![feature(arc_weak, semaphore)]
 
 use std::sync;
 
index 1d13e531004c8515274d0a216940e9b8f7785383..acd9e0675aed92ab2fbcc9837b3f4a2c3de87e27 100644 (file)
@@ -12,5 +12,5 @@
 fn main() {
     let x = "\\\\\
     ";
-    assert!(x == r"\\"); // extraneous whitespace stripped
+    assert_eq!(x, r"\\"); // extraneous whitespace stripped
 }
index 60f9c4465a01c8ff53c6a3a7afc9587e3122511f..b67eb205396b29cff30bdf088bc3877469b2c534 100644 (file)
@@ -11,8 +11,9 @@
 // Checks that functional-record-update order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
+#![feature(const_fn)]
 
-use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::{Ordering, AtomicUsize};
 
 struct W { wrapped: u32 }
 struct S { f0: W, _f1: i32 }
@@ -34,7 +35,7 @@ pub fn main() {
             "expect: 0x{:x} actual: 0x{:x}", expect, actual);
 }
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 fn event_log() -> usize {
     LOG.load(Ordering::SeqCst)
index 23a7e1ea71b8b11127dc4f2a5a78a6826236820c..20d27d8b309bbb9c35795c129ffa4d61c906d7de 100644 (file)
@@ -11,8 +11,9 @@
 // Checks that struct-literal expression order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
+#![feature(const_fn)]
 
-use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::{Ordering, AtomicUsize};
 
 struct W { wrapped: u32 }
 struct S { f0: W, _f1: i32 }
@@ -31,7 +32,7 @@ pub fn main() {
             "expect: 0x{:x} actual: 0x{:x}", expect, actual);
 }
 
-static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
+static LOG: AtomicUsize = AtomicUsize::new(0);
 
 fn event_log() -> usize {
     LOG.load(Ordering::SeqCst)
index 811b9dce4bc32889d2234fa4aba2ed6e97dee3ca..a47ae52f5902cfabfbaa8d1183d3d30b54087aff 100644 (file)
@@ -181,7 +181,6 @@ pub fn main() {
 
   println!("{:?}", true as isize);
   println!("{:?}", true as usize);
-  println!("{:?}", true as *const libc::FILE);
   println!("{:?}", true as i8);
   println!("{:?}", true as i16);
   println!("{:?}", true as i32);
@@ -190,8 +189,6 @@ pub fn main() {
   println!("{:?}", true as u16);
   println!("{:?}", true as u32);
   println!("{:?}", true as u64);
-  println!("{:?}", true as f32);
-  println!("{:?}", true as f64);
 
   println!("{:?}", 1f32 as isize);
   println!("{:?}", 1f32 as usize);
index d84ee104514d632841c63cbd5e2479bce931a60d..12e72aac38d4a6926997bb1cc2805aaef96486b7 100644 (file)
@@ -14,5 +14,6 @@ use std::mem::swap;
 pub fn main() {
     let mut x = 3; let mut y = 7;
     swap(&mut x, &mut y);
-    assert!((x == 7)); assert!((y == 3));
+    assert_eq!(x, 7);
+    assert_eq!(y, 3);
 }
index 7a845788592296ac769312d585de72f28025e95e..0ee04c4463b0fec858c485aaf82392b1a60d6b9a 100644 (file)
@@ -10,9 +10,9 @@
 
 // pretty-expanded FIXME #23616
 
-#![allow(unused_mut)]
+#![allow(warnings)]
 #![feature(collections)]
-#![feature(collections_drain)]
+#![feature(drain, enumset, collections_bound, btree_range, vecmap)]
 
 extern crate collections;
 
diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs
new file mode 100644 (file)
index 0000000..d76bf89
--- /dev/null
@@ -0,0 +1,121 @@
+// 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.
+
+// pretty-expanded FIXME #23616
+
+#![allow(warnings)]
+#![feature(iter_empty)]
+#![feature(iter_once)]
+#![feature(iter_unfold)]
+#![feature(range_inclusive)]
+#![feature(step_by)]
+#![feature(str_escape)]
+
+use std::iter::{empty, once, range_inclusive, repeat, Unfold};
+
+fn is_sync<T>(_: T) where T: Sync {}
+fn is_send<T>(_: T) where T: Send {}
+
+macro_rules! all_sync_send {
+    ($ctor:expr, $iter:ident) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter());
+        let mut y = $ctor;
+        is_send(y.$iter());
+    });
+    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter($( $param ),+));
+        let mut y = $ctor;
+        is_send(y.$iter($( $param ),+));
+    });
+    ($ctor:expr, $iter:ident, $($rest:tt)*) => ({
+        all_sync_send!($ctor, $iter);
+        all_sync_send!($ctor, $($rest)*);
+    });
+    ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({
+        all_sync_send!($ctor, $iter($( $param ),+));
+        all_sync_send!($ctor, $($rest)*);
+    });
+}
+
+macro_rules! all_sync_send_mutable_ref {
+    ($ctor:expr, $($iter:ident),+) => ({
+        $(
+            let mut x = $ctor;
+            is_sync((&mut x).$iter());
+            let mut y = $ctor;
+            is_send((&mut y).$iter());
+        )+
+    })
+}
+
+macro_rules! is_sync_send {
+    ($ctor:expr) => ({
+        let x = $ctor;
+        is_sync(x);
+        let y = $ctor;
+        is_send(y);
+    })
+}
+
+fn main() {
+    // for char.rs
+    all_sync_send!("Я", escape_default, escape_unicode);
+
+    // for iter.rs
+    all_sync_send_mutable_ref!([1], iter);
+
+    // Bytes implements DoubleEndedIterator
+    all_sync_send!("a".bytes(), rev);
+
+    let a = [1];
+    let b = [2];
+    all_sync_send!(a.iter(),
+                   cloned,
+                   cycle,
+                   chain([2].iter()),
+                   zip([2].iter()),
+                   map(|_| 1),
+                   filter(|_| true),
+                   filter_map(|_| Some(1)),
+                   enumerate,
+                   peekable,
+                   skip_while(|_| true),
+                   take_while(|_| true),
+                   skip(1),
+                   take(1),
+                   scan(1, |_, _| Some(1)),
+                   flat_map(|_| b.iter()),
+                   fuse,
+                   inspect(|_| ()));
+
+    is_sync_send!(Unfold::new(Some(1), |&mut v| v));
+    is_sync_send!((1..).step_by(2));
+    is_sync_send!(range_inclusive(1, 1));
+    is_sync_send!((1..2).step_by(2));
+    is_sync_send!((1..2));
+    is_sync_send!((1..));
+    is_sync_send!(repeat(1));
+    is_sync_send!(empty::<usize>());
+    is_sync_send!(once(1));
+
+    // for option.rs
+    // FIXME
+
+    // for result.rs
+    // FIXME
+
+    // for slice.rs
+    // FIXME
+
+    // for str/mod.rs
+    // FIXME
+}
index 61d6d3fdd3b717dd08c9753588096038b02033ca..d752015a4dcdc515acc03fa47d8dbea5ff090297 100644 (file)
@@ -2,6 +2,6 @@
 
 {
     assert!(file!().ends_with("includeme.fragment"));
-    assert!(line!() == 5u32);
+    assert_eq!(line!(), 5u32);
     format!("victory robot {}", line!())
 }
index 8834fd39d1d8845f135e14abf1bd9f56d1587e17..2f52e424936ea321874bb63c838cd8d1eaa2e6dc 100644 (file)
@@ -25,7 +25,7 @@ macro_rules! indirect_line { () => ( line!() ) }
 
 pub fn main() {
     assert_eq!(line!(), 27);
-    assert!((column!() == 4));
+    assert_eq!(column!(), 4);
     assert_eq!(indirect_line!(), 29);
     assert!((file!().ends_with("syntax-extension-source-utils.rs")));
     assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string());
index 6dc69656759de878423cf95d9a557fdcae9be6e6..9a2b3b1ff00178dd9c8663be09aae19b55b8c47c 100644 (file)
@@ -41,10 +41,10 @@ pub fn main() {
 }
 
 fn test_color(color: color, val: isize, name: String) {
-    //assert!(unsafe::transmute(color) == val);
+    //assert_eq!(unsafe::transmute(color), val);
     assert_eq!(color as isize, val);
-    assert!(get_color_alt(color) == name);
-    assert!(get_color_if(color) == name);
+    assert_eq!(get_color_alt(color), name);
+    assert_eq!(get_color_if(color), name);
 }
 
 fn get_color_alt(color: color) -> String {
index a796750ef88b7d999e4a289f893203ff6288930c..ced240502ed8b9fff17d2ab0d6f7a8d3a8d59f19 100644 (file)
@@ -20,10 +20,10 @@ fn start(tx: &Sender<Sender<String>>) {
     let mut a;
     let mut b;
     a = rx.recv().unwrap();
-    assert!(a == "A".to_string());
+    assert_eq!(a, "A".to_string());
     println!("{}", a);
     b = rx.recv().unwrap();
-    assert!(b == "B".to_string());
+    assert_eq!(b, "B".to_string());
     println!("{}", b);
 }
 
index 250ed58a8ef4c5040cd0d1389b68521695ff0193..9aa2badd80b94e4cda7245179293c4fb80df8c91 100644 (file)
@@ -100,13 +100,13 @@ pub fn main() {
 
 fn check_legs(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
     let mut legs = 0;
-    for pet in &*arc {
+    for pet in arc.iter() {
         legs += pet.num_legs();
     }
     assert!(legs == 12);
 }
 fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
-    for pet in &*arc {
+    for pet in arc.iter() {
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         pet.name(Box::new(|name| {
             assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
@@ -114,7 +114,7 @@ fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
     }
 }
 fn check_pedigree(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
-    for pet in &*arc {
+    for pet in arc.iter() {
         assert!(pet.of_good_pedigree());
     }
 }
diff --git a/src/test/run-pass/trait-contravariant-self.rs b/src/test/run-pass/trait-contravariant-self.rs
deleted file mode 100644 (file)
index 17c68d6..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// ignore-test
-
-// 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.
-
-// This is an interesting test case. We have a trait (Bar) that is
-// implemented for a `Box<Foo>` object (note: no bounds). And then we
-// have a `Box<Foo+Send>` object. The impl for `Box<Foo>` is applicable
-// to `Box<Foo+Send>` because:
-//
-// 1. The trait Bar is contravariant w/r/t Self because `Self` appears
-//    only in argument position.
-// 2. The impl provides `Bar for Box<Foo>`
-// 3. The fn `wants_bar()` requires `Bar for Box<Foo:Send>`.
-// 4. `Bar for Box<Foo> <: Bar for Box<Foo:Send>` because
-//    `Box<Foo:Send> <: Box<Foo>`.
-
-#![allow(unknown_features)]
-#![feature(box_syntax)]
-
-trait Foo { }
-struct SFoo;
-impl Foo for SFoo { }
-
-trait Bar { fn dummy(&self); }
-impl Bar for Box<Foo> { fn dummy(&self) { } }
-
-fn wants_bar<B:Bar>(b: &B) { }
-
-fn main() {
-    let x: Box<Foo+Send> = (box SFoo);
-    wants_bar(&x);
-}
index 10025a76f798f43b71f2b0c925b930067e706abb..e940f6c2126f32f301cecc95317848ecd004fbe7 100644 (file)
@@ -42,7 +42,7 @@ fn main() {
     T::foo(x);
     T::bar();
 
-    unsafe { assert!(COUNT == 12); }
+    unsafe { assert_eq!(COUNT, 12); }
 
     // Cross-crait case
     let x: &Bar = &Foo;
index 6074c8a71b0d047f8dc91008681e0cfab9e6129e..3d82ee67925043e03376c4dae4c1043a63150ac8 100644 (file)
@@ -32,5 +32,5 @@ fn mi(v: isize) -> MyInt { MyInt { val: v } }
 pub fn main() {
     let (x, y) = (mi(3), mi(5));
     let z = f(x, y);
-    assert!(z.val == 8)
+    assert_eq!(z.val, 8)
 }
index a29e0e932c07d329fe6969b303a0e37c389db35e..8fa628def79691c5f12386837f61b8538b112fd3 100644 (file)
@@ -29,16 +29,16 @@ impl<T:to_str> to_str for Vec<T> {
 }
 
 pub fn main() {
-    assert!(1.to_string_() == "1".to_string());
-    assert!((vec!(2, 3, 4)).to_string_() == "[2, 3, 4]".to_string());
+    assert_eq!(1.to_string_(), "1".to_string());
+    assert_eq!((vec!(2, 3, 4)).to_string_(), "[2, 3, 4]".to_string());
 
     fn indirect<T:to_str>(x: T) -> String {
         format!("{}!", x.to_string_())
     }
-    assert!(indirect(vec!(10, 20)) == "[10, 20]!".to_string());
+    assert_eq!(indirect(vec!(10, 20)), "[10, 20]!".to_string());
 
     fn indirect2<T:to_str>(x: T) -> String {
         indirect(x)
     }
-    assert!(indirect2(vec!(1)) == "[1]!".to_string());
+    assert_eq!(indirect2(vec!(1)), "[1]!".to_string());
 }
index cfd812400947e5e637b4986731c020aa81a64665..6b0faa2207b25f942583936b2a8fb99e11abe7fe 100644 (file)
@@ -10,7 +10,7 @@
 //
 
 pub trait Clone2 {
-    /// Returns a copy of the value. The contents of owned pointers
+    /// Returns a copy of the value. The contents of boxes
     /// are copied to maintain uniqueness, while the contents of
     /// managed pointers are not copied.
     fn clone(&self) -> Self;
index 1534c301c996c2bd0802719255da65c7fd8df9d1..4a169c0a384aa2bcf8bebe4f476447ef956544c4 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-#![feature(core)]
+#![feature(core_intrinsics)]
 
 use std::intrinsics::type_name;
 
index 36f8b2ca5b42ae414a35e9f07f12b095ce7ac1af..7172e9b85e3c8e0269616b3679997edf4a1353e7 100644 (file)
@@ -13,4 +13,4 @@ struct A { a: isize }
 
 fn a(a: A) -> isize { return a.a; }
 
-pub fn main() { let x: A = A {a: 1}; assert!((a(x) == 1)); }
+pub fn main() { let x: A = A {a: 1}; assert_eq!(a(x), 1); }
index fc6499ce5d462f9c90fc937f836cbed8d9649211..86159ce340b4d6fe2396e294c3ded8e08a6b9a8a 100644 (file)
@@ -40,7 +40,7 @@ pub fn main() {
     assert_eq!(size_of::<u>(), 3 as usize);
     // Alignment causes padding before the char and the u32.
 
-    assert!(size_of::<v>() ==
+    assert_eq!(size_of::<v>(),
                 16 as usize);
     assert_eq!(size_of::<isize>(), size_of::<usize>());
     assert_eq!(size_of::<w>(), size_of::<isize>());
index 9741ed0fddec8dea803ec5ba93001339406b1a5f..feb43dfb9ade22891fba2771945bf4692915672d 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:typeid-intrinsic2.rs
 
 
-#![feature(hash, core)]
+#![feature(hash_default, core_intrinsics)]
 
 extern crate typeid_intrinsic as other1;
 extern crate typeid_intrinsic2 as other2;
index 0749b52a1c60146c4ed251b26b72de382bdb86e8..a47883463e8a098b55390e4b07ac25c3ee5d14fe 100644 (file)
@@ -12,5 +12,5 @@
 pub fn main() {
     let (x, y) = (10, 20);
     let z = x + y;
-    assert!((z == 30));
+    assert_eq!(z, 30);
 }
index a8240dfbd1f8bd558fc80f8665abee2300c7230a..27f11d0411c47f11f194b4a1d765d13a196318ba 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 
-#![feature(collections, rand, into_cow)]
+#![feature(collections, rand, into_cow, map_in_place, bitvec)]
+#![allow(warnings)]
 
 use std::borrow::{Cow, IntoCow};
 use std::collections::BitVec;
index 6a76fdb5ad7e43344fb3bcdbdd4faaac89d228cf..74c5f6949082578439f56713c26835b3c886dae9 100644 (file)
@@ -38,6 +38,6 @@ fn call_box(f: &mut FnMut(i32) -> i32, x: i32) -> i32 {
 fn main() {
     let x = call_it(S, 1);
     let y = call_box(&mut S, 1);
-    assert!(x == 4);
-    assert!(y == 4);
+    assert_eq!(x, 4);
+    assert_eq!(y, 4);
 }
index de7eeb57de10d7143351c8b9efc6dc91b6a12e78..30c45fc766a12863ade944eedf964604d6aaacb8 100644 (file)
@@ -12,7 +12,7 @@
 //
 //    error: internal compiler error: get_unique_type_id_of_type() -
 //    unexpected type: closure,
-//    ty_closure(syntax::ast::DefId{krate: 0, node: 66},
+//    TyClosure(syntax::ast::DefId{krate: 0, node: 66},
 //    ReScope(63))
 //
 // This is a regression test for issue #17021.
index 938b5dc616729530ffc5b3554844eddf1b7028a4..9d5383fe0603fd70d59ee842f4f2640ac7a3233d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(iter_unfold)]
 
 use std::iter::Unfold;
 
index 3b0ad63aeffe9744c2f0dea1266f7b0a53531113..1bd44ecb7217a3782178eeeec673933158ff005f 100644 (file)
@@ -14,7 +14,7 @@
 
 pub fn main() {
     let i: Box<_> = box 100;
-    assert!(i == box 100);
+    assert_eq!(i, box 100);
     assert!(i < box 101);
     assert!(i <= box 100);
     assert!(i > box 99);
index 41945821587cafd8ffd8f086075d7fcb247a18c0..026bc0435d91c339ab3ec3e3c13bed43a32a618a 100644 (file)
@@ -14,5 +14,5 @@
 
 pub fn main() {
     let vect : Vec<Box<_>> = vec!(box 100);
-    assert!(vect[0] == box 100);
+    assert_eq!(vect[0], box 100);
 }
index b808ac2b00823d7db7e94ac25a877bda52010a8b..f45b3285da76221f40829f13c0530313189bb7b7 100644 (file)
 #![feature(box_syntax)]
 
 use std::cmp::PartialEq;
+use std::fmt::Debug;
 
 fn sendable() {
 
-    fn f<T:Send + PartialEq>(i: T, j: T) {
-        assert!(i == j);
+    fn f<T:Send + PartialEq + Debug>(i: T, j: T) {
+        assert_eq!(i, j);
     }
 
     fn g<T:Send + PartialEq>(i: T, j: T) {
@@ -34,8 +35,8 @@ fn sendable() {
 
 fn copyable() {
 
-    fn f<T:PartialEq>(i: T, j: T) {
-        assert!(i == j);
+    fn f<T:PartialEq + Debug>(i: T, j: T) {
+        assert_eq!(i, j);
     }
 
     fn g<T:PartialEq>(i: T, j: T) {
@@ -52,8 +53,8 @@ fn copyable() {
 
 fn noncopyable() {
 
-    fn f<T:PartialEq>(i: T, j: T) {
-        assert!(i == j);
+    fn f<T:PartialEq + Debug>(i: T, j: T) {
+        assert_eq!(i, j);
     }
 
     fn g<T:PartialEq>(i: T, j: T) {
index 2977f579fc592abb76b961f721dffb3561fa3234..6d378cb294e328d46ff684fd865012207c838d76 100644 (file)
@@ -11,8 +11,8 @@
 // Test structs with always-unsized fields.
 
 
-#![allow(unknown_features)]
-#![feature(box_syntax, core)]
+#![allow(warnings)]
+#![feature(box_syntax, unsize, raw)]
 
 use std::mem;
 use std::raw;
@@ -70,8 +70,8 @@ pub fn main() {
 
         let data: Box<Foo_<i32>> = box Foo_{f: [1, 2, 3] };
         let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3));
-        assert!(x.f.len() == 3);
-        assert!(x.f[0] == 1);
+        assert_eq!(x.f.len(), 3);
+        assert_eq!(x.f[0], 1);
 
         struct Baz_ {
             f1: usize,
@@ -81,14 +81,14 @@ pub fn main() {
         let data: Box<_> = box Baz_ {
             f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
         let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5));
-        assert!(x.f1 == 42);
+        assert_eq!(x.f1, 42);
         let chs: Vec<char> = x.f2.chars().collect();
-        assert!(chs.len() == 5);
-        assert!(chs[0] == 'a');
-        assert!(chs[1] == 'b');
-        assert!(chs[2] == 'c');
-        assert!(chs[3] == 'd');
-        assert!(chs[4] == 'e');
+        assert_eq!(chs.len(), 5);
+        assert_eq!(chs[0], 'a');
+        assert_eq!(chs[1], 'b');
+        assert_eq!(chs[2], 'c');
+        assert_eq!(chs[3], 'd');
+        assert_eq!(chs[4], 'e');
 
         struct Qux_ {
             f: St
@@ -100,6 +100,6 @@ pub fn main() {
         let data: Box<_> = box Qux_{ f: St { f: 234 } };
         let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable,
                                                         data: mem::transmute(&*data) });
-        assert!(x.f.foo() == 234);
+        assert_eq!(x.f.foo(), 234);
     }
 }
index 36b64551ef28f679f1144c3bfd52d7dc54c52f8d..4d369ba4d872db10d68159c890bd72c48e6ed335 100644 (file)
@@ -19,12 +19,12 @@ pub fn main() {
     let s: String = chs.iter().cloned().collect();
     let schs: Vec<char> = s.chars().collect();
 
-    assert!(s.len() == 10);
-    assert!(s.chars().count() == 4);
-    assert!(schs.len() == 4);
-    assert!(schs.iter().cloned().collect::<String>() == s);
-    assert!(s.char_at(0) == 'e');
-    assert!(s.char_at(1) == 'é');
+    assert_eq!(s.len(), 10);
+    assert_eq!(s.chars().count(), 4);
+    assert_eq!(schs.len(), 4);
+    assert_eq!(schs.iter().cloned().collect::<String>(), s);
+    assert_eq!(s.char_at(0), 'e');
+    assert_eq!(s.char_at(1), 'é');
 
     assert!((str::from_utf8(s.as_bytes()).is_ok()));
     // invalid prefix
index 658c35ae8d5ea32047b87a0bea55b530a103901f..25c1cfe1f4d427678fd2595e6dac9f8e5e87496f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(collections)]
+#![feature(vec_push_all)]
 
 use std::vec;
 
index 223907c01bea3c929f45b43c492a3ad693de4bd5..aadbb922f676316c67afc3dca8064ae888e7319f 100644 (file)
@@ -16,21 +16,21 @@ pub fn main() {
     // Tests for indexing into box/& [T; n]
     let x: [isize; 3] = [1, 2, 3];
     let mut x: Box<[isize; 3]> = box x;
-    assert!(x[0] == 1);
-    assert!(x[1] == 2);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 2);
+    assert_eq!(x[2], 3);
     x[1] = 45;
-    assert!(x[0] == 1);
-    assert!(x[1] == 45);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 45);
+    assert_eq!(x[2], 3);
 
     let mut x: [isize; 3] = [1, 2, 3];
     let x: &mut [isize; 3] = &mut x;
-    assert!(x[0] == 1);
-    assert!(x[1] == 2);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 2);
+    assert_eq!(x[2], 3);
     x[1] = 45;
-    assert!(x[0] == 1);
-    assert!(x[1] == 45);
-    assert!(x[2] == 3);
+    assert_eq!(x[0], 1);
+    assert_eq!(x[1], 45);
+    assert_eq!(x[2], 3);
 }
index 948fe28cc621adf1c467f373ef80a4ee17f24ef4..cf3a8796d32c96e4480259c1fb08cb1bf5dd7037 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
-#![feature(lang_items, start, no_std, core, libc, collections)]
+#![feature(lang_items, start, no_std, core, core_slice_ext, libc, collections)]
 #![no_std]
 
 extern crate std as other;
index 5728424e32bb111c82ad0a36d9dfacfd1589e3df..9df777e7af0dc4e85f6d2dc82441f061d5f063e5 100644 (file)
@@ -16,7 +16,7 @@ pub fn main() {
     match x {
         [2, _, _] => panic!(),
         [1, a, b] => {
-            assert!([a, b] == [2, 3]);
+            assert_eq!([a, b], [2, 3]);
         }
         [_, _, _] => panic!(),
     }
index 75f970543a45acefc04fd0d20939dc7b626a0a65..6cc7e3a072cf040d4dc60f574d17d66764295c96 100644 (file)
@@ -24,10 +24,10 @@ pub fn main() {
     ];
     match x {
         [ref first, tail..] => {
-            assert!(first.string == "foo".to_string());
+            assert_eq!(first.string, "foo".to_string());
             assert_eq!(tail.len(), 2);
-            assert!(tail[0].string == "bar".to_string());
-            assert!(tail[1].string == "baz".to_string());
+            assert_eq!(tail[0].string, "bar".to_string());
+            assert_eq!(tail[1].string, "baz".to_string());
 
             match tail {
                 [Foo { .. }, _, Foo { .. }, _tail..] => {
index a51274199b6200069ff6816e81f2de39f8eea81a..42b05aeea2910a73de32b8872c3a9c0cd2b0120b 100644 (file)
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 
-#![feature(rand, core)]
+#![feature(rand, num_bits_bytes)]
+#![feature(const_fn)]
 
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 use std::__rand::{thread_rng, Rng};
 use std::thread;
 
@@ -20,20 +21,20 @@ const MAX_LEN: usize = 32;
 static drop_counts: [AtomicUsize;  MAX_LEN] =
     // FIXME #5244: AtomicUsize is not Copy.
     [
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
-        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
+        AtomicUsize::new(0), AtomicUsize::new(0),
      ];
 
-static creation_count: AtomicUsize = ATOMIC_USIZE_INIT;
+static creation_count: AtomicUsize = AtomicUsize::new(0);
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
 struct DropCounter { x: u32, creation_id: usize }
index 1d477b87446d4623ba5578b514327f9917cb0360..ee19e76c14628ba3397e222b703b18e9173dc69b 100644 (file)
@@ -55,6 +55,6 @@ fn main() {
     foo1(&x);
     foo2(&x);
     unsafe {
-        assert!(COUNT == 12);
+        assert_eq!(COUNT, 12);
     }
 }
index 7ff770327742baaf8c36e0d24126dda278073581..e4ca5515653cbb5035b19489d385f023a3888a71 100644 (file)
@@ -17,7 +17,7 @@ enum t { a, b(String), }
 
 fn make(i: isize) -> t {
     if i > 10 { return t::a; }
-    let mut s = String::from_str("hello");
+    let mut s = String::from("hello");
     // Ensure s is non-const.
 
     s.push_str("there");
index e195d624fe529758cdbd26aa9194126142e2b99c..48eea1206230ec5349a3254655de3a705034ec29 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core)]
+#![feature(num_wrapping)]
 
 // Test inherent wrapping_* methods for {i,u}{size,8,16,32,64}.
 
index 62da9c9d14be220c8cb5f49cde38ecc62716dbc0..c9742b0645e1da9e3a65479df800f32004cacdb6 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// pretty-expanded FIXME #23616
-
 #![feature(std_misc)]
 
 pub type HANDLE = u32;
index a80faeaea7ea780c6d3cc4e9c27fe6444291b50c..fecbeed407c0359b749a333eff8b00af5354eeea 100644 (file)
@@ -28,5 +28,5 @@ pub fn foo() {
 
 pub fn main() {
   foo();
-  assert!((unsafe { destructions } == 0));
+  assert_eq!(unsafe { destructions }, 0);
 }
index 20076a764943c2896ed94e856a9b3e7eda91dfaf..d5047ade062dc164f9b7a296923b13aafe3a8b8e 100644 (file)
@@ -18,3 +18,25 @@ pub trait Index<I: ?Sized> {
     //      "fn index<'a>(&'a self, index: I) -> &'a Self::Output"
     fn index<'a>(&'a self, index: I) -> &'a Self::Output;
 }
+
+// @has assoc_types/fn.use_output.html
+// @has - '//*[@class="rust fn"]' '-> &T::Output'
+pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
+    obj.index(index)
+}
+
+pub trait Feed {
+    type Input;
+}
+
+// @has assoc_types/fn.use_input.html
+// @has - '//*[@class="rust fn"]' 'T::Input'
+pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
+
+// @has assoc_types/fn.cmp_input.html
+// @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq<U::Input>'
+pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
+    where T::Input: PartialEq<U::Input>
+{
+    a == b
+}
index bb9eec793df9cd7daf8ec23d7c144f123114ca20..af67f7e2c1fb7bd2a2d412f7581eb1ba0f864a4e 100644 (file)
@@ -22,7 +22,7 @@
 ///
 /// fn test() {
 ///     let x = Bar(Foo);
-///     assert!(x == x); // check that the derivings worked
+///     assert_eq!(x, x); // check that the derivings worked
 /// }
 ///
 /// }
index b84ec6d616636b211adcbf790921e78cb0f9e0d6..8835e18f1c5ce49d658053241ad8d25e9d9547e9 100644 (file)
@@ -19,4 +19,4 @@ impl Deref for Bar {
 
 // @has issue_19190_2/struct.Bar.html
 // @has - '//*[@id="method.count_ones"]' 'fn count_ones(self) -> u32'
-
+// @!has - '//*[@id="method.min_value"]' 'fn min_value() -> i32'
index eec5c0253773720b42574accfed97994efb26cde..64c396b29f27e186db4079886ec2a5aad4805e16 100644 (file)
@@ -18,14 +18,17 @@ use issue_19190_3::Baz;
 
 // @has issue_19190_3/struct.Foo.html
 // @has - '//*[@id="method.count_ones"]' 'fn count_ones(self) -> u32'
+// @!has - '//*[@id="method.min_value"]' 'fn min_value() -> i32'
 pub use issue_19190_3::Foo;
 
 // @has issue_19190_3/struct.Bar.html
 // @has - '//*[@id="method.baz"]' 'fn baz(&self)'
+// @!has - '//*[@id="method.static_baz"]' 'fn static_baz()'
 pub use issue_19190_3::Bar;
 
 // @has issue_19190_3/struct.MyBar.html
 // @has - '//*[@id="method.baz"]' 'fn baz(&self)'
+// @!has - '//*[@id="method.static_baz"]' 'fn static_baz()'
 pub struct MyBar;
 
 impl Deref for MyBar {
index f011a3e64a6be0f6ba8023ac2f8dc54b29a87eaf..6289fcc6fe526b671b64fb41261099f7d340941a 100644 (file)
@@ -15,6 +15,7 @@ pub struct Bar;
 
 impl Foo {
     pub fn foo(&self) {}
+    pub fn static_foo() {}
 }
 
 impl Deref for Bar {
@@ -24,3 +25,4 @@ impl Deref for Bar {
 
 // @has issue_19190/struct.Bar.html
 // @has - '//*[@id="method.foo"]' 'fn foo(&self)'
+// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
index 42469a21f22d0abbf25f3bfc31e5c76e396efde7..70b77f6760d8b24299a4ebdb8afcd3a05e538e7c 100644 (file)
@@ -10,6 +10,8 @@
 
 #![crate_name = "rustdoc_test"]
 
+use std::ops::Deref;
+
 // @has search-index.js Foo
 pub use private::Foo;
 
@@ -24,3 +26,11 @@ mod private {
         fn trait_method(&self) {} // @!has - priv_method
     }
 }
+
+pub struct Bar;
+
+impl Deref for Bar {
+    // @!has search-index.js Target
+    type Target = Bar;
+    fn deref(&self) -> &Bar { self }
+}
index 3ce91d63300074e66943dfbbc92f4abfad9df1bb..91ec69d9a3cbbdbeaaff4adcd705862997122097 100644 (file)
@@ -42,3 +42,7 @@ pub enum Foxtrot<F> { Foxtrot1(F) }
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
 //          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
 impl<F> MyTrait for Foxtrot<F> where F: MyTrait {}
+
+// @has foo/type.Golf.html '//pre[@class="rust typedef"]' \
+//          "type Golf<T> where T: Clone = (T, T)"
+pub type Golf<T> where T: Clone = (T, T);