]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #20518: nagisa/weighted-bool
authorAlex Crichton <alex@alexcrichton.com>
Tue, 6 Jan 2015 02:37:25 +0000 (18:37 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 6 Jan 2015 02:37:25 +0000 (18:37 -0800)
1 in 1 chance to return true always results in true.

533 files changed:
CONTRIBUTING.md
man/rustc.1
mk/docs.mk
mk/install.mk
src/compiletest/compiletest.rs
src/compiletest/header.rs
src/compiletest/runtest.rs
src/doc/complement-lang-faq.md
src/doc/guide-ffi.md
src/doc/guide-ownership.md
src/doc/guide-testing.md
src/doc/guide.md
src/doc/index.md
src/doc/reference.md
src/doc/uptack.tex [new file with mode: 0644]
src/etc/rustup.sh
src/etc/vim/syntax/rust.vim
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/rc.rs
src/libcollections/bench.rs
src/libcollections/binary_heap.rs
src/libcollections/bit.rs
src/libcollections/btree/map.rs
src/libcollections/btree/set.rs
src/libcollections/dlist.rs
src/libcollections/lib.rs
src/libcollections/ring_buf.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_map.rs
src/libcore/any.rs
src/libcore/atomic.rs
src/libcore/char.rs
src/libcore/fmt/float.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/iter.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/prelude.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/lib.rs
src/libcoretest/option.rs
src/libcoretest/raw.rs [deleted file]
src/libcoretest/result.rs
src/libflate/lib.rs
src/libgraphviz/lib.rs
src/liblog/macros.rs
src/librand/chacha.rs
src/librand/isaac.rs
src/librand/lib.rs
src/librbml/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/metadata/common.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/cstore.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/cfg/graphviz.rs
src/librustc/middle/check_const.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dead.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/fast_reject.rs
src/librustc/middle/infer/coercion.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/freshen.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/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_walk.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/graphviz.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/base.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/debuginfo.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/meth.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_trans/trans/tvec.rs
src/librustc_trans/trans/type_.rs
src/librustc_trans/trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionmanip.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/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/flock.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/lib.rs
src/librustdoc/visit_ast.rs
src/libserialize/collection_impls.rs
src/libserialize/collection_impls_stage0.rs [new file with mode: 0644]
src/libserialize/json.rs
src/libserialize/json_stage0.rs [new file with mode: 0644]
src/libserialize/lib.rs
src/libserialize/serialize.rs
src/libserialize/serialize_stage0.rs [new file with mode: 0644]
src/libstd/c_str.rs [deleted file]
src/libstd/c_vec.rs [deleted file]
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/dynamic_lib.rs
src/libstd/failure.rs
src/libstd/ffi/c_str.rs [new file with mode: 0644]
src/libstd/ffi/mod.rs [new file with mode: 0644]
src/libstd/io/fs.rs
src/libstd/io/mod.rs
src/libstd/io/net/ip.rs
src/libstd/io/net/pipe.rs
src/libstd/io/process.rs
src/libstd/io/tempfile.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/num/strconv.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/prelude/v1.rs
src/libstd/rand/mod.rs
src/libstd/rt/args.rs
src/libstd/rt/backtrace.rs
src/libstd/rt/unwind.rs
src/libstd/rt/util.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/common/mod.rs
src/libstd/sys/common/net.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/timer.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/process.rs
src/libstd/thread.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/codemap.rs
src/libsyntax/config.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/totaleq.rs
src/libsyntax/ext/deriving/cmp/totalord.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/primitive.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/ext/deriving/show.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/owned_slice.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/ptr.rs
src/libsyntax/show_span.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/libtest/stats.rs
src/libunicode/lib.rs
src/libunicode/tables.rs
src/libunicode/u_char.rs
src/libunicode/u_str.rs
src/llvm
src/rust-installer
src/rustllvm/llvm-auto-clean-trigger
src/snapshots.txt
src/test/auxiliary/cci_impl_lib.rs
src/test/auxiliary/cci_iter_lib.rs
src/test/auxiliary/cci_no_inline_lib.rs
src/test/auxiliary/iss.rs
src/test/auxiliary/issue13507.rs
src/test/auxiliary/linkage-visibility.rs
src/test/auxiliary/logging_right_crate.rs
src/test/bench/core-set.rs
src/test/bench/rt-messaging-ping-pong.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-meteor.rs
src/test/compile-fail/access-mode-in-closures.rs
src/test/compile-fail/assign-to-method.rs
src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs [new file with mode: 0644]
src/test/compile-fail/associated-type-projection-from-supertrait.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-issue-17359.rs [new file with mode: 0644]
src/test/compile-fail/block-coerce-no-2.rs [deleted file]
src/test/compile-fail/block-coerce-no.rs [deleted file]
src/test/compile-fail/borrowck-assign-comp-idx.rs
src/test/compile-fail/borrowck-autoref-3261.rs
src/test/compile-fail/borrowck-block-unint.rs
src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs
src/test/compile-fail/borrowck-closures-mut-and-imm.rs
src/test/compile-fail/borrowck-closures-mut-of-imm.rs
src/test/compile-fail/borrowck-closures-two-mut.rs
src/test/compile-fail/borrowck-closures-unique-imm.rs
src/test/compile-fail/borrowck-closures-unique.rs
src/test/compile-fail/borrowck-closures-use-after-free.rs
src/test/compile-fail/borrowck-init-in-called-fn-expr.rs
src/test/compile-fail/borrowck-init-in-fn-expr.rs
src/test/compile-fail/borrowck-insert-during-each.rs
src/test/compile-fail/borrowck-lend-flow-if.rs
src/test/compile-fail/borrowck-lend-flow-loop.rs
src/test/compile-fail/borrowck-lend-flow.rs
src/test/compile-fail/borrowck-loan-blocks-move-cc.rs
src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs
src/test/compile-fail/borrowck-loan-rcvr.rs
src/test/compile-fail/borrowck-loan-vec-content.rs
src/test/compile-fail/borrowck-move-by-capture.rs
src/test/compile-fail/borrowck-move-in-irrefut-pat.rs
src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs
src/test/compile-fail/break-outside-loop.rs
src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
src/test/compile-fail/closure-bounds-not-builtin.rs [deleted file]
src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
src/test/compile-fail/closure-bounds-subtype.rs
src/test/compile-fail/closure-reform-bad.rs
src/test/compile-fail/closure-that-fails.rs [deleted file]
src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs [deleted file]
src/test/compile-fail/dead-code-closure-bang.rs
src/test/compile-fail/extern-wrong-value-type.rs
src/test/compile-fail/fn-variance-1.rs
src/test/compile-fail/immut-function-arguments.rs
src/test/compile-fail/issue-10291.rs
src/test/compile-fail/issue-11192.rs
src/test/compile-fail/issue-11873.rs
src/test/compile-fail/issue-14182.rs
src/test/compile-fail/issue-16939.rs
src/test/compile-fail/issue-17636.rs [deleted file]
src/test/compile-fail/issue-17651.rs
src/test/compile-fail/issue-17904.rs [new file with mode: 0644]
src/test/compile-fail/issue-18343.rs
src/test/compile-fail/issue-18345.rs [deleted file]
src/test/compile-fail/issue-18783.rs
src/test/compile-fail/issue-19009.rs [deleted file]
src/test/compile-fail/issue-19141.rs [deleted file]
src/test/compile-fail/issue-19692.rs
src/test/compile-fail/issue-20193.rs [deleted file]
src/test/compile-fail/issue-20228-1.rs [deleted file]
src/test/compile-fail/issue-20228-2.rs [deleted file]
src/test/compile-fail/issue-2149.rs
src/test/compile-fail/issue-3044.rs
src/test/compile-fail/issue-3563.rs
src/test/compile-fail/issue-4335.rs
src/test/compile-fail/issue-4523.rs [deleted file]
src/test/compile-fail/issue-5216.rs
src/test/compile-fail/issue-5239-1.rs
src/test/compile-fail/issue-6801.rs
src/test/compile-fail/issue-7573.rs
src/test/compile-fail/kindck-copy.rs
src/test/compile-fail/kindck-inherited-copy-bound.rs
src/test/compile-fail/kindck-send-object.rs
src/test/compile-fail/lint-raw-ptr-derive.rs [new file with mode: 0644]
src/test/compile-fail/lint-raw-ptr-deriving.rs [deleted file]
src/test/compile-fail/lint-unused-mut-variables.rs
src/test/compile-fail/lint-unused-unsafe.rs
src/test/compile-fail/liveness-closure-require-ret.rs
src/test/compile-fail/moves-based-on-type-block-bad.rs
src/test/compile-fail/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs
src/test/compile-fail/pptypedef.rs
src/test/compile-fail/refutable-pattern-in-fn-arg.rs
src/test/compile-fail/region-bound-on-closure-outlives-call.rs
src/test/compile-fail/regionck-closure-lifetimes.rs [deleted file]
src/test/compile-fail/regions-addr-of-upvar-self.rs
src/test/compile-fail/regions-bounded-by-send.rs
src/test/compile-fail/regions-close-associated-type-into-object.rs [new file with mode: 0644]
src/test/compile-fail/regions-close-param-into-object.rs [new file with mode: 0644]
src/test/compile-fail/regions-creating-enums.rs
src/test/compile-fail/regions-escape-bound-fn-2.rs
src/test/compile-fail/regions-escape-bound-fn.rs
src/test/compile-fail/regions-escape-method.rs
src/test/compile-fail/regions-escape-via-trait-or-not.rs
src/test/compile-fail/regions-fn-subtyping.rs [deleted file]
src/test/compile-fail/regions-fns.rs [deleted file]
src/test/compile-fail/regions-free-region-ordering-callee.rs
src/test/compile-fail/regions-freevar.rs [deleted file]
src/test/compile-fail/regions-infer-at-fn-not-param.rs
src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs
src/test/compile-fail/regions-infer-call-3.rs
src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
src/test/compile-fail/regions-infer-not-param.rs
src/test/compile-fail/regions-name-undeclared.rs
src/test/compile-fail/regions-nested-fns-2.rs
src/test/compile-fail/regions-nested-fns.rs
src/test/compile-fail/regions-pattern-typing-issue-19552.rs [new file with mode: 0644]
src/test/compile-fail/regions-pattern-typing-issue-19997.rs [new file with mode: 0644]
src/test/compile-fail/regions-ref-in-fn-arg.rs
src/test/compile-fail/regions-ret-borrowed-1.rs
src/test/compile-fail/regions-ret-borrowed.rs
src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs
src/test/compile-fail/regions-steal-closure.rs
src/test/compile-fail/syntax-trait-polarity-feature-gate.rs [new file with mode: 0644]
src/test/compile-fail/syntax-trait-polarity.rs [new file with mode: 0644]
src/test/compile-fail/type-arg-out-of-scope.rs
src/test/compile-fail/unboxed-closures-type-mismatch.rs
src/test/compile-fail/unboxed-closures-vtable-mismatch.rs
src/test/compile-fail/unsized.rs
src/test/compile-fail/variance-trait-matching-2.rs [deleted file]
src/test/debuginfo/closure-in-generic-function.rs
src/test/debuginfo/lexical-scope-in-parameterless-closure.rs
src/test/debuginfo/lexical-scope-in-stack-closure.rs
src/test/debuginfo/multi-byte-chars.rs
src/test/debuginfo/recursive-enum.rs
src/test/debuginfo/type-names.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/test/debuginfo/var-captured-in-stack-closure.rs
src/test/pretty/closure-reform-pretty.rs
src/test/pretty/disamb-stmt-expr.rs
src/test/pretty/do1.rs
src/test/pretty/fn-types.rs
src/test/pretty/trait-polarity.rs [new file with mode: 0644]
src/test/run-make/static-unwinding/lib.rs
src/test/run-pass/argument-passing.rs
src/test/run-pass/associated-type-doubleendediterator-object.rs [new file with mode: 0644]
src/test/run-pass/associated-types-iterator-binding.rs [new file with mode: 0644]
src/test/run-pass/autobind.rs
src/test/run-pass/block-arg-call-as.rs
src/test/run-pass/block-explicit-types.rs
src/test/run-pass/block-fn-coerce.rs
src/test/run-pass/block-iter-1.rs
src/test/run-pass/block-iter-2.rs
src/test/run-pass/borrowck-borrow-from-expr-block.rs
src/test/run-pass/borrowck-closures-two-imm.rs
src/test/run-pass/borrowck-mut-uniq.rs
src/test/run-pass/c-stack-returning-int64.rs
src/test/run-pass/call-closure-from-overloaded-op.rs
src/test/run-pass/capture-clauses-boxed-closures.rs
src/test/run-pass/closure-inference.rs
src/test/run-pass/closure-inference2.rs
src/test/run-pass/closure-reform.rs
src/test/run-pass/closure-return-bang.rs [deleted file]
src/test/run-pass/closure-syntax.rs [deleted file]
src/test/run-pass/coerce-to-closure-and-proc.rs [deleted file]
src/test/run-pass/const-fn-val.rs
src/test/run-pass/const-polymorphic-paths.rs [new file with mode: 0644]
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/const-vec-of-fns.rs
src/test/run-pass/empty-tag.rs
src/test/run-pass/enum-null-pointer-opt.rs
src/test/run-pass/expr-block-fn.rs
src/test/run-pass/expr-block-generic-unique1.rs
src/test/run-pass/expr-block-generic-unique2.rs
src/test/run-pass/expr-block-generic.rs
src/test/run-pass/expr-if-generic.rs
src/test/run-pass/expr-match-generic-unique1.rs
src/test/run-pass/expr-match-generic-unique2.rs
src/test/run-pass/fn-bare-coerce-to-block.rs
src/test/run-pass/fn-coerce-field.rs
src/test/run-pass/fn-pattern-expected-type.rs
src/test/run-pass/fn-type-infer.rs
src/test/run-pass/foreach-nested.rs
src/test/run-pass/foreach-put-structured.rs
src/test/run-pass/foreach-simple-outer-slot.rs
src/test/run-pass/foreign-fn-linkname.rs
src/test/run-pass/fun-call-variants.rs
src/test/run-pass/generic-static-methods.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs
src/test/run-pass/hrtb-parse.rs
src/test/run-pass/hrtb-trait-object-passed-to-closure.rs
src/test/run-pass/issue-11881.rs
src/test/run-pass/issue-13434.rs
src/test/run-pass/issue-13507-2.rs
src/test/run-pass/issue-13808.rs
src/test/run-pass/issue-1460.rs
src/test/run-pass/issue-14919.rs
src/test/run-pass/issue-1516.rs [deleted file]
src/test/run-pass/issue-15924.rs
src/test/run-pass/issue-16256.rs
src/test/run-pass/issue-16668.rs
src/test/run-pass/issue-17904.rs [new file with mode: 0644]
src/test/run-pass/issue-2074.rs
src/test/run-pass/issue-2487-a.rs
src/test/run-pass/issue-3052.rs
src/test/run-pass/issue-3424.rs
src/test/run-pass/issue-3429.rs
src/test/run-pass/issue-3874.rs
src/test/run-pass/issue-3904.rs
src/test/run-pass/issue-4016.rs
src/test/run-pass/issue-5239-2.rs
src/test/run-pass/issue-6153.rs
src/test/run-pass/issue-6157.rs
src/test/run-pass/issue-868.rs
src/test/run-pass/issue-9129.rs
src/test/run-pass/iter-range.rs
src/test/run-pass/lambda-infer-unresolved.rs
src/test/run-pass/last-use-in-block.rs
src/test/run-pass/last-use-in-cap-clause.rs
src/test/run-pass/last-use-is-capture.rs
src/test/run-pass/match-phi.rs
src/test/run-pass/monad.rs
src/test/run-pass/move-nullary-fn.rs
src/test/run-pass/mut-function-arguments.rs
src/test/run-pass/mut-in-ident-patterns.rs
src/test/run-pass/newlambdas.rs
src/test/run-pass/non-legacy-modes.rs
src/test/run-pass/object-one-type-two-traits.rs
src/test/run-pass/overloaded-calls-object-one-arg.rs [new file with mode: 0644]
src/test/run-pass/overloaded-calls-object-two-args.rs [new file with mode: 0644]
src/test/run-pass/overloaded-calls-object-zero-args.rs [new file with mode: 0644]
src/test/run-pass/overloaded-calls-simple.rs
src/test/run-pass/parse-complex-macro-invoc-op.rs [new file with mode: 0644]
src/test/run-pass/pattern-in-closure.rs
src/test/run-pass/purity-infer.rs
src/test/run-pass/regions-copy-closure.rs
src/test/run-pass/regions-dependent-autofn.rs
src/test/run-pass/regions-fn-subtyping-2.rs
src/test/run-pass/regions-fn-subtyping.rs
src/test/run-pass/regions-infer-call-2.rs
src/test/run-pass/regions-lifetime-nonfree-late-bound.rs
src/test/run-pass/regions-link-fn-args.rs
src/test/run-pass/regions-params.rs
src/test/run-pass/regions-reassign-let-bound-pointer.rs [new file with mode: 0644]
src/test/run-pass/regions-reassign-match-bound-pointer.rs [new file with mode: 0644]
src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs [new file with mode: 0644]
src/test/run-pass/regions-static-closure.rs
src/test/run-pass/rename-directory.rs
src/test/run-pass/return-from-closure.rs
src/test/run-pass/sendfn-is-a-block.rs
src/test/run-pass/static-impl.rs
src/test/run-pass/struct-partial-move-1.rs
src/test/run-pass/struct-partial-move-2.rs
src/test/run-pass/syntax-trait-polarity.rs [new file with mode: 0644]
src/test/run-pass/tempfile.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/trait-generic.rs
src/test/run-pass/type-id-higher-rank.rs
src/test/run-pass/type-params-in-for-each.rs
src/test/run-pass/unboxed-closures-boxed.rs
src/test/run-pass/unboxed-closures-call-fn-autoderef.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-extern-fn.rs
src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
src/test/run-pass/unboxed-closures-generic.rs
src/test/run-pass/unboxed-closures-manual-impl.rs
src/test/run-pass/unboxed-closures-prelude.rs
src/test/run-pass/unboxed-closures-simple.rs
src/test/run-pass/unboxed-closures-static-call-fn-once.rs
src/test/run-pass/unnamed_argument_mode.rs
src/test/run-pass/unused-move-capture.rs
src/test/run-pass/variadic-ffi.rs
src/test/run-pass/vec-matching-fold.rs
src/test/run-pass/weird-exprs.rs
src/test/run-pass/wf-bound-region-in-object-type.rs [new file with mode: 0644]

index 7a4b38d1b4249df755c23e64a9cbacdfec5425d5..2b3609e28a6a0c15441c05946485d8ebd37a3640 100644 (file)
@@ -47,5 +47,14 @@ example, if it's 2014, and you change a Rust file that was created in
 // Copyright 2010-2014 The Rust Project Developers.
 ```
 
+# Coordination and communication
+
+Get feedback from other developers on
+[discuss.rust-lang.org][discuss], and
+[#rust-internals][pound-rust-internals].
+
+[pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
+[discuss]: http://discuss.rust-lang.org
+
 For more details, please refer to
 [Note-development-policy](https://github.com/rust-lang/rust/wiki/Note-development-policy).
index 4457ac8cce7e31fe39686105b38d1cdb72af7fab..3d8b27a408a27edd808ece57785b33e47940b6e7 100644 (file)
@@ -34,7 +34,7 @@ Specify the name of the crate being built
 \fB\-\-emit\fR [asm|llvm-bc|llvm-ir|obj|link|dep-info]
 Configure the output that rustc will produce
 .TP
-\fB\-\-print\fR [crate-name|output-file-names|sysroot]
+\fB\-\-print\fR [crate-name|file-names|sysroot]
 Comma separated list of compiler information to print on stdout
 .TP
 \fB\-g\fR
index 2a7ef5164f0e96e811d68d20b7abdecc519011c7..274598feada670d1a94c0347e2353ff74533f058 100644 (file)
@@ -49,8 +49,10 @@ RUSTDOC_HTML_OPTS_NO_CSS = --html-before-content=doc/version_info.html \
 RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css
 
 PANDOC_BASE_OPTS := --standalone --toc --number-sections
-PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.tex \
-       --from=markdown --include-before-body=doc/footer.tex --to=latex
+PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --from=markdown --to=latex \
+       --include-before-body=doc/version.tex \
+       --include-before-body=doc/footer.tex \
+       --include-in-header=doc/uptack.tex
 PANDOC_EPUB_OPTS = $(PANDOC_BASE_OPTS) --to=epub
 
 # The rustdoc executable...
@@ -155,6 +157,9 @@ doc/footer.tex: $(D)/footer.inc | doc/
        @$(call E, pandoc: $@)
        $(CFG_PANDOC) --from=html --to=latex $< --output=$@
 
+doc/uptack.tex: $(D)/uptack.tex | doc/
+       $(Q)cp $< $@
+
 # HTML (rustdoc)
 DOC_TARGETS += doc/not_found.html
 doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
@@ -180,7 +185,7 @@ doc/$(1).epub: $$(D)/$(1).md | doc/
 
 # PDF (md =(pandoc)=> tex =(pdflatex)=> pdf)
 DOC_TARGETS += doc/$(1).tex
-doc/$(1).tex: $$(D)/$(1).md doc/footer.tex doc/version.tex | doc/
+doc/$(1).tex: $$(D)/$(1).md doc/uptack.tex doc/footer.tex doc/version.tex | doc/
        @$$(call E, pandoc: $$@)
        $$(CFG_PANDOC) $$(PANDOC_TEX_OPTS) $$< --output=$$@
 
index a8dfdffb59d1a3390f0c06374f771c9f0b85a6aa..60c0a6bb4c7649e57c8598b9128fbaff3e83cfd9 100644 (file)
@@ -28,11 +28,7 @@ endif
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
-ifeq ($(CFG_DISABLE_DOCS),)
-prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz dist/$(DOC_PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
-else
-prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
-endif
+prepare_install: dist-tar-bins | tmp/empty_dir
 
 uninstall:
 ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
@@ -48,7 +44,7 @@ endif
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
-prepare_uninstall: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
+prepare_uninstall: dist-tar-bins | tmp/empty_dir
 
 .PHONY: install prepare_install uninstall prepare_uninstall
 
index 350a10ce4832a9debfe68b687f3e2dc578cba0ab..48610b6b526d22899df5a4061453f673fd761cd5 100644 (file)
@@ -339,8 +339,9 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool {
     return valid;
 }
 
-pub fn make_test(config: &Config, testfile: &Path, f: || -> test::TestFn)
-                 -> test::TestDescAndFn {
+pub fn make_test<F>(config: &Config, testfile: &Path, f: F) -> test::TestDescAndFn where
+    F: FnOnce() -> test::TestFn,
+{
     test::TestDescAndFn {
         desc: test::TestDesc {
             name: make_test_name(config, testfile),
index 27be6c6d8356889e700203280c56e285e476364f..2413a001ee8053b5bdbf9d90c8c0836f332c8bb7 100644 (file)
@@ -220,7 +220,9 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
     !val
 }
 
-fn iter_header(testfile: &Path, it: |&str| -> bool) -> bool {
+fn iter_header<F>(testfile: &Path, mut it: F) -> bool where
+    F: FnMut(&str) -> bool,
+{
     use std::io::{BufferedReader, File};
 
     let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
index c513aec0b843a9ac793fc7276b46718ceb4b0dab..875061e69b7a28ce49bfc6c8070dbd5bb6f4c619 100644 (file)
@@ -1233,12 +1233,14 @@ enum TargetLocation {
     ThisDirectory(Path),
 }
 
-fn make_compile_args(config: &Config,
-                     props: &TestProps,
-                     extras: Vec<String> ,
-                     xform: |&Config, &Path| -> TargetLocation,
-                     testfile: &Path)
-                     -> ProcArgs {
+fn make_compile_args<F>(config: &Config,
+                        props: &TestProps,
+                        extras: Vec<String> ,
+                        xform: F,
+                        testfile: &Path)
+                        -> ProcArgs where
+    F: FnOnce(&Config, &Path) -> TargetLocation,
+{
     let xform_file = xform(config, testfile);
     let target = if props.force_host {
         config.host.as_slice()
index 9e73863239fbc06b05e807f243b7bb65d99d7cf5..a9a9e0858ec6b7cc387a5b48d2d09b8c5f166b24 100644 (file)
@@ -17,7 +17,7 @@ Some examples that demonstrate different aspects of the language:
 * [sprocketnes], an NES emulator with no GC, using modern Rust conventions
 * The language's general-purpose [hash] function, SipHash-2-4. Bit twiddling, OO, macros
 * The standard library's [HashMap], a sendable hash map in an OO style
-* The extra library's [json] module. Enums and pattern matching
+* 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
index b8808eaf57d93e076b5b90829ecd0d45b5317202..7ee1c1a7032a5c4fce6975e1c9d0e0201fe4dbe7 100644 (file)
@@ -451,7 +451,7 @@ them.
 ~~~no_run
 extern crate libc;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::ptr;
 
 #[link(name = "readline")]
@@ -460,11 +460,10 @@ extern {
 }
 
 fn main() {
-    "[my-awesome-shell] $".with_c_str(|buf| {
-        unsafe { rl_prompt = buf; }
-        // get a line, process it
-        unsafe { rl_prompt = ptr::null(); }
-    });
+    let prompt = CString::from_slice(b"[my-awesome-shell] $");
+    unsafe { rl_prompt = prompt.as_ptr(); }
+    // get a line, process it
+    unsafe { rl_prompt = ptr::null(); }
 }
 ~~~
 
@@ -509,23 +508,28 @@ to define a block for all windows systems, not just x86 ones.
 
 # Interoperability with foreign code
 
-Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
-only if the `#[repr(C)]` attribute is applied to it.  `#[repr(C, packed)]` can be used to lay out
-struct members without padding.  `#[repr(C)]` can also be applied to an enum.
-
-Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
-object. However, they should not be manually created because they are managed by internal
-allocators. References can safely be assumed to be non-nullable pointers directly to the type.
-However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
-using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
-them.
-
-Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
-`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
-NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
-
-The standard library includes type aliases and function definitions for the C standard library in
-the `libc` module, and Rust links against `libc` and `libm` by default.
+Rust guarantees that the layout of a `struct` is compatible with the platform's
+representation in C only if the `#[repr(C)]` attribute is applied to it.
+`#[repr(C, packed)]` can be used to lay out struct members without padding.
+`#[repr(C)]` can also be applied to an enum.
+
+Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
+to the contained object. However, they should not be manually created because
+they are managed by internal allocators. References can safely be assumed to be
+non-nullable pointers directly to the type.  However, breaking the borrow
+checking or mutability rules is not guaranteed to be safe, so prefer using raw
+pointers (`*`) if that's needed because the compiler can't make as many
+assumptions about them.
+
+Vectors and strings share the same basic memory layout, and utilities are
+available in the `vec` and `str` modules for working with C APIs. However,
+strings are not terminated with `\0`. If you need a NUL-terminated string for
+interoperability with C, you should use the `CString` type in the `std::ffi`
+module.
+
+The standard library includes type aliases and function definitions for the C
+standard library in the `libc` module, and Rust links against `libc` and `libm`
+by default.
 
 # The "nullable pointer optimization"
 
index bf750ecaa8f673acd63f36e7822feb6c0c33465f..414a874082eefdc24fe8acf2bfbdc656351bf93d 100644 (file)
@@ -230,8 +230,9 @@ fn add_one(num: &int) -> int {
 ```
 
 Rust has a feature called 'lifetime elision,' which allows you to not write
-lifetime annotations in certain circumstances. This is one of them. Without
-eliding the lifetimes, `add_one` looks like this:
+lifetime annotations in certain circumstances. This is one of them. We will
+cover the others later. Without eliding the lifetimes, `add_one` looks like
+this:
 
 ```rust
 fn add_one<'a>(num: &'a int) -> int {
@@ -449,6 +450,80 @@ This is the simplest kind of multiple ownership possible. For example, there's
 also `Arc<T>`, which uses more expensive atomic instructions to be the
 thread-safe counterpart of `Rc<T>`.
 
+## Lifetime Elision
+
+Earlier, we mentioned 'lifetime elision,' a feature of Rust which allows you to
+not write lifetime annotations in certain circumstances. All references have a
+lifetime, and so if you elide a lifetime (like `&T` instead of `&'a T`), Rust
+will do three things to determine what those lifetimes should be.
+
+When talking about lifetime elision, we use the term 'input lifetime' and
+'output lifetime'. An 'input liftime' is a lifetime associated with a parameter
+of a function, and an 'output lifetime' is a lifetime associated with the return
+value of a function. For example, this function has an input lifetime:
+
+```{rust,ignore}
+fn foo<'a>(bar: &'a str)
+```
+
+This one has an output lifetime:
+
+```{rust,ignore}
+fn foo<'a>() -> &'a str
+```
+
+This one has a lifetime in both positions:
+
+```{rust,ignore}
+fn foo<'a>(bar: &'a str) -> &'a str
+```
+
+Here are the three rules:
+
+* Each elided lifetime in a function's arguments becomes a distinct lifetime
+  parameter.
+
+* If there is exactly one input lifetime, elided or not, that lifetime is
+  assigned to all elided lifetimes in the return values of that function..
+
+* If there are multiple input lifetimes, but one of them is `&self` or `&mut
+  self`, the lifetime of `self` is assigned to all elided output lifetimes.
+
+Otherwise, it is an error to elide an output lifetime.
+
+### Examples
+
+Here are some examples of functions with elided lifetimes, and the version of
+what the elided lifetimes are expand to:
+
+```{rust,ignore}
+fn print(s: &str);                                      // elided
+fn print<'a>(s: &'a str);                               // expanded
+
+fn debug(lvl: uint, s: &str);                           // elided
+fn debug<'a>(lvl: uint, s: &'a str);                    // expanded
+
+// In the preceeding example, `lvl` doesn't need a lifetime because it's not a
+// reference (`&`). Only things relating to references (such as a `struct`
+// which contains a reference) need lifetimes.
+
+fn substr(s: &str, until: uint) -> &str;                // elided
+fn substr<'a>(s: &'a str, until: uint) -> &'a str;      // expanded
+
+fn get_str() -> &str;                                   // ILLEGAL, no inputs
+
+fn frob(s: &str, t: &str) -> &str;                      // ILLEGAL, two inputs
+
+fn get_mut(&mut self) -> &mut T;                        // elided
+fn get_mut<'a>(&'a mut self) -> &'a mut T;              // expanded
+
+fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command                  // elided
+fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
+
+fn new(buf: &mut [u8]) -> BufWriter;                    // elided
+fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>          // expanded
+```
+
 # Related Resources
 
 Coming Soon.
index 682c89fcc53fcc73bd3646247c970a8f41d2c0eb..4c3d93bdfbe5feb70333c8aa1fc7f1b419f66db7 100644 (file)
@@ -503,6 +503,8 @@ Advice on writing benchmarks:
 * Make the code in the `iter` loop do something simple, to assist in pinpointing
   performance improvements (or regressions)
 
+## Gotcha: optimizations
+
 There's another tricky part to writing benchmarks: benchmarks compiled with
 optimizations activated can be dramatically changed by the optimizer so that
 the benchmark is no longer benchmarking what one expects. For example, the
@@ -537,7 +539,8 @@ computation entirely. This could be done for the example above by adjusting the
 `b.iter` call to
 
 ```rust
-# struct X; impl X { fn iter<T>(&self, _: || -> T) {} } let b = X;
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
 b.iter(|| {
     // note lack of `;` (could also use an explicit `return`).
     range(0u, 1000).fold(0, |old, new| old ^ new)
@@ -552,10 +555,15 @@ argument as used.
 extern crate test;
 
 # fn main() {
-# struct X; impl X { fn iter<T>(&self, _: || -> T) {} } let b = X;
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
 b.iter(|| {
-    test::black_box(range(0u, 1000).fold(0, |old, new| old ^ new));
-});
+    let mut n = 1000_u32;
+
+    test::black_box(&mut n); // pretend to modify `n`
+
+    range(0, n).fold(0, |a, b| a ^ b)
+})
 # }
 ```
 
@@ -571,3 +579,6 @@ test bench_xor_1000_ints ... bench:       1 ns/iter (+/- 0)
 
 test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
 ```
+
+However, the optimizer can still modify a testcase in an undesirable manner
+even when using either of the above.
index 55465651cfb4b30db1b3df20cf582b8e2e803714..66551ec499a89eeb96044251a9b440b9910e46ae 100644 (file)
@@ -23,15 +23,15 @@ 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):
 
 ```bash
-curl -L https://static.rust-lang.org/rustup.sh | sudo sh
+curl -L https://static.rust-lang.org/rustup.sh | sudo sh
 ```
 
 If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
 please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script:
 
 ```bash
-curl -L https://static.rust-lang.org/rustup.sh -O
-sudo sh rustup.sh
+curl -L https://static.rust-lang.org/rustup.sh -O
+sudo sh rustup.sh
 ```
 
 If you're on Windows, please download either the [32-bit
@@ -101,7 +101,7 @@ you can access through
 [Mibbit](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust). 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 [our
-mailing list](https://mail.mozilla.org/listinfo/rust-dev), [the /r/rust
+forum](http://discuss.rust-lang.org/), [the /r/rust
 subreddit](http://www.reddit.com/r/rust), and [Stack
 Overflow](http://stackoverflow.com/questions/tagged/rust).
 
@@ -284,13 +284,14 @@ program doesn't have any dependencies, so we'll only be using the first part of
 its functionality. Eventually, we'll add more. Since we started off by using
 Cargo, it'll be easy to add later.
 
-Let's convert Hello World to Cargo. The first thing we need to do to begin
-using Cargo is to install Cargo. Luckily for us, the script we ran to install
-Rust includes Cargo by default. If you installed Rust some other way, you may
-want to [check the Cargo
+If you installed Rust via the official installers you will also have
+Cargo. If you installed Rust some other way, you may want to [check
+the Cargo
 README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies)
 for specific instructions about installing it.
 
+Let's convert Hello World to Cargo.
+
 To Cargo-ify our project, we need to do two things: Make a `Cargo.toml`
 configuration file, and put our source file in the right place. Let's
 do that part first:
@@ -354,7 +355,7 @@ Hello, world!
 Bam! We build our project with `cargo build`, and run it with
 `./target/hello_world`. This hasn't bought us a whole lot over our simple use
 of `rustc`, but think about the future: when our project has more than one
-file, we would need to call `rustc` twice, and pass it a bunch of options to
+file, we would need to call `rustc` more than once, and pass it a bunch of options to
 tell it to build everything together. With Cargo, as our project grows, we can
 just `cargo build` and it'll work the right way.
 
@@ -384,7 +385,7 @@ The first thing we'll learn about are 'variable bindings.' They look like this:
 
 ```{rust}
 fn main() {
-    let x = 5i;
+    let x = 5;
 }
 ```
 
@@ -399,15 +400,13 @@ hand side of a `let` expression is a full pattern, not just a variable name.
 This means we can do things like:
 
 ```{rust}
-let (x, y) = (1i, 2i);
+let (x, y) = (1, 2);
 ```
 
 After this expression is evaluated, `x` will be one, and `y` will be two.
 Patterns are really powerful, but this is about all we can do with them so far.
 So let's just keep this in the back of our minds as we go forward.
 
-By the way, in these examples, `i` indicates that the number is an integer.
-
 Rust is a statically typed language, which means that we specify our types up
 front. So why does our first example compile? Well, Rust has this thing called
 "type inference." If it can figure out what the type of something is, Rust
@@ -416,18 +415,18 @@ doesn't require you to actually type it out.
 We can add the type if we want to, though. Types come after a colon (`:`):
 
 ```{rust}
-let x: int = 5;
+let x: i32 = 5;
 ```
 
 If I asked you to read this out loud to the rest of the class, you'd say "`x`
-is a binding with the type `int` and the value `five`."
+is a binding with the type `i32` and the value `five`."
 
 In future examples, we may annotate the type in a comment. The examples will
 look like this:
 
 ```{rust}
 fn main() {
-    let x = 5i; // x: int
+    let x = 5; // x: i32
 }
 ```
 
@@ -438,23 +437,23 @@ include them to help you understand what the types that Rust infers are.
 By default, bindings are **immutable**. This code will not compile:
 
 ```{ignore}
-let x = 5i;
-x = 10i;
+let x = 5;
+x = 10;
 ```
 
 It will give you this error:
 
 ```text
 error: re-assignment of immutable variable `x`
-     x = 10i;
+     x = 10;
      ^~~~~~~
 ```
 
 If you want a binding to be mutable, you can use `mut`:
 
 ```{rust}
-let mut x = 5i; // mut x: int
-x = 10i;
+let mut x = 5; // mut x: i32
+x = 10;
 ```
 
 There is no single reason that bindings are immutable by default, but we can
@@ -488,14 +487,14 @@ src/main.rs:2     let x;
 Giving it a type will compile, though:
 
 ```{rust}
-let x: int;
+let x: i32;
 ```
 
 Let's try it out. Change your `src/main.rs` file to look like this:
 
 ```{rust}
 fn main() {
-    let x: int;
+    let x: i32;
 
     println!("Hello world!");
 }
@@ -507,7 +506,7 @@ but it will still print "Hello, world!":
 ```text
    Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
 src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
-src/main.rs:2     let x: int;
+src/main.rs:2     let x: i32;
                       ^
 ```
 
@@ -517,7 +516,7 @@ do that. Change your program to look like this:
 
 ```{rust,ignore}
 fn main() {
-    let x: int;
+    let x: i32;
 
     println!("The value of x is: {}", x);
 }
@@ -568,9 +567,9 @@ multiple paths can be taken.
 In the case of `if`, there is one choice that leads down two paths:
 
 ```rust
-let x = 5i;
+let x = 5;
 
-if x == 5i {
+if x == 5 {
     println!("x is five!");
 }
 ```
@@ -582,9 +581,9 @@ the block is executed. If it's `false`, then it is not.
 If you want something to happen in the `false` case, use an `else`:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
-if x == 5i {
+if x == 5 {
     println!("x is five!");
 } else {
     println!("x is not five :(");
@@ -595,21 +594,21 @@ This is all pretty standard. However, you can also do this:
 
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
-let y = if x == 5i {
-    10i
+let y = if x == 5 {
+    10
 } else {
-    15i
-}; // y: int
+    15
+}; // y: i32
 ```
 
 Which we can (and probably should) write like this:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
-let y = if x == 5i { 10i } else { 15i }; // y: int
+let y = if x == 5 { 10 } else { 15 }; // y: i32
 ```
 
 This reveals two interesting things about Rust: it is an expression-based
@@ -641,15 +640,15 @@ In Rust, however, using `let` to introduce a binding is _not_ an expression. The
 following will produce a compile-time error:
 
 ```{ignore}
-let x = (let y = 5i); // expected identifier, found keyword `let`
+let x = (let y = 5); // expected identifier, found keyword `let`
 ```
 
 The compiler is telling us here that it was expecting to see the beginning of
 an expression, and a `let` can only begin a statement, not an expression.
 
-Note that assigning to an already-bound variable (e.g. `y = 5i`) is still an
+Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
 expression, although its value is not particularly useful. Unlike C, where an
-assignment evaluates to the assigned value (e.g. `5i` in the previous example),
+assignment evaluates to the assigned value (e.g. `5` in the previous example),
 in Rust the value of an assignment is the unit type `()` (which we'll cover later).
 
 The second kind of statement in Rust is the **expression statement**. Its
@@ -664,9 +663,9 @@ What is this exception that makes us say 'almost?' You saw it already, in this
 code:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
-let y: int = if x == 5i { 10i } else { 15i };
+let y: i32 = if x == 5 { 10 } else { 15 };
 ```
 
 Note that I've added the type annotation to `y`, to specify explicitly that I
@@ -675,20 +674,20 @@ want `y` to be an integer.
 This is not the same as this, which won't compile:
 
 ```{ignore}
-let x = 5i;
+let x = 5;
 
-let y: int = if x == 5i { 10i; } else { 15i; };
+let y: i32 = if x == 5 { 10; } else { 15; };
 ```
 
 Note the semicolons after the 10 and 15. Rust will give us the following error:
 
 ```text
-error: mismatched types: expected `int` but found `()` (expected int but found ())
+error: mismatched types: expected `i32` but found `()` (expected i32 but found ())
 ```
 
 We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
 special type in Rust's type system. In Rust, `()` is _not_ a valid value for a
-variable of type `int`. It's only a valid value for variables of the type `()`,
+variable of type `i32`. It's only a valid value for variables of the type `()`,
 which aren't very useful. Remember how we said statements don't return a value?
 Well, that's the purpose of unit in this case. The semicolon turns any
 expression into a statement by throwing away its value and returning unit
@@ -719,7 +718,7 @@ fn foo() {
 So, what about taking arguments? Here's a function that prints a number:
 
 ```{rust}
-fn print_number(x: int) {
+fn print_number(x: i32) {
     println!("x is: {}", x);
 }
 ```
@@ -731,7 +730,7 @@ fn main() {
     print_number(5);
 }
 
-fn print_number(x: int) {
+fn print_number(x: i32) {
     println!("x is: {}", x);
 }
 ```
@@ -746,7 +745,7 @@ fn main() {
     print_sum(5, 6);
 }
 
-fn print_sum(x: int, y: int) {
+fn print_sum(x: i32, y: i32) {
     println!("sum is: {}", x + y);
 }
 ```
@@ -779,7 +778,7 @@ sweet spot between full inference and no inference.
 What about returning a value? Here's a function that adds one to an integer:
 
 ```{rust}
-fn add_one(x: int) -> int {
+fn add_one(x: i32) -> i32 {
     x + 1
 }
 ```
@@ -790,7 +789,7 @@ Rust functions return exactly one value, and you declare the type after an
 You'll note the lack of a semicolon here. If we added it in:
 
 ```{ignore}
-fn add_one(x: int) -> int {
+fn add_one(x: i32) -> i32 {
     x + 1;
 }
 ```
@@ -799,7 +798,7 @@ We would get an error:
 
 ```text
 error: not all control paths return a value
-fn add_one(x: int) -> int {
+fn add_one(x: i32) -> i32 {
      x + 1;
 }
 
@@ -809,7 +808,7 @@ help: consider removing this semicolon:
 ```
 
 Remember our earlier discussions about semicolons and `()`? Our function claims
-to return an `int`, but with a semicolon, it would return `()` instead. Rust
+to return an `i32`, but with a semicolon, it would return `()` instead. Rust
 realizes this probably isn't what we want, and suggests removing the semicolon.
 
 This is very much like our `if` statement before: the result of the block
@@ -823,7 +822,7 @@ semicolon in a return position would cause a bug.
 But what about early returns? Rust does have a keyword for that, `return`:
 
 ```{rust}
-fn foo(x: int) -> int {
+fn foo(x: i32) -> i32 {
     if x < 5 { return x; }
 
     x + 1
@@ -834,7 +833,7 @@ Using a `return` as the last line of a function works, but is considered poor
 style:
 
 ```{rust}
-fn foo(x: int) -> int {
+fn foo(x: i32) -> i32 {
     if x < 5 { return x; }
 
     return x + 1;
@@ -857,7 +856,7 @@ and **doc comment**s.
 ```{rust}
 // Line comments are anything after '//' and extend to the end of the line.
 
-let x = 5i; // this is also a line comment.
+let x = 5; // this is also a line comment.
 
 // If you have a long explanation for something, you can put line comments next
 // to each other. Put a space between the // and your comment so that it's
@@ -904,19 +903,19 @@ The first compound data type we're going to talk about are called **tuple**s.
 Tuples are an ordered list of a fixed size. Like this:
 
 ```rust
-let x = (1i, "hello");
+let x = (1, "hello");
 ```
 
 The parentheses and commas form this two-length tuple. Here's the same code, but
 with the type annotated:
 
 ```rust
-let x: (int, &str) = (1, "hello");
+let x: (i32, &str) = (1, "hello");
 ```
 
 As you can see, the type of a tuple looks just like the tuple, but with each
 position having a type name rather than the value. Careful readers will also
-note that tuples are heterogeneous: we have an `int` and a `&str` in this tuple.
+note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
 You haven't seen `&str` as a type before, and we'll discuss the details of
 strings later. In systems programming languages, strings are a bit more complex
 than in other languages. For now, just read `&str` as "a string slice," and
@@ -926,7 +925,7 @@ You can access the fields in a tuple through a **destructuring let**. Here's
 an example:
 
 ```rust
-let (x, y, z) = (1i, 2i, 3i);
+let (x, y, z) = (1, 2, 3);
 
 println!("x is {}", x);
 ```
@@ -944,8 +943,8 @@ destructuring. You can assign one tuple into another, if they have the same
 arity and contained types.
 
 ```rust
-let mut x = (1i, 2i); // x: (int, int)
-let y = (2i, 3i);     // y: (int, int)
+let mut x = (1, 2); // x: (i32, i32)
+let y = (2, 3);     // y: (i32, i32)
 
 x = y;
 ```
@@ -954,8 +953,8 @@ You can also check for equality with `==`. Again, this will only compile if the
 tuples have the same type.
 
 ```rust
-let x = (1i, 2i, 3i);
-let y = (2i, 2i, 4i);
+let x = (1, 2, 3);
+let y = (2, 2, 4);
 
 if x == y {
     println!("yes");
@@ -969,16 +968,16 @@ This will print `no`, because some of the values aren't equal.
 One other use of tuples is to return multiple values from a function:
 
 ```rust
-fn next_two(x: int) -> (int, int) { (x + 1i, x + 2i) }
+fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }
 
 fn main() {
-    let (x, y) = next_two(5i);
+    let (x, y) = next_two(5);
     println!("x, y = {}, {}", x, y);
 }
 ```
 
 Even though Rust functions can only return one value, a tuple _is_ one value,
-that happens to be made up of two. You can also see in this example how you
+that happens to be made up of more than one value. You can also see in this example how you
 can destructure a pattern returned by a function, as well.
 
 Tuples are a very simple data structure, and so are not often what you want.
@@ -992,12 +991,12 @@ difference: structs give each element that they contain a name, called a
 
 ```rust
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
 fn main() {
-    let origin = Point { x: 0i, y: 0i }; // origin: Point
+    let origin = Point { x: 0, y: 0 }; // origin: Point
 
     println!("The origin is at ({}, {})", origin.x, origin.y);
 }
@@ -1019,12 +1018,12 @@ Use `mut` to make them mutable:
 
 ```{rust}
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
 fn main() {
-    let mut point = Point { x: 0i, y: 0i };
+    let mut point = Point { x: 0, y: 0 };
 
     point.x = 5;
 
@@ -1042,15 +1041,15 @@ don't:
 
 
 ```{rust}
-struct Color(int, int, int);
-struct Point(int, int, int);
+struct Color(i32, i32, i32);
+struct Point(i32, i32, i32);
 ```
 
 These two will not be equal, even if they have the same values:
 
 ```{rust}
-# struct Color(int, int, int);
-# struct Point(int, int, int);
+# struct Color(i32, i32, i32);
+# struct Point(i32, i32, i32);
 let black  = Color(0, 0, 0);
 let origin = Point(0, 0, 0);
 ```
@@ -1060,15 +1059,15 @@ It is almost always better to use a struct than a tuple struct. We would write
 
 ```{rust}
 struct Color {
-    red: int,
-    blue: int,
-    green: int,
+    red: i32,
+    blue: i32,
+    green: i32,
 }
 
 struct Point {
-    x: int,
-    y: int,
-    z: int,
+    x: i32,
+    y: i32,
+    z: i32,
 }
 ```
 
@@ -1080,7 +1079,7 @@ tuple struct with only one element. We call this a 'newtype,' because it lets
 you create a new type that's a synonym for another one:
 
 ```{rust}
-struct Inches(int);
+struct Inches(i32);
 
 let length = Inches(10);
 
@@ -1117,15 +1116,15 @@ Here's an example of how to use `Ordering`:
 ```{rust}
 use std::cmp::Ordering;
 
-fn cmp(a: int, b: int) -> Ordering {
+fn cmp(a: i32, b: i32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 
 fn main() {
-    let x = 5i;
-    let y = 10i;
+    let x = 5;
+    let y = 10;
 
     let ordering = cmp(x, y); // ordering: Ordering
 
@@ -1140,7 +1139,7 @@ fn main() {
 ```
 
 There's a symbol here we haven't seen before: the double colon (`::`).
-This is used to indicate a namesapce. In this case, `Ordering` lives in
+This is used to indicate a namespace. In this case, `Ordering` lives in
 the `cmp` submodule of the `std` module. We'll talk more about modules
 later in the guide. For now, all you need to know is that you can `use`
 things from the standard library if you need them.
@@ -1163,21 +1162,21 @@ This enum has two variants, one of which has a value:
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 ```
 
-This enum represents an `int` that we may or may not have. In the `Missing`
+This enum represents an `i32` that we may or may not have. In the `Missing`
 case, we have no value, but in the `Value` case, we do. This enum is specific
-to `int`s, though. We can make it usable by any type, but we haven't quite
+to `i32`s, though. We can make it usable by any type, but we haven't quite
 gotten there yet!
 
 You can also have any number of values in an enum:
 
 ```{rust}
 enum OptionalColor {
-    Color(int, int, int),
+    Color(i32, i32, i32),
     Missing,
 }
 ```
@@ -1256,7 +1255,7 @@ Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
 groupings with something more powerful. Check it out:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
 match x {
     1 => println!("one"),
@@ -1283,7 +1282,7 @@ error: non-exhaustive patterns: `_` not covered
 
 In other words, Rust is trying to tell us we forgot a value. Because `x` is an
 integer, Rust knows that it can have a number of different values – for example,
-`6i`. Without the `_`, however, there is no arm that could match, and so Rust refuses
+`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses
 to compile. `_` acts like a 'catch-all arm'. If none of the other arms match,
 the arm with `_` will, and since we have this catch-all arm, we now have an arm
 for every possible value of `x`, and so our program will compile successfully.
@@ -1294,15 +1293,15 @@ section on enums?
 ```{rust}
 use std::cmp::Ordering;
 
-fn cmp(a: int, b: int) -> Ordering {
+fn cmp(a: i32, b: i32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 
 fn main() {
-    let x = 5i;
-    let y = 10i;
+    let x = 5;
+    let y = 10;
 
     let ordering = cmp(x, y);
 
@@ -1321,15 +1320,15 @@ We can re-write this as a `match`:
 ```{rust}
 use std::cmp::Ordering;
 
-fn cmp(a: int, b: int) -> Ordering {
+fn cmp(a: i32, b: i32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 
 fn main() {
-    let x = 5i;
-    let y = 10i;
+    let x = 5;
+    let y = 10;
 
     match cmp(x, y) {
         Ordering::Less    => println!("less"),
@@ -1350,7 +1349,7 @@ make sure to cover all of our bases.
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
@@ -1372,7 +1371,7 @@ fn main() {
 
 That is how you can get and use the values contained in `enum`s.
 It can also allow us to handle errors or unexpected computations; for example, a
-function that is not guaranteed to be able to compute a result (an `int` here)
+function that is not guaranteed to be able to compute a result (an `i32` here)
 could return an `OptionalInt`, and we would handle that value with a `match`.
 As you can see, `enum` and `match` used together are quite useful!
 
@@ -1383,15 +1382,15 @@ also implement the previous line like this:
 ```{rust}
 use std::cmp::Ordering;
 
-fn cmp(a: int, b: int) -> Ordering {
+fn cmp(a: i32, b: i32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 
 fn main() {
-    let x = 5i;
-    let y = 10i;
+    let x = 5;
+    let y = 10;
 
     println!("{}", match cmp(x, y) {
         Ordering::Less    => "less",
@@ -1423,8 +1422,8 @@ for (x = 0; x < 10; x++) {
 Instead, it looks like this:
 
 ```{rust}
-for x in range(0i, 10i) {
-    println!("{}", x); // x: int
+for x in range(0, 10) {
+    println!("{}", x); // x: i32
 }
 ```
 
@@ -1528,7 +1527,7 @@ We now loop forever with `loop` and use `break` to break out early.
 iteration. This will only print the odd numbers:
 
 ```{rust}
-for x in range(0i, 10i) {
+for x in range(0, 10) {
     if x % 2 == 0 { continue; }
 
     println!("{}", x);
@@ -1624,15 +1623,15 @@ things. The most basic is the **array**, a fixed-size list of elements of the
 same type. By default, arrays are immutable.
 
 ```{rust}
-let a = [1i, 2i, 3i];     // a: [int; 3]
-let mut m = [1i, 2i, 3i]; // mut m: [int; 3]
+let a = [1, 2, 3];     // a: [i32; 3]
+let mut m = [1, 2, 3]; // mut m: [i32; 3]
 ```
 
 There's a shorthand for initializing each element of an array to the same
-value. In this example, each element of `a` will be initialized to `0i`:
+value. In this example, each element of `a` will be initialized to `0`:
 
 ```{rust}
-let a = [0i; 20]; // a: [int; 20]
+let a = [0; 20]; // a: [i32; 20]
 ```
 
 Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we
@@ -1643,7 +1642,7 @@ You can get the number of elements in an array `a` with `a.len()`, and use
 number in order:
 
 ```{rust}
-let a = [1i, 2, 3]; // Only the first item needs a type suffix
+let a = [1, 2, 3];
 
 println!("a has {} elements", a.len());
 for e in a.iter() {
@@ -1672,7 +1671,7 @@ later). Vectors are to arrays what `String` is to `&str`. You can create them
 with the `vec!` macro:
 
 ```{rust}
-let v = vec![1i, 2, 3]; // v: Vec<int>
+let v = vec![1, 2, 3]; // v: Vec<i32>
 ```
 
 (Notice that unlike the `println!` macro we've used in the past, we use square
@@ -1683,7 +1682,7 @@ You can get the length of, iterate over, and subscript vectors just like
 arrays. In addition, (mutable) vectors can grow automatically:
 
 ```{rust}
-let mut nums = vec![1i, 2, 3]; // mut nums: Vec<int>
+let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
 
 nums.push(4);
 
@@ -1700,7 +1699,7 @@ Slices have a length, can be mutable or not, and in many ways behave like
 arrays:
 
 ```{rust}
-let a = [0i, 1, 2, 3, 4];
+let a = [0, 1, 2, 3, 4];
 let middle = a.slice(1, 4);     // A slice of a: just the elements [1,2,3]
 
 for e in middle.iter() {
@@ -1792,7 +1791,7 @@ Do you remember this code?
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
@@ -1824,7 +1823,7 @@ where there's no standard input. Because of this, `read_line` returns a type
 very similar to our `OptionalInt`: an `IoResult<T>`. We haven't talked about
 `IoResult<T>` yet because it is the **generic** form of our `OptionalInt`.
 Until then, you can think of it as being the same thing, just for any type –
-not just `int`s.
+not just `i32`s.
 
 Rust provides a method on these `IoResult<T>`s called `ok()`, which does the
 same thing as our `match` statement but assumes that we have a valid value.
@@ -2006,7 +2005,7 @@ use std::rand;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random() % 100i) + 1i; // secret_number: int
+    let secret_number = (rand::random() % 100) + 1; // secret_number: i32
 
     println!("The secret number is: {}", secret_number);
 
@@ -2038,7 +2037,7 @@ Let's try to compile this using `cargo build`:
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
 src/main.rs:7:26: 7:34 error: the type of this value must be known in this context
-src/main.rs:7     let secret_number = (rand::random() % 100i) + 1i;
+src/main.rs:7     let secret_number = (rand::random() % 100) + 1;
                                        ^~~~~~~~
 error: aborting due to previous error
 ```
@@ -2047,15 +2046,15 @@ It didn't work! Rust says "the type of this value must be known in this
 context." What's up with that? Well, as it turns out, `rand::random()` can
 generate many kinds of random values, not just integers. And in this case, Rust
 isn't sure what kind of value `random()` should generate. So we have to help
-it. With number literals, we just add an `i` onto the end to tell Rust they're
+it. With number literals, we can just add an `i32` onto the end to tell Rust they're
 integers, but that does not work with functions. There's a different syntax,
 and it looks like this:
 
 ```{rust,ignore}
-rand::random::<int>();
+rand::random::<i32>();
 ```
 
-This says "please give me a random `int` value." We can change our code to use
+This says "please give me a random `i32` value." We can change our code to use
 this hint:
 
 ```{rust,no_run}
@@ -2065,7 +2064,7 @@ use std::rand;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<int>() % 100i) + 1i;
+    let secret_number = (rand::random::<i32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -2182,7 +2181,7 @@ fn main() {
     }
 }
 
-fn cmp(a: int, b: int) -> Ordering {
+fn cmp(a: i32, b: i32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -2194,10 +2193,10 @@ If we try to compile, we'll get some errors:
 ```bash
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:20:15: 20:20 error: mismatched types: expected `int` but found `collections::string::String` (expected int but found struct collections::string::String)
+src/main.rs:20:15: 20:20 error: mismatched types: expected `i32` but found `collections::string::String` (expected i32 but found struct collections::string::String)
 src/main.rs:20     match cmp(input, secret_number) {
                              ^~~~~
-src/main.rs:20:22: 20:35 error: mismatched types: expected `int` but found `uint` (expected int but found uint)
+src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `uint` (expected i32 but found uint)
 src/main.rs:20     match cmp(input, secret_number) {
                                     ^~~~~~~~~~~~~
 error: aborting due to 2 previous errors
@@ -2906,7 +2905,7 @@ Here's a very basic test:
 ```{rust}
 #[test]
 fn is_one_equal_to_one() {
-    assert_eq!(1i, 1i);
+    assert_eq!(1, 1);
 }
 ```
 
@@ -3207,9 +3206,9 @@ to look like this:
 ```{rust,ignore}
 #[test]
 fn math_checks_out() {
-    let result = add_three_times_four(5i);
+    let result = add_three_times_four(5);
 
-    assert_eq!(32i, result);
+    assert_eq!(32, result);
 }
 ```
 
@@ -3219,7 +3218,7 @@ And try to run the test:
 $ cargo test
    Compiling testing v0.0.1 (file:///home/you/projects/testing)
 /home/you/projects/testing/tests/lib.rs:3:18: 3:38 error: unresolved name `add_three_times_four`.
-/home/you/projects/testing/tests/lib.rs:3     let result = add_three_times_four(5i);
+/home/you/projects/testing/tests/lib.rs:3     let result = add_three_times_four(5);
                                                            ^~~~~~~~~~~~~~~~~~~~
 error: aborting due to previous error
 Build failed, waiting for other jobs to finish...
@@ -3240,7 +3239,7 @@ and put this in it:
 
 ```{rust}
 # fn main() {}
-pub fn add_three_times_four(x: int) -> int {
+pub fn add_three_times_four(x: i32) -> i32 {
     (x + 3) * 4
 }
 ```
@@ -3267,9 +3266,9 @@ use testing::add_three_times_four;
 
 #[test]
 fn math_checks_out() {
-    let result = add_three_times_four(5i);
+    let result = add_three_times_four(5);
 
-    assert_eq!(32i, result);
+    assert_eq!(32, result);
 }
 ```
 
@@ -3313,13 +3312,13 @@ some unit tests to test those.
 Change your `src/lib.rs` to look like this:
 
 ```{rust,ignore}
-pub fn add_three_times_four(x: int) -> int {
+pub fn add_three_times_four(x: i32) -> i32 {
     times_four(add_three(x))
 }
 
-fn add_three(x: int) -> int { x + 3 }
+fn add_three(x: i32) -> i32 { x + 3 }
 
-fn times_four(x: int) -> int { x * 4 }
+fn times_four(x: i32) -> i32 { x * 4 }
 ```
 
 If you run `cargo test`, you should get the same output:
@@ -3363,16 +3362,16 @@ use testing::add_three;
 
 #[test]
 fn math_checks_out() {
-    let result = add_three_times_four(5i);
+    let result = add_three_times_four(5);
 
-    assert_eq!(32i, result);
+    assert_eq!(32, result);
 }
 
 #[test]
 fn test_add_three() {
-    let result = add_three(5i);
+    let result = add_three(5);
 
-    assert_eq!(8i, result);
+    assert_eq!(8, result);
 }
 ```
 
@@ -3389,13 +3388,13 @@ Right. It's private. So external, integration tests won't work. We need a
 unit test. Open up your `src/lib.rs` and add this:
 
 ```{rust,ignore}
-pub fn add_three_times_four(x: int) -> int {
+pub fn add_three_times_four(x: i32) -> i32 {
     times_four(add_three(x))
 }
 
-fn add_three(x: int) -> int { x + 3 }
+fn add_three(x: i32) -> i32 { x + 3 }
 
-fn times_four(x: int) -> int { x * 4 }
+fn times_four(x: i32) -> i32 { x * 4 }
 
 #[cfg(test)]
 mod test {
@@ -3404,16 +3403,16 @@ mod test {
 
     #[test]
     fn test_add_three() {
-        let result = add_three(5i);
+        let result = add_three(5);
 
-        assert_eq!(8i, result);
+        assert_eq!(8, result);
     }
 
     #[test]
     fn test_times_four() {
-        let result = times_four(5i);
+        let result = times_four(5);
 
-        assert_eq!(20i, result);
+        assert_eq!(20, result);
     }
 }
 ```
@@ -3495,7 +3494,7 @@ References are created using the ampersand (`&`). Here's a simple
 reference:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 let y = &x;
 ```
 
@@ -3503,10 +3502,10 @@ let y = &x;
 rather than the reference itself) `y`, we use the asterisk (`*`):
 
 ```{rust}
-let x = 5i;
+let x = 5;
 let y = &x;
 
-assert_eq!(5i, *y);
+assert_eq!(5, *y);
 ```
 
 Like any `let` binding, references are immutable by default.
@@ -3514,7 +3513,7 @@ Like any `let` binding, references are immutable by default.
 You can declare that functions take a reference:
 
 ```{rust}
-fn add_one(x: &int) -> int { *x + 1 }
+fn add_one(x: &i32) -> i32 { *x + 1 }
 
 fn main() {
     assert_eq!(6, add_one(&5));
@@ -3529,7 +3528,7 @@ Because references are immutable, you can have multiple references that
 **alias** (point to the same place):
 
 ```{rust}
-let x = 5i;
+let x = 5;
 let y = &x;
 let z = &x;
 ```
@@ -3537,14 +3536,14 @@ let z = &x;
 We can make a mutable reference by using `&mut` instead of `&`:
 
 ```{rust}
-let mut x = 5i;
+let mut x = 5;
 let y = &mut x;
 ```
 
 Note that `x` must also be mutable. If it isn't, like this:
 
 ```{rust,ignore}
-let x = 5i;
+let x = 5;
 let y = &mut x;
 ```
 
@@ -3570,7 +3569,7 @@ Rust will also prevent us from creating two mutable references that alias.
 This won't work:
 
 ```{rust,ignore}
-let mut x = 5i;
+let mut x = 5;
 let y = &mut x;
 let z = &mut x;
 ```
@@ -3586,7 +3585,7 @@ note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent
                   ^
 note: previous borrow ends here
  fn main() {
-     let mut x = 5i;
+     let mut x = 5;
      let y = &mut x;
      let z = &mut x;
  }
@@ -3667,7 +3666,7 @@ all of Rust. Let's see this syntax in action:
 
 ```{rust}
 {
-    let x = 5i; // x is the owner of this integer, which is memory on the stack.
+    let x = 5; // x is the owner of this integer, which is memory on the stack.
 
     // other code here...
 
@@ -3675,11 +3674,11 @@ all of Rust. Let's see this syntax in action:
 
 /// this function borrows an integer. It's given back automatically when the
 /// function returns.
-fn foo(x: &int) -> &int { x }
+fn foo(x: &i32) -> &i32 { x }
 
 {
     // x is the owner of the integer, which is memory on the stack.
-    let x = 5i;
+    let x = 5;
 
     // privilege 2: you may lend that resource to as many borrowers as you like
     let y = &x;
@@ -3692,7 +3691,7 @@ fn foo(x: &int) -> &int { x }
 
 {
     // x is the owner of this integer, which is memory on the stack.
-    let mut x = 5i;
+    let mut x = 5;
 
     // privilege 3: you may lend that resource to a single borrower, mutably
     let y = &mut x;
@@ -3718,7 +3717,7 @@ violation of the restrictions placed on owners who lend something out mutably.
 The code:
 
 ```{rust,ignore}
-let mut x = 5i;
+let mut x = 5;
 let y = &mut x;
 let z = &mut x;
 ```
@@ -3734,7 +3733,7 @@ note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent
                   ^
 note: previous borrow ends here
  fn main() {
-     let mut x = 5i;
+     let mut x = 5;
      let y = &mut x;
      let z = &mut x;
  }
@@ -3767,7 +3766,7 @@ we can't change `x` until the borrow is over.
 ```text
 note: previous borrow ends here
  fn main() {
-     let mut x = 5i;
+     let mut x = 5;
      let y = &mut x;
      let z = &mut x;
  }
@@ -3828,7 +3827,7 @@ an integer `5` and makes `x` a pointer to it:
 
 ```{rust}
 {
-    let x = box 5i;
+    let x = box 5;
     println!("{}", *x);     // Prints 5
 }
 ```
@@ -3844,7 +3843,7 @@ The Rust code above will do the same thing as the following C code:
 
 ```{c,ignore}
 {
-    int *x = (int *)malloc(sizeof(int));
+    i32 *x = (i32 *)malloc(sizeof(i32));
     if (!x) abort();
     *x = 5;
     printf("%d\n", *x);
@@ -3859,7 +3858,7 @@ Boxes are the sole owner of their contents, so you cannot take a mutable
 reference to them and then use the original box:
 
 ```{rust,ignore}
-let mut x = box 5i;
+let mut x = box 5;
 let y = &mut x;
 
 *x; // you might expect 5, but this is actually an error
@@ -3880,7 +3879,7 @@ As long as `y` is borrowing the contents, we cannot use `x`. After `y` is
 done borrowing the value, we can use it again. This works fine:
 
 ```{rust}
-let mut x = box 5i;
+let mut x = box 5;
 
 {
     let y = &mut x;
@@ -3915,7 +3914,7 @@ To create an `Rc` value, use `Rc::new()`. To create a second owner, use the
 ```{rust}
 use std::rc::Rc;
 
-let x = Rc::new(5i);
+let x = Rc::new(5);
 let y = x.clone();
 
 println!("{} {}", *x, *y);      // Prints 5 5
@@ -3944,7 +3943,7 @@ A quick refresher: you can match against literals directly, and `_` acts as an
 'any' case:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 => println!("one"),
@@ -3957,7 +3956,7 @@ match x {
 You can match multiple patterns with `|`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 | 2 => println!("one or two"),
@@ -3969,7 +3968,7 @@ match x {
 You can match a range of values with `...`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 ... 5 => println!("one through five"),
@@ -3983,7 +3982,7 @@ If you're matching multiple things, via a `|` or a `...`, you can bind
 the value to a name with `@`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     e @ 1 ... 5 => println!("got a range element {}", e),
@@ -3996,14 +3995,14 @@ ignore the value and type in the variant:
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
-let x = OptionalInt::Value(5i);
+let x = OptionalInt::Value(5);
 
 match x {
-    OptionalInt::Value(..) => println!("Got an int!"),
+    OptionalInt::Value(..) => println!("Got an i32!"),
     OptionalInt::Missing   => println!("No such luck."),
 }
 ```
@@ -4012,15 +4011,15 @@ You can introduce **match guards** with `if`:
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
-let x = OptionalInt::Value(5i);
+let x = OptionalInt::Value(5);
 
 match x {
-    OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
-    OptionalInt::Value(..) => println!("Got an int!"),
+    OptionalInt::Value(i) if i > 5 => println!("Got an i32 bigger than five!"),
+    OptionalInt::Value(..) => println!("Got an i32!"),
     OptionalInt::Missing   => println!("No such luck."),
 }
 ```
@@ -4029,33 +4028,33 @@ If you're matching on a pointer, you can use the same syntax as you declared it
 with. First, `&`:
 
 ```{rust}
-let x = &5i;
+let x = &5;
 
 match x {
     &val => println!("Got a value: {}", val),
 }
 ```
 
-Here, the `val` inside the `match` has type `int`. In other words, the left-hand
-side of the pattern destructures the value. If we have `&5i`, then in `&val`, `val`
-would be `5i`.
+Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
+side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
+would be `5`.
 
 If you want to get a reference, use the `ref` keyword:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
 match x {
     ref r => println!("Got a reference to {}", r),
 }
 ```
 
-Here, the `r` inside the `match` has the type `&int`. In other words, the `ref`
+Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
 keyword _creates_ a reference, for use in the pattern. If you need a mutable
 reference, `ref mut` will work in the same way:
 
 ```{rust}
-let mut x = 5i;
+let mut x = 5;
 
 match x {
     ref mut mr => println!("Got a mutable reference to {}", mr),
@@ -4067,11 +4066,11 @@ If you have a struct, you can destructure it inside of a pattern:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { x: x, y: y } => println!("({},{})", x, y),
@@ -4083,11 +4082,11 @@ If we only care about some of the values, we don't have to give them all names:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { x: x, .. } => println!("x is {}", x),
@@ -4099,11 +4098,11 @@ You can do this kind of match on any member, not just the first:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { y: y, .. } => println!("y is {}", y),
@@ -4233,9 +4232,9 @@ arguments, really powerful things are possible.
 Let's make a closure:
 
 ```{rust}
-let add_one = |x| { 1i + x };
+let add_one = |&: x| { 1 + x };
 
-println!("The sum of 5 plus 1 is {}.", add_one(5i));
+println!("The sum of 5 plus 1 is {}.", add_one(5));
 ```
 
 We create a closure using the `|...| { ... }` syntax, and then we create a
@@ -4245,8 +4244,8 @@ binding name and two parentheses, just like we would for a named function.
 Let's compare syntax. The two are pretty close:
 
 ```{rust}
-let add_one = |x: int| -> int { 1i + x };
-fn  add_one   (x: int) -> int { 1i + x }
+let add_one = |&: x: i32| -> i32 { 1 + x };
+fn  add_one      (x: i32) -> i32 { 1 + x }
 ```
 
 As you may have noticed, closures infer their argument and return types, so you
@@ -4259,9 +4258,9 @@ this:
 
 ```{rust}
 fn main() {
-    let x = 5i;
+    let x: i32 = 5;
 
-    let printer = || { println!("x is: {}", x); };
+    let printer = |&:| { println!("x is: {}", x); };
 
     printer(); // prints "x is: 5"
 }
@@ -4275,11 +4274,11 @@ defined. The closure borrows any variables it uses, so this will error:
 
 ```{rust,ignore}
 fn main() {
-    let mut x = 5i;
+    let mut x = 5;
 
-    let printer = || { println!("x is: {}", x); };
+    let printer = |&:| { println!("x is: {}", x); };
 
-    x = 6i; // error: cannot assign to `x` because it is borrowed
+    x = 6; // error: cannot assign to `x` because it is borrowed
 }
 ```
 
@@ -4299,67 +4298,67 @@ now. We'll talk about them more in the "Threads" section of the guide.
 Closures are most useful as an argument to another function. Here's an example:
 
 ```{rust}
-fn twice(x: int, f: |int| -> int) -> int {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
     f(x) + f(x)
 }
 
 fn main() {
-    let square = |x: int| { x * x };
+    let square = |&: x: i32| { x * x };
 
-    twice(5i, square); // evaluates to 50
+    twice(5, square); // evaluates to 50
 }
 ```
 
 Let's break the example down, starting with `main`:
 
 ```{rust}
-let square = |x: int| { x * x };
+let square = |&: x: i32| { x * x };
 ```
 
 We've seen this before. We make a closure that takes an integer, and returns
 its square.
 
 ```{rust}
-# fn twice(x: int, f: |int| -> int) -> int { f(x) + f(x) }
-# let square = |x: int| { x * x };
-twice(5i, square); // evaluates to 50
+# fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
+# let square = |&: x: i32| { x * x };
+twice(5, square); // evaluates to 50
 ```
 
 This line is more interesting. Here, we call our function, `twice`, and we pass
 it two arguments: an integer, `5`, and our closure, `square`. This is just like
 passing any other two variable bindings to a function, but if you've never
 worked with closures before, it can seem a little complex. Just think: "I'm
-passing two variables: one is an int, and one is a function."
+passing two variables: one is an i32, and one is a function."
 
 Next, let's look at how `twice` is defined:
 
 ```{rust,ignore}
-fn twice(x: int, f: |int| -> int) -> int {
+fn twice(x: i32, f: |i32| -> i32) -> i32 {
 ```
 
 `twice` takes two arguments, `x` and `f`. That's why we called it with two
-arguments. `x` is an `int`, we've done that a ton of times. `f` is a function,
-though, and that function takes an `int` and returns an `int`. Notice
-how the `|int| -> int` syntax looks a lot like our definition of `square`
+arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
+though, and that function takes an `i32` and returns an `i32`. Notice
+how the `|i32| -> i32` syntax looks a lot like our definition of `square`
 above, if we added the return type in:
 
 ```{rust}
-let square = |x: int| -> int { x * x };
-//           |int|    -> int
+let square = |&: x: i32| -> i32 { x * x };
+//           |i32|       -> i32
 ```
 
-This function takes an `int` and returns an `int`.
+This function takes an `i32` and returns an `i32`.
 
 This is the most complicated function signature we've seen yet! Give it a read
 a few times until you can see how it works. It takes a teeny bit of practice, and
 then it's easy.
 
-Finally, `twice` returns an `int` as well.
+Finally, `twice` returns an `i32` as well.
 
 Okay, let's look at the body of `twice`:
 
 ```{rust}
-fn twice(x: int, f: |int| -> int) -> int {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
   f(x) + f(x)
 }
 ```
@@ -4377,12 +4376,12 @@ If we didn't want to give `square` a name, we could just define it inline.
 This example is the same as the previous one:
 
 ```{rust}
-fn twice(x: int, f: |int| -> int) -> int {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
     f(x) + f(x)
 }
 
 fn main() {
-    twice(5i, |x: int| { x * x }); // evaluates to 50
+    twice(5, |x: i32| { x * x }); // evaluates to 50
 }
 ```
 
@@ -4390,14 +4389,14 @@ A named function's name can be used wherever you'd use a closure. Another
 way of writing the previous example:
 
 ```{rust}
-fn twice(x: int, f: |int| -> int) -> int {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
     f(x) + f(x)
 }
 
-fn square(x: int) -> int { x * x }
+fn square(x: i32) -> i32 { x * x }
 
 fn main() {
-    twice(5i, square); // evaluates to 50
+    twice(5, square); // evaluates to 50
 }
 ```
 
@@ -4415,7 +4414,7 @@ Let's talk about loops.
 Remember Rust's `for` loop? Here's an example:
 
 ```{rust}
-for x in range(0i, 10i) {
+for x in range(0, 10) {
     println!("{}", x);
 }
 ```
@@ -4427,7 +4426,7 @@ call the `.next()` method on repeatedly, and it gives us a sequence of things.
 Like this:
 
 ```{rust}
-let mut range = range(0i, 10i);
+let mut range = range(0, 10);
 
 loop {
     match range.next() {
@@ -4442,8 +4441,8 @@ loop {
 We make a mutable binding to the return value of `range`, which is our iterator.
 We then `loop`, with an inner `match`. This `match` is used on the result of
 `range.next()`, which gives us a reference to the next value of the iterator.
-`next` returns an `Option<int>`, in this case, which will be `Some(int)` when
-we have a value and `None` once we run out. If we get `Some(int)`, we print it
+`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
+we have a value and `None` once we run out. If we get `Some(i32)`, we print it
 out, and if we get `None`, we `break` out of the loop.
 
 This code sample is basically the same as our `for` loop version. The `for`
@@ -4460,7 +4459,7 @@ primitive. For example, if you needed to iterate over the contents of
 a vector, you may be tempted to write this:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
 for i in range(0u, nums.len()) {
     println!("{}", nums[i]);
@@ -4472,7 +4471,7 @@ vectors returns an iterator that iterates through a reference to each element
 of the vector in turn. So write this:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
 for num in nums.iter() {
     println!("{}", num);
@@ -4489,12 +4488,12 @@ very common with iterators: we can ignore unnecessary bounds checks, but still
 know that we're safe.
 
 There's another detail here that's not 100% clear because of how `println!`
-works. `num` is actually of type `&int`. That is, it's a reference to an `int`,
-not an `int` itself. `println!` handles the dereferencing for us, so we don't
+works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
+not an `i32` itself. `println!` handles the dereferencing for us, so we don't
 see it. This code works fine too:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
 for num in nums.iter() {
     println!("{}", *num);
@@ -4528,7 +4527,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
 but it shows the intention:
 
 ```{rust,ignore}
-let one_to_one_hundred = range(1i, 101i).collect();
+let one_to_one_hundred = range(1, 101).collect();
 ```
 
 As you can see, we call `collect()` on our iterator. `collect()` takes
@@ -4538,7 +4537,7 @@ type of things you want to collect, and so you need to let it know.
 Here's the version that does compile:
 
 ```{rust}
-let one_to_one_hundred = range(1i, 101i).collect::<Vec<int>>();
+let one_to_one_hundred = range(1, 101).collect::<Vec<i32>>();
 ```
 
 If you remember, the `::<>` syntax allows us to give a type hint,
@@ -4548,7 +4547,7 @@ and so we tell it that we want a vector of integers.
 is one:
 
 ```{rust}
-let greater_than_forty_two = range(0i, 100i)
+let greater_than_forty_two = range(0, 100)
                              .find(|x| *x > 42);
 
 match greater_than_forty_two {
@@ -4565,8 +4564,8 @@ element, `find` returns an `Option` rather than the element itself.
 Another important consumer is `fold`. Here's what it looks like:
 
 ```{rust}
-let sum = range(1i, 4i)
-              .fold(0i, |sum, x| sum + x);
+let sum = range(1, 4)
+              .fold(0, |sum, x| sum + x);
 ```
 
 `fold()` is a consumer that looks like this:
@@ -4582,24 +4581,24 @@ in this iterator:
 
 | base | accumulator | element | closure result |
 |------|-------------|---------|----------------|
-| 0i   | 0i          | 1i      | 1i             |
-| 0i   | 1i          | 2i      | 3i             |
-| 0i   | 3i          | 3i      | 6i             |
+| 0    | 0           | 1       | 1              |
+| 0    | 1           | 2       | 3              |
+| 0    | 3           | 3       | 6              |
 
 We called `fold()` with these arguments:
 
 ```{rust}
-# range(1i, 4i)
-.fold(0i, |sum, x| sum + x);
+# range(1, 4)
+.fold(0, |sum, x| sum + x);
 ```
 
-So, `0i` is our base, `sum` is our accumulator, and `x` is our element.  On the
-first iteration, we set `sum` to `0i`, and `x` is the first element of `nums`,
-`1i`. We then add `sum` and `x`, which gives us `0i + 1i = 1i`. On the second
+So, `0` is our base, `sum` is our accumulator, and `x` is our element.  On the
+first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
+`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
 iteration, that value becomes our accumulator, `sum`, and the element is
-the second element of the array, `2i`. `1i + 2i = 3i`, and so that becomes
+the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
 the value of the accumulator for the last iteration. On that iteration,
-`x` is the last element, `3i`, and `3i + 3i = 6i`, which is our final
+`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
 result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
 
 Whew. `fold` can be a bit strange the first few times you see it, but once it
@@ -4620,14 +4619,14 @@ This code, for example, does not actually generate the numbers
 `1-100`, and just creates a value that represents the sequence:
 
 ```{rust}
-let nums = range(1i, 100i);
+let nums = range(1, 100);
 ```
 
 Since we didn't do anything with the range, it didn't generate the sequence.
 Let's add the consumer:
 
 ```{rust}
-let nums = range(1i, 100i).collect::<Vec<int>>();
+let nums = range(1, 100).collect::<Vec<i32>>();
 ```
 
 Now, `collect()` will require that `range()` give it some numbers, and so
@@ -4638,7 +4637,7 @@ which you've used before. `iter()` can turn a vector into a simple iterator
 that gives you each element in turn:
 
 ```{rust}
-let nums = [1i, 2i, 3i];
+let nums = [1, 2, 3];
 
 for num in nums.iter() {
    println!("{}", num);
@@ -4649,12 +4648,12 @@ These two basic iterators should serve you well. There are some more
 advanced iterators, including ones that are infinite. Like `count`:
 
 ```{rust}
-std::iter::count(1i, 5i);
+std::iter::count(1, 5);
 ```
 
 This iterator counts up from one, adding five each time. It will give
 you a new integer every time, forever (well, technically, until it reaches the
-maximum number representable by an `int`). But since iterators are lazy,
+maximum number representable by an `i32`). But since iterators are lazy,
 that's okay! You probably don't want to use `collect()` on it, though...
 
 That's enough about iterators. Iterator adapters are the last concept
@@ -4666,7 +4665,7 @@ we need to talk about with regards to iterators. Let's get to it!
 a new iterator. The simplest one is called `map`:
 
 ```{rust,ignore}
-range(1i, 100i).map(|x| x + 1i);
+range(1, 100).map(|x| x + 1);
 ```
 
 `map` is called upon another iterator, and produces a new iterator where each
@@ -4677,7 +4676,7 @@ compile the example, you'll get a warning:
 ```text
 warning: unused result which must be used: iterator adaptors are lazy and
          do nothing unless consumed, #[warn(unused_must_use)] on by default
- range(1i, 100i).map(|x| x + 1i);
+ range(1, 100).map(|x| x + 1);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ```
 
@@ -4685,7 +4684,7 @@ Laziness strikes again! That closure will never execute. This example
 doesn't print any numbers:
 
 ```{rust,ignore}
-range(1i, 100i).map(|x| println!("{}", x));
+range(1, 100).map(|x| println!("{}", x));
 ```
 
 If you are trying to execute a closure on an iterator for its side effects,
@@ -4697,7 +4696,7 @@ has no side effect on the original iterator. Let's try it out with our infinite
 iterator from before, `count()`:
 
 ```{rust}
-for i in std::iter::count(1i, 5i).take(5) {
+for i in std::iter::count(1, 5).take(5) {
     println!("{}", i);
 }
 ```
@@ -4717,7 +4716,7 @@ returns `true` or `false`. The new iterator `filter()` produces
 only the elements that that closure returns `true` for:
 
 ```{rust}
-for i in range(1i, 100i).filter(|&x| x % 2 == 0) {
+for i in range(1, 100).filter(|&x| x % 2 == 0) {
     println!("{}", i);
 }
 ```
@@ -4732,11 +4731,11 @@ 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}
-range(1i, 1000i)
+range(1, 1000)
     .filter(|&x| x % 2 == 0)
     .filter(|&x| x % 3 == 0)
     .take(5)
-    .collect::<Vec<int>>();
+    .collect::<Vec<i32>>();
 ```
 
 This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
@@ -4755,7 +4754,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type?
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 ```
@@ -4788,30 +4787,30 @@ The `<T>` part, which you've seen a few times before, indicates that this is a
 generic data type. `T` is called a **type parameter**. When we create instances
 of `Option`, we need to provide a concrete type in place of the type
 parameter. For example, if we wanted something like our `OptionalInt`, we would
-need to instantiate an `Option<int>`. Inside the declaration of our enum,
+need to instantiate an `Option<i32>`. Inside the declaration of our enum,
 wherever we see a `T`, we replace it with the type specified (or inferred by the
 the compiler).
 
 ```{rust}
-let x: Option<int> = Some(5i);
+let x: Option<i32> = Some(5);
 ```
 
-In this particular `Option`, `T` has the value of `int`. On the right-hand side
-of the binding, we do make a `Some(T)`, where `T` is `5i`.  Since that's an
-`int`, the two sides match, and Rust is happy. If they didn't match, we'd get an
+In this particular `Option`, `T` has the value of `i32`. On the right-hand side
+of the binding, we do make a `Some(T)`, where `T` is `5`.  Since that's an
+`i32`, the two sides match, and Rust is happy. If they didn't match, we'd get an
 error:
 
 ```{rust,ignore}
-let x: Option<f64> = Some(5i);
+let x: Option<f64> = Some(5);
 // error: mismatched types: expected `core::option::Option<f64>`,
-// found `core::option::Option<int>` (expected f64, found int)
+// found `core::option::Option<i32>` (expected f64, found i32)
 ```
 
 That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to
 match up:
 
 ```{rust}
-let x: Option<int> = Some(5i);
+let x: Option<i32> = Some(5);
 let y: Option<f64> = Some(5.0f64);
 ```
 
@@ -5084,25 +5083,25 @@ As you can see, `print_area` is now generic, but also ensures that we
 have passed in the correct types. If we pass in an incorrect type:
 
 ```{rust,ignore}
-print_area(5i);
+print_area(5);
 ```
 
 We get a compile-time error:
 
 ```text
-error: failed to find an implementation of trait main::HasArea for int
+error: failed to find an implementation of trait main::HasArea for i32
 ```
 
 So far, we've only added trait implementations to structs, but you can
 implement a trait for any type. So technically, we _could_ implement
-`HasArea` for `int`:
+`HasArea` for `i32`:
 
 ```{rust}
 trait HasArea {
     fn area(&self) -> f64;
 }
 
-impl HasArea for int {
+impl HasArea for i32 {
     fn area(&self) -> f64 {
         println!("this is silly");
 
@@ -5110,7 +5109,7 @@ impl HasArea for int {
     }
 }
 
-5i.area();
+5.area();
 ```
 
 It is considered poor style to implement methods on such primitive types, even
@@ -5166,7 +5165,7 @@ fn main() {
 ```
 
 Requiring us to `use` traits whose methods we want means that even if someone
-does something bad like add methods to `int`, it won't affect us, unless you
+does something bad like add methods to `i32`, it won't affect us, unless you
 `use` that trait.
 
 The second condition allows us to `impl` built-in `trait`s for types we define,
@@ -5174,9 +5173,9 @@ or allows us to `impl` our own `trait`s for built-in types, but restricts us
 from mixing and matching third party or built-in `impl`s with third party or
 built-in types.
 
-We could `impl` the `HasArea` trait for `int`, because `HasArea` is in our
+We could `impl` the `HasArea` trait for `i32`, because `HasArea` is in our
 crate. But if we tried to implement `Float`, a standard library `trait`, for
-`int`, we could not, because neither the `trait` nor the `type` are in our
+`i32`, we could not, because neither the `trait` nor the `type` are in our
 crate.
 
 ## Monomorphization
@@ -5259,7 +5258,7 @@ touches.  This implies that those variables are not usable from the
 parent thread after the child thread is spawned:
 
 ```{rust,ignore}
-let mut x = vec![1i, 2i, 3i];
+let mut x = vec![1, 2, 3];
 
 spawn(move || {
     println!("The value of x[0] is: {}", x[0]);
@@ -5333,7 +5332,7 @@ use std::sync::Future;
 let mut delayed_value = Future::spawn(move || {
     // just return anything for examples' sake
 
-    12345i
+    12345
 });
 println!("value = {}", delayed_value.get());
 ```
@@ -5401,7 +5400,7 @@ a function, but it would be worse. Why? Well, what macros allow you to do
 is write code that generates more code. So when we call `println!` like this:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 println!("x is: {}", x);
 ```
 
@@ -5421,7 +5420,7 @@ called `print.rs`:
 
 ```{rust}
 fn main() {
-    let x = 5i;
+    let x = 5;
     println!("x is: {}", x);
 }
 ```
@@ -5439,7 +5438,7 @@ extern crate "native" as rt;
 #[prelude_import]
 use std::prelude::*;
 fn main() {
-    let x = 5i;
+    let x = 5;
     match (&x,) {
         (__arg0,) => {
             #[inline]
@@ -5457,7 +5456,7 @@ fn main() {
 }
 ```
 
-Whew! This isn't too terrible. You can see that we still `let x = 5i`,
+Whew! This isn't too terrible. You can see that we still `let x = 5`,
 but then things get a little bit hairy. Three more bindings get set: a
 static format string, an argument vector, and the arguments. We then
 invoke the `println_args` function with the generated arguments.
index e54bf0eb24282d3670d04549bbf752b6a73ce4ab..7f22c1eeb855f64f33879cb2f7898829fe4eea68 100644 (file)
@@ -58,7 +58,7 @@ a guide that can help you out:
 * [Strings](guide-strings.html)
 * [Pointers](guide-pointers.html)
 * [Crates and modules](guide-crates.html)
-* [Threads and Communication](guide-threads.html)
+* [Threads and Communication](guide-tasks.html)
 * [Error Handling](guide-error-handling.html)
 * [Foreign Function Interface](guide-ffi.html)
 * [Writing Unsafe and Low-Level Code](guide-unsafe.html)
index d7930285260523858d4164b846cf9a82f39a78cc..016cf12985eb30c5edd73ec08d85eeec985a87ef 100644 (file)
@@ -1259,8 +1259,8 @@ We call such functions "diverging" because they never return a value to the
 caller. Every control path in a diverging function must end with a `panic!()` or
 a call to another diverging function on every control path. The `!` annotation
 does *not* denote a type. Rather, the result type of a diverging function is a
-special type called $\bot$ ("bottom") that unifies with any type. Rust has no
-syntax for $\bot$.
+special type called  ("bottom") that unifies with any type. Rust has no
+syntax for .
 
 It might be necessary to declare a diverging function because as mentioned
 previously, the typechecker checks that every control path in a function ends
@@ -1563,7 +1563,7 @@ functions](#generic-functions).
 trait Seq<T> {
    fn len(&self) -> uint;
    fn elt_at(&self, n: uint) -> T;
-   fn iter(&self, |T|);
+   fn iter<F>(&self, F) where F: Fn(T);
 }
 ```
 
@@ -3218,7 +3218,7 @@ In this example, we define a function `ten_times` that takes a higher-order
 function argument, and call it with a lambda expression as an argument.
 
 ```
-fn ten_times(f: |int|) {
+fn ten_times<F>(f: F) where F: Fn(int) {
     let mut i = 0;
     while i < 10 {
         f(i);
@@ -3828,7 +3828,7 @@ fn add(x: int, y: int) -> int {
 
 let mut x = add(5,7);
 
-type Binop<'a> = |int,int|: 'a -> int;
+type Binop = fn(int, int) -> int;
 let bo: Binop = add;
 x = bo(5,7);
 ```
@@ -3852,14 +3852,14 @@ An example of creating and calling a closure:
 ```rust
 let captured_var = 10i;
 
-let closure_no_args = || println!("captured_var={}", captured_var);
+let closure_no_args = |&:| println!("captured_var={}", captured_var);
 
-let closure_args = |arg: int| -> int {
+let closure_args = |&: arg: int| -> int {
   println!("captured_var={}, arg={}", captured_var, arg);
   arg // Note lack of semicolon after 'arg'
 };
 
-fn call_closure(c1: ||, c2: |int| -> int) {
+fn call_closure<F: Fn(), G: Fn(int) -> int>(c1: F, c2: G) {
   c1();
   c2(2);
 }
@@ -4316,73 +4316,28 @@ fine-grained control is desired over the output format of a Rust crate.
 
 *TODO*.
 
-# Appendix: Influences and further references
-
-## Influences
-
->  The essential problem that must be solved in making a fault-tolerant
->  software system is therefore that of fault-isolation. Different programmers
->  will write different modules, some modules will be correct, others will have
->  errors. We do not want the errors in one module to adversely affect the
->  behaviour of a module which does not have any errors.
->
->  &mdash; Joe Armstrong
-
->  In our approach, all data is private to some process, and processes can
->  only communicate through communications channels. *Security*, as used
->  in this paper, is the property which guarantees that processes in a system
->  cannot affect each other except by explicit communication.
->
->  When security is absent, nothing which can be proven about a single module
->  in isolation can be guaranteed to hold when that module is embedded in a
->  system [...]
->
->  &mdash; Robert Strom and Shaula Yemini
-
->  Concurrent and applicative programming complement each other. The
->  ability to send messages on channels provides I/O without side effects,
->  while the avoidance of shared data helps keep concurrent processes from
->  colliding.
->
->  &mdash; Rob Pike
-
-Rust is not a particularly original language. It may however appear unusual by
-contemporary standards, as its design elements are drawn from a number of
-"historical" languages that have, with a few exceptions, fallen out of favour.
-Five prominent lineages contribute the most, though their influences have come
-and gone during the course of Rust's development:
-
-* The NIL (1981) and Hermes (1990) family. These languages were developed by
-  Robert Strom, Shaula Yemini, David Bacon and others in their group at IBM
-  Watson Research Center (Yorktown Heights, NY, USA).
-
-* The Erlang (1987) language, developed by Joe Armstrong, Robert Virding, Claes
-  Wikstr&ouml;m, Mike Williams and others in their group at the Ericsson Computer
-  Science Laboratory (&Auml;lvsj&ouml;, Stockholm, Sweden) .
-
-* The Sather (1990) language, developed by Stephen Omohundro, Chu-Cheow Lim,
-  Heinz Schmidt and others in their group at The International Computer
-  Science Institute of the University of California, Berkeley (Berkeley, CA,
-  USA).
-
-* The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These
-  languages were developed by Rob Pike, Phil Winterbottom, Sean Dorward and
-  others in their group at Bell Labs Computing Sciences Research Center
-  (Murray Hill, NJ, USA).
-
-* The Napier (1985) and Napier88 (1988) family. These languages were
-  developed by Malcolm Atkinson, Ron Morrison and others in their group at
-  the University of St. Andrews (St. Andrews, Fife, UK).
-
-Additional specific influences can be seen from the following languages:
-
-* The structural algebraic types and compilation manager of SML.
-* The attribute and assembly systems of C#.
-* The references and deterministic destructor system of C++.
-* The memory region systems of the ML Kit and Cyclone.
-* The typeclass system of Haskell.
-* The lexical identifier rule of Python.
-* The block syntax of Ruby.
+# Appendix: Influences
+
+Rust is not a particularly original language, with design elements coming from
+a wide range of sources. Some of these are listed below (including elements
+that have since been removed):
+
+* SML, OCaml: algebraic datatypes, pattern matching, type inference,
+  semicolon statement separation
+* C++: references, RAII, smart pointers, move semantics, monomorphisation,
+  memory model
+* ML Kit, Cyclone: region based memory management
+* Haskell (GHC): typeclasses, type families
+* Newsqueak, Alef, Limbo: channels, concurrency
+* Erlang: message passing, task failure, ~~linked task failure~~,
+  ~~lightweight concurrency~~
+* Swift: optional bindings
+* Scheme: hygienic macros
+* C#: attributes
+* Ruby: ~~block syntax~~
+* NIL, Hermes: ~~typestate~~
+* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and
+  pattern syntax
 
 [ffi]: guide-ffi.html
 [plugin]: guide-plugin.html
diff --git a/src/doc/uptack.tex b/src/doc/uptack.tex
new file mode 100644 (file)
index 0000000..32158ea
--- /dev/null
@@ -0,0 +1,2 @@
+\usepackage{newunicodechar}
+\newunicodechar⊥{{$\bot$}}
index 85e15e363271be452c852b4a9d13002a14216e6f..749d9eaa173e86fcf41416c3fc192de3fe2f3ccc 100755 (executable)
@@ -230,7 +230,7 @@ validate_opt() {
 }
 
 create_tmp_dir() {
-    local TMP_DIR=./rustup-tmp-install
+    local TMP_DIR=`pwd`/rustup-tmp-install
 
     rm -Rf "${TMP_DIR}"
     need_ok "failed to remove temporary installation directory"
@@ -245,6 +245,21 @@ probe_need CFG_CURL  curl
 probe_need CFG_TAR   tar
 probe_need CFG_FILE  file
 
+probe CFG_SHA256SUM sha256sum
+probe CFG_SHASUM shasum
+
+if [ -z "$CFG_SHA256SUM" -a -z "$CFG_SHASUM" ]; then
+    err "unable to find either sha256sum or shasum"
+fi
+
+calculate_hash() {
+    if [ -n "$CFG_SHA256SUM" ]; then
+        ${CFG_SHA256SUM} $@
+    else
+        ${CFG_SHASUM} -a 256 $@
+    fi
+}
+
 CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
 CFG_SELF="$0"
 CFG_ARGS="$@"
@@ -269,7 +284,8 @@ VAL_OPTIONS=""
 
 flag uninstall "only uninstall from the installation prefix"
 valopt prefix "" "set installation prefix"
-opt cargo 1 "install cargo with rust"
+valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly"
+flag save "save the downloaded nightlies to ~/.rustup"
 
 if [ $HELP -eq 1 ]
 then
@@ -417,6 +433,13 @@ CFG_TMP_DIR=$(mktemp -d 2>/dev/null \
            || mktemp -d -t 'rustup-tmp-install' 2>/dev/null \
            || create_tmp_dir)
 
+# If we're saving nightlies and we didn't specify which one, grab todays.
+# Otherwise we'll use the latest version.
+if [ -n "${CFG_SAVE}" -a -z "${CFG_DATE}" ];
+then
+    CFG_DATE=`date "+%Y-%m-%d"`
+fi
+
 RUST_URL="https://static.rust-lang.org/dist"
 RUST_PACKAGE_NAME=rust-nightly
 RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}"
@@ -424,35 +447,84 @@ RUST_TARBALL_NAME="${RUST_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
 RUST_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${RUST_PACKAGE_NAME_AND_TRIPLE}"
 RUST_LOCAL_INSTALL_SCRIPT="${RUST_LOCAL_INSTALL_DIR}/install.sh"
 
-CARGO_URL="https://static.rust-lang.org/cargo-dist"
-CARGO_PACKAGE_NAME=cargo-nightly
-CARGO_PACKAGE_NAME_AND_TRIPLE="${CARGO_PACKAGE_NAME}-${HOST_TRIPLE}"
-CARGO_TARBALL_NAME="${CARGO_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
-CARGO_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${CARGO_PACKAGE_NAME_AND_TRIPLE}"
-CARGO_LOCAL_INSTALL_SCRIPT="${CARGO_LOCAL_INSTALL_DIR}/install.sh"
+# add a date suffix if we want a particular nighly.
+if [ -n "${CFG_DATE}" ];
+then
+    RUST_URL="${RUST_URL}/${CFG_DATE}"
+fi
+
+verify_hash() {
+    remote_sha256="$1"
+    local_file="$2"
+
+    msg "Downloading ${remote_sha256}"
+    remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"`
+    if [ "$?" -ne 0 ]; then
+        rm -Rf "${CFG_TMP_DIR}"
+        err "Failed to download ${remote_url}"
+    fi
+
+    msg "Verifying hash"
+    local_sha256=$(calculate_hash "${local_file}")
+    if [ "$?" -ne 0 ]; then
+        rm -Rf "${CFG_TMP_DIR}"
+        err "Failed to compute hash for ${local_tarball}"
+    fi
+
+    # We only need the sha, not the filenames
+    remote_sha256=`echo ${remote_sha256} | cut -f 1 -d ' '`
+    local_sha256=`echo ${local_sha256} | cut -f 1 -d ' '`
+
+    if [ "${remote_sha256}" != "${local_sha256}" ]; then
+        rm -Rf "${CFG_TMP_DIR}"
+        errmsg="invalid sha256.\n"
+        errmsg="$errmsg ${remote_sha256}\t${remote_tarball}\n"
+        errmsg="$errmsg ${local_sha256}\t${local_tarball}"
+        err "$errmsg"
+    fi
+}
 
-# Fetch the package.
+# Fetch the package. Optionally caches the tarballs.
 download_package() {
     remote_tarball="$1"
     local_tarball="$2"
+    remote_sha256="${remote_tarball}.sha256"
 
-    msg "Downloading ${remote_tarball} to ${local_tarball}"
+    # Check if we've already downloaded this file.
+    if [ -e "${local_tarball}.tmp" ]; then
+        msg "Resuming ${remote_tarball} to ${local_tarball}"
 
-    "${CFG_CURL}" -f -o "${local_tarball}" "${remote_tarball}"
-    if [ $? -ne 0 ]
-    then
-        rm -Rf "${CFG_TMP_DIR}"
-        err "failed to download installer"
+        "${CFG_CURL}" -f -C - -o "${local_tarball}.tmp" "${remote_tarball}"
+        if [ $? -ne 0 ]
+        then
+            rm -Rf "${CFG_TMP_DIR}"
+            err "failed to download installer"
+        fi
+
+        mv "${local_tarball}.tmp" "${local_tarball}"
+    elif [ ! -e "${local_tarball}" ]; then
+        msg "Downloading ${remote_tarball} to ${local_tarball}"
+
+        "${CFG_CURL}" -f -o "${local_tarball}.tmp" "${remote_tarball}"
+        if [ $? -ne 0 ]
+        then
+            rm -Rf "${CFG_TMP_DIR}"
+            err "failed to download installer"
+        fi
+
+        mv "${local_tarball}.tmp" "${local_tarball}"
     fi
+
+    verify_hash "${remote_sha256}" "${local_tarball}"
 }
 
 # Wrap all the commands needed to install a package.
 install_package() {
-    tarball_name="$1"
+    local_tarball="$1"
     install_script="$2"
 
-    msg "Extracting ${tarball_name}"
-    (cd "${CFG_TMP_DIR}" && "${CFG_TAR}" -xzf "${tarball_name}")
+    msg "Extracting ${local_tarball}"
+    (cd "${CFG_TMP_DIR}" && "${CFG_TAR}" -xzf "${local_tarball}")
     if [ $? -ne 0 ]; then
         rm -Rf "${CFG_TMP_DIR}"
         err "failed to unpack installer"
@@ -479,29 +551,27 @@ install_packages() {
     mkdir -p "${CFG_TMP_DIR}"
     need_ok "failed to create create temporary installation directory"
 
-    RUST_LOCAL_TARBALL="${CFG_TMP_DIR}/${RUST_TARBALL_NAME}"
-    CARGO_LOCAL_TARBALL="${CFG_TMP_DIR}/${CARGO_TARBALL_NAME}"
+    # If we're saving our nightlies, put them in $HOME/.rustup.
+    if [ -n "${CFG_SAVE}" ]
+    then
+        RUST_DOWNLOAD_DIR="${HOME}/.rustup/${CFG_DATE}"
+    else
+        RUST_DOWNLOAD_DIR="${CFG_TMP_DIR}"
+    fi
+
+    mkdir -p "${RUST_DOWNLOAD_DIR}"
+    need_ok "failed to create create download directory"
+
+    RUST_LOCAL_TARBALL="${RUST_DOWNLOAD_DIR}/${RUST_TARBALL_NAME}"
 
     download_package \
         "${RUST_URL}/${RUST_TARBALL_NAME}" \
         "${RUST_LOCAL_TARBALL}"
 
-    if [ -z "${CFG_DISABLE_CARGO}" ]; then
-        download_package \
-            "${CARGO_URL}/${CARGO_TARBALL_NAME}" \
-            "${CARGO_LOCAL_TARBALL}"
-    fi
-
     install_package \
-        "${RUST_TARBALL_NAME}" \
+        "${RUST_LOCAL_TARBALL}" \
         "${RUST_LOCAL_INSTALL_SCRIPT}"
 
-    if [ -z "${CFG_DISABLE_CARGO}" ]; then
-        install_package \
-            "${CARGO_TARBALL_NAME}" \
-            "${CARGO_LOCAL_INSTALL_SCRIPT}"
-    fi
-
     rm -Rf "${CFG_TMP_DIR}"
     need_ok "couldn't rm temporary installation directory"
 }
index 9e663eb0317efcb47352dae8fb93f38ef8ec51f5..5588152a244c44c2554192290eedfe53d62a501e 100644 (file)
@@ -157,8 +157,8 @@ syn region    rustString      start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustE
 syn region    rustString      start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
 syn region    rustString      start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
 
-syn region    rustAttribute   start="#!\?\[" end="\]" contains=rustString,rustDeriving
-syn region    rustDeriving    start="deriving(" end=")" contained contains=rustTrait
+syn region    rustAttribute   start="#!\?\[" end="\]" contains=rustString,rustDerive
+syn region    rustDerive      start="derive(" end=")" contained contains=rustTrait
 
 " Number literals
 syn match     rustDecNumber   display "\<[0-9][0-9_]*\%([iu]\%(8\|16\|32\|64\)\=\)\="
@@ -263,7 +263,7 @@ hi def link rustMacro         Macro
 hi def link rustType          Type
 hi def link rustTodo          Todo
 hi def link rustAttribute     PreProc
-hi def link rustDeriving      PreProc
+hi def link rustDerive        PreProc
 hi def link rustStorage       StorageClass
 hi def link rustObsoleteStorage Error
 hi def link rustLifetime      Special
@@ -275,7 +275,7 @@ hi def link rustBoxPlacementExpr rustKeyword
 
 " Other Suggestions:
 " hi rustAttribute ctermfg=cyan
-" hi rustDeriving ctermfg=cyan
+" hi rustDerive ctermfg=cyan
 " hi rustAssert ctermfg=yellow
 " hi rustPanic ctermfg=red
 " hi rustMacro ctermfg=magenta
index 88f02d6573eac788f930391f1c393873cb7b1c52..080d34dbda5731e913ab0b768be0ad23823ab781 100644 (file)
@@ -35,7 +35,7 @@
 //! use std::sync::Arc;
 //! use std::thread::Thread;
 //!
-//! let five = Arc::new(5i);
+//! let five = Arc::new(5);
 //!
 //! for i in range(0u, 10) {
 //!     let five = five.clone();
@@ -52,7 +52,7 @@
 //! use std::sync::{Arc, Mutex};
 //! use std::thread::Thread;
 //!
-//! let five = Arc::new(Mutex::new(5i));
+//! let five = Arc::new(Mutex::new(5));
 //!
 //! for _ in range(0u, 10) {
 //!     let five = five.clone();
@@ -154,7 +154,7 @@ impl<T> Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     /// ```
     #[inline]
     #[stable]
@@ -176,7 +176,7 @@ pub fn new(data: T) -> Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
     /// let weak_five = five.downgrade();
     /// ```
@@ -220,7 +220,7 @@ impl<T> Clone for Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
     /// five.clone();
     /// ```
@@ -267,7 +267,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let mut five = Arc::new(5i);
+    /// let mut five = Arc::new(5);
     ///
     /// let mut_five = five.make_unique();
     /// ```
@@ -303,14 +303,14 @@ impl<T: Sync + Send> Drop for Arc<T> {
     /// use std::sync::Arc;
     ///
     /// {
-    ///     let five = Arc::new(5i);
+    ///     let five = Arc::new(5);
     ///
     ///     // stuff
     ///
     ///     drop(five); // explict drop
     /// }
     /// {
-    ///     let five = Arc::new(5i);
+    ///     let five = Arc::new(5);
     ///
     ///     // stuff
     ///
@@ -369,7 +369,7 @@ impl<T: Sync + Send> Weak<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
     /// let weak_five = five.downgrade();
     ///
@@ -405,7 +405,7 @@ impl<T: Sync + Send> Clone for Weak<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let weak_five = Arc::new(5i).downgrade();
+    /// let weak_five = Arc::new(5).downgrade();
     ///
     /// weak_five.clone();
     /// ```
@@ -430,7 +430,7 @@ impl<T: Sync + Send> Drop for Weak<T> {
     /// use std::sync::Arc;
     ///
     /// {
-    ///     let five = Arc::new(5i);
+    ///     let five = Arc::new(5);
     ///     let weak_five = five.downgrade();
     ///
     ///     // stuff
@@ -438,7 +438,7 @@ impl<T: Sync + Send> Drop for Weak<T> {
     ///     drop(weak_five); // explict drop
     /// }
     /// {
-    ///     let five = Arc::new(5i);
+    ///     let five = Arc::new(5);
     ///     let weak_five = five.downgrade();
     ///
     ///     // stuff
@@ -472,9 +472,9 @@ impl<T: PartialEq> PartialEq for Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five == Arc::new(5i);
+    /// five == Arc::new(5);
     /// ```
     fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
 
@@ -487,9 +487,9 @@ fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five != Arc::new(5i);
+    /// five != Arc::new(5);
     /// ```
     fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
 }
@@ -504,9 +504,9 @@ impl<T: PartialOrd> PartialOrd for Arc<T> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five.partial_cmp(&Arc::new(5i));
+    /// five.partial_cmp(&Arc::new(5));
     /// ```
     fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
         (**self).partial_cmp(&**other)
@@ -521,9 +521,9 @@ fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five < Arc::new(5i);
+    /// five < Arc::new(5);
     /// ```
     fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
 
@@ -536,9 +536,9 @@ fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five <= Arc::new(5i);
+    /// five <= Arc::new(5);
     /// ```
     fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
 
@@ -551,9 +551,9 @@ fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five > Arc::new(5i);
+    /// five > Arc::new(5);
     /// ```
     fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
 
@@ -566,9 +566,9 @@ fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
     /// ```
     /// use std::sync::Arc;
     ///
-    /// let five = Arc::new(5i);
+    /// let five = Arc::new(5);
     ///
-    /// five >= Arc::new(5i);
+    /// five >= Arc::new(5);
     /// ```
     fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
 }
index 362f6c66b599d4b28bc16736197b75effe312376..2c318181b099521fc88e0f9f54c15da0dbc12b77 100644 (file)
@@ -12,7 +12,7 @@
 
 #![stable]
 
-use core::any::{Any, AnyRefExt};
+use core::any::Any;
 use core::clone::Clone;
 use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
 use core::default::Default;
index c4b455aff5c53cea59eecc9ff87489e29bb1d731..d9239e93a0740aa6ee6bc089a65f444c7c57098e 100644 (file)
@@ -187,7 +187,7 @@ impl<T> Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     /// ```
     #[stable]
     pub fn new(value: T) -> Rc<T> {
@@ -214,7 +214,7 @@ pub fn new(value: T) -> Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
     /// let weak_five = five.downgrade();
     /// ```
@@ -247,7 +247,7 @@ pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
 /// use std::rc;
 /// use std::rc::Rc;
 ///
-/// let five = Rc::new(5i);
+/// let five = Rc::new(5);
 ///
 /// rc::is_unique(&five);
 /// ```
@@ -329,7 +329,7 @@ impl<T: Clone> Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let mut five = Rc::new(5i);
+    /// let mut five = Rc::new(5);
     ///
     /// let mut_five = five.make_unique();
     /// ```
@@ -378,14 +378,14 @@ impl<T> Drop for Rc<T> {
     /// use std::rc::Rc;
     ///
     /// {
-    ///     let five = Rc::new(5i);
+    ///     let five = Rc::new(5);
     ///
     ///     // stuff
     ///
     ///     drop(five); // explict drop
     /// }
     /// {
-    ///     let five = Rc::new(5i);
+    ///     let five = Rc::new(5);
     ///
     ///     // stuff
     ///
@@ -424,7 +424,7 @@ impl<T> Clone for Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
     /// five.clone();
     /// ```
@@ -465,9 +465,9 @@ impl<T: PartialEq> PartialEq for Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five == Rc::new(5i);
+    /// five == Rc::new(5);
     /// ```
     #[inline(always)]
     fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
@@ -481,9 +481,9 @@ fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five != Rc::new(5i);
+    /// five != Rc::new(5);
     /// ```
     #[inline(always)]
     fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
@@ -503,9 +503,9 @@ impl<T: PartialOrd> PartialOrd for Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five.partial_cmp(&Rc::new(5i));
+    /// five.partial_cmp(&Rc::new(5));
     /// ```
     #[inline(always)]
     fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
@@ -521,9 +521,9 @@ fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five < Rc::new(5i);
+    /// five < Rc::new(5);
     /// ```
     #[inline(always)]
     fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
@@ -537,9 +537,9 @@ fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five <= Rc::new(5i);
+    /// five <= Rc::new(5);
     /// ```
     #[inline(always)]
     fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
@@ -553,9 +553,9 @@ fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five > Rc::new(5i);
+    /// five > Rc::new(5);
     /// ```
     #[inline(always)]
     fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
@@ -569,9 +569,9 @@ fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five >= Rc::new(5i);
+    /// five >= Rc::new(5);
     /// ```
     #[inline(always)]
     fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
@@ -588,9 +588,9 @@ impl<T: Ord> Ord for Rc<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
-    /// five.partial_cmp(&Rc::new(5i));
+    /// five.partial_cmp(&Rc::new(5));
     /// ```
     #[inline]
     fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
@@ -639,7 +639,7 @@ impl<T> Weak<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let five = Rc::new(5i);
+    /// let five = Rc::new(5);
     ///
     /// let weak_five = five.downgrade();
     ///
@@ -668,7 +668,7 @@ impl<T> Drop for Weak<T> {
     /// use std::rc::Rc;
     ///
     /// {
-    ///     let five = Rc::new(5i);
+    ///     let five = Rc::new(5);
     ///     let weak_five = five.downgrade();
     ///
     ///     // stuff
@@ -676,7 +676,7 @@ impl<T> Drop for Weak<T> {
     ///     drop(weak_five); // explict drop
     /// }
     /// {
-    ///     let five = Rc::new(5i);
+    ///     let five = Rc::new(5);
     ///     let weak_five = five.downgrade();
     ///
     ///     // stuff
@@ -710,7 +710,7 @@ impl<T> Clone for Weak<T> {
     /// ```
     /// use std::rc::Rc;
     ///
-    /// let weak_five = Rc::new(5i).downgrade();
+    /// let weak_five = Rc::new(5).downgrade();
     ///
     /// weak_five.clone();
     /// ```
index c7164b8199cc341d6f563321e13c2430312889f9..cd4f8d203dfe94ec5d861f2af02312d440a16f28 100644 (file)
@@ -11,7 +11,7 @@
 use prelude::*;
 use std::rand;
 use std::rand::Rng;
-use test::Bencher;
+use test::{Bencher, black_box};
 
 pub fn insert_rand_n<M, I, R>(n: uint,
                               map: &mut M,
@@ -33,7 +33,8 @@ pub fn insert_rand_n<M, I, R>(n: uint,
         let k = rng.gen::<uint>() % n;
         insert(map, k);
         remove(map, k);
-    })
+    });
+    black_box(map);
 }
 
 pub fn insert_seq_n<M, I, R>(n: uint,
@@ -55,7 +56,8 @@ pub fn insert_seq_n<M, I, R>(n: uint,
         insert(map, i);
         remove(map, i);
         i = (i + 2) % n;
-    })
+    });
+    black_box(map);
 }
 
 pub fn find_rand_n<M, T, I, F>(n: uint,
@@ -82,7 +84,7 @@ pub fn find_rand_n<M, T, I, F>(n: uint,
     b.iter(|| {
         let t = find(map, keys[i]);
         i = (i + 1) % n;
-        t
+        black_box(t);
     })
 }
 
@@ -104,6 +106,6 @@ pub fn find_seq_n<M, T, I, F>(n: uint,
     b.iter(|| {
         let x = find(map, i);
         i = (i + 1) % n;
-        x
+        black_box(x);
     })
 }
index 4a550e5ce277d5eb7b1f8267bb567f9a72b02e6d..82002f16133ec9bf9742623a01c99c3a172b4965 100644 (file)
@@ -211,7 +211,7 @@ pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
     ///
     /// ```
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]);
+    /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]);
     /// ```
     pub fn from_vec(vec: Vec<T>) -> BinaryHeap<T> {
         let mut heap = BinaryHeap { data: vec };
@@ -230,7 +230,7 @@ pub fn from_vec(vec: Vec<T>) -> BinaryHeap<T> {
     ///
     /// ```
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]);
+    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order
     /// for x in heap.iter() {
@@ -250,7 +250,7 @@ pub fn iter(&self) -> Iter<T> {
     ///
     /// ```
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]);
+    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order
     /// for x in heap.into_iter() {
@@ -272,7 +272,7 @@ pub fn into_iter(self) -> IntoIter<T> {
     /// let mut heap = BinaryHeap::new();
     /// assert_eq!(heap.peek(), None);
     ///
-    /// heap.push(1i);
+    /// heap.push(1);
     /// heap.push(5);
     /// heap.push(2);
     /// assert_eq!(heap.peek(), Some(&5));
@@ -355,7 +355,7 @@ pub fn shrink_to_fit(&mut self) {
     ///
     /// ```
     /// use std::collections::BinaryHeap;
-    /// let mut heap = BinaryHeap::from_vec(vec![1i, 3]);
+    /// let mut heap = BinaryHeap::from_vec(vec![1, 3]);
     ///
     /// assert_eq!(heap.pop(), Some(3));
     /// assert_eq!(heap.pop(), Some(1));
@@ -379,7 +379,7 @@ pub fn pop(&mut self) -> Option<T> {
     /// ```
     /// use std::collections::BinaryHeap;
     /// let mut heap = BinaryHeap::new();
-    /// heap.push(3i);
+    /// heap.push(3);
     /// heap.push(5);
     /// heap.push(1);
     ///
@@ -401,7 +401,7 @@ pub fn push(&mut self, item: T) {
     /// ```
     /// use std::collections::BinaryHeap;
     /// let mut heap = BinaryHeap::new();
-    /// heap.push(1i);
+    /// heap.push(1);
     /// heap.push(5);
     ///
     /// assert_eq!(heap.push_pop(3), 5);
@@ -433,7 +433,7 @@ pub fn push_pop(&mut self, mut item: T) -> T {
     /// use std::collections::BinaryHeap;
     /// let mut heap = BinaryHeap::new();
     ///
-    /// assert_eq!(heap.replace(1i), None);
+    /// assert_eq!(heap.replace(1), None);
     /// assert_eq!(heap.replace(3), Some(1));
     /// assert_eq!(heap.len(), 1);
     /// assert_eq!(heap.peek(), Some(&3));
@@ -456,7 +456,7 @@ pub fn replace(&mut self, mut item: T) -> Option<T> {
     ///
     /// ```
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]);
+    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4, 5, 6, 7]);
     /// let vec = heap.into_vec();
     ///
     /// // Will print in some order
@@ -474,12 +474,12 @@ pub fn into_vec(self) -> Vec<T> { self.data }
     /// ```
     /// use std::collections::BinaryHeap;
     ///
-    /// let mut heap = BinaryHeap::from_vec(vec![1i, 2, 4, 5, 7]);
+    /// let mut heap = BinaryHeap::from_vec(vec![1, 2, 4, 5, 7]);
     /// heap.push(6);
     /// heap.push(3);
     ///
     /// let vec = heap.into_sorted_vec();
-    /// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]);
+    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]);
     /// ```
     pub fn into_sorted_vec(mut self) -> Vec<T> {
         let mut end = self.len();
index 5e7089bb7aca2ebae6cde8d03b137fc9de2c2ee3..c092e000215d3ffdc1858c3bbf5762a2abf2b8a2 100644 (file)
@@ -164,21 +164,6 @@ pub struct Bitv {
     nbits: uint
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-// FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing)
-impl Index<uint,bool> for Bitv {
-    #[inline]
-    fn index(&self, i: &uint) -> &bool {
-        if self.get(*i).expect("index out of bounds") {
-            &TRUE
-        } else {
-            &FALSE
-        }
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 // FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing)
 impl Index<uint> for Bitv {
     type Output = bool;
index 3a722178bc02c90aa91de7e3486db4a85cb590f7..ea504530c4b21309b2660a5f1449c29742b855fe 100644 (file)
@@ -19,7 +19,7 @@
 
 use core::prelude::*;
 
-use core::borrow::BorrowFrom;
+use core::borrow::{BorrowFrom, ToOwned};
 use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt::Show;
@@ -128,20 +128,23 @@ pub struct Values<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
 }
 
+#[stable]
 /// A view into a single entry in a map, which may either be vacant or occupied.
-pub enum Entry<'a, K:'a, V:'a> {
+pub enum Entry<'a, Sized? Q:'a, K:'a, V:'a> {
     /// A vacant Entry
-    Vacant(VacantEntry<'a, K, V>),
+    Vacant(VacantEntry<'a, Q, K, V>),
     /// An occupied Entry
     Occupied(OccupiedEntry<'a, K, V>),
 }
 
+#[stable]
 /// A vacant Entry.
-pub struct VacantEntry<'a, K:'a, V:'a> {
-    key: K,
+pub struct VacantEntry<'a, Sized? Q:'a, K:'a, V:'a> {
+    key: &'a Q,
     stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>,
 }
 
+#[stable]
 /// An occupied Entry.
 pub struct OccupiedEntry<'a, K:'a, V:'a> {
     stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>,
@@ -874,18 +877,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
-    where Q: BorrowFrom<K> + Ord
-{
-    fn index(&self, key: &Q) -> &V {
-        self.get(key).expect("no entry found for key")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<K: Ord, Sized? Q, V> Index<Q> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
@@ -897,18 +888,6 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for BTreeMap<K, V>
-    where Q: BorrowFrom<K> + Ord
-{
-    fn index_mut(&mut self, key: &Q) -> &mut V {
-        self.get_mut(key).expect("no entry found for key")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<K: Ord, Sized? Q, V> IndexMut<Q> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
@@ -1132,40 +1111,56 @@ fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
 #[stable]
 impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
 
+impl<'a, Sized? Q, K: Ord, V> Entry<'a, Q, K, V> {
+    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
+    pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
+        match self {
+            Occupied(entry) => Ok(entry.into_mut()),
+            Vacant(entry) => Err(entry),
+        }
+    }
+}
 
-impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
+impl<'a, Sized? Q: ToOwned<K>, K: Ord, V> VacantEntry<'a, Q, K, V> {
+    #[stable]
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it.
-    pub fn set(self, value: V) -> &'a mut V {
-        self.stack.insert(self.key, value)
+    pub fn insert(self, value: V) -> &'a mut V {
+        self.stack.insert(self.key.to_owned(), value)
     }
 }
 
 impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
+    #[stable]
     /// Gets a reference to the value in the entry.
     pub fn get(&self) -> &V {
         self.stack.peek()
     }
 
+    #[stable]
     /// Gets a mutable reference to the value in the entry.
     pub fn get_mut(&mut self) -> &mut V {
         self.stack.peek_mut()
     }
 
+    #[stable]
     /// Converts the entry into a mutable reference to its value.
     pub fn into_mut(self) -> &'a mut V {
         self.stack.into_top()
     }
 
+    #[stable]
     /// Sets the value of the entry with the OccupiedEntry's key,
     /// and returns the entry's old value.
-    pub fn set(&mut self, mut value: V) -> V {
+    pub fn insert(&mut self, mut value: V) -> V {
         mem::swap(self.stack.peek_mut(), &mut value);
         value
     }
 
+    #[stable]
     /// Takes the value of the entry out of the map, and returns it.
-    pub fn take(self) -> V {
+    pub fn remove(self) -> V {
         self.stack.remove()
     }
 }
@@ -1352,9 +1347,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
     ///
     /// // count the number of occurrences of letters in the vec
     /// for x in vec!["a","b","a","c","a","b"].iter() {
-    ///     match count.entry(*x) {
+    ///     match count.entry(x) {
     ///         Entry::Vacant(view) => {
-    ///             view.set(1);
+    ///             view.insert(1);
     ///         },
     ///         Entry::Occupied(mut view) => {
     ///             let v = view.get_mut();
@@ -1365,12 +1360,16 @@ impl<K: Ord, V> BTreeMap<K, V> {
     ///
     /// assert_eq!(count["a"], 3u);
     /// ```
-    pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
+    /// The key must have the same ordering before or after `.to_owned()` is called.
+    #[stable]
+    pub fn entry<'a, Sized? Q>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V>
+        where Q: Ord + ToOwned<K>
+    {
         // same basic logic of `swap` and `pop`, blended together
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                return match Node::search(node, &key) {
+                return match Node::search(node, key) {
                     Found(handle) => {
                         // Perfect match
                         Finished(Occupied(OccupiedEntry {
@@ -1413,6 +1412,7 @@ pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
 #[cfg(test)]
 mod test {
     use prelude::*;
+    use std::borrow::{ToOwned, BorrowFrom};
 
     use super::{BTreeMap, Occupied, Vacant};
 
@@ -1562,11 +1562,11 @@ fn test_entry(){
         let mut map: BTreeMap<int, int> = xs.iter().map(|&x| x).collect();
 
         // Existing key (insert)
-        match map.entry(1) {
+        match map.entry(&1) {
             Vacant(_) => unreachable!(),
             Occupied(mut view) => {
                 assert_eq!(view.get(), &10);
-                assert_eq!(view.set(100), 10);
+                assert_eq!(view.insert(100), 10);
             }
         }
         assert_eq!(map.get(&1).unwrap(), &100);
@@ -1574,7 +1574,7 @@ fn test_entry(){
 
 
         // Existing key (update)
-        match map.entry(2) {
+        match map.entry(&2) {
             Vacant(_) => unreachable!(),
             Occupied(mut view) => {
                 let v = view.get_mut();
@@ -1585,10 +1585,10 @@ fn test_entry(){
         assert_eq!(map.len(), 6);
 
         // Existing key (take)
-        match map.entry(3) {
+        match map.entry(&3) {
             Vacant(_) => unreachable!(),
             Occupied(view) => {
-                assert_eq!(view.take(), 30);
+                assert_eq!(view.remove(), 30);
             }
         }
         assert_eq!(map.get(&3), None);
@@ -1596,10 +1596,10 @@ fn test_entry(){
 
 
         // Inexistent key (insert)
-        match map.entry(10) {
+        match map.entry(&10) {
             Occupied(_) => unreachable!(),
             Vacant(view) => {
-                assert_eq!(*view.set(1000), 1000);
+                assert_eq!(*view.insert(1000), 1000);
             }
         }
         assert_eq!(map.get(&10).unwrap(), &1000);
index 0406edcdd32e7ac622bbb277544f63120df93e93..80d01c07547d192b1691849e762854a04d4456ae 100644 (file)
@@ -245,7 +245,7 @@ pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
     ///
     /// let mut v = BTreeSet::new();
     /// assert_eq!(v.len(), 0);
-    /// v.insert(1i);
+    /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
     #[stable]
@@ -260,7 +260,7 @@ pub fn len(&self) -> uint { self.map.len() }
     ///
     /// let mut v = BTreeSet::new();
     /// assert!(v.is_empty());
-    /// v.insert(1i);
+    /// v.insert(1);
     /// assert!(!v.is_empty());
     /// ```
     #[stable]
@@ -274,7 +274,7 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
     /// use std::collections::BTreeSet;
     ///
     /// let mut v = BTreeSet::new();
-    /// v.insert(1i);
+    /// v.insert(1);
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
@@ -294,7 +294,7 @@ pub fn clear(&mut self) {
     /// ```
     /// use std::collections::BTreeSet;
     ///
-    /// let set: BTreeSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
+    /// let set: BTreeSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
@@ -311,7 +311,7 @@ pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord
     /// ```
     /// use std::collections::BTreeSet;
     ///
-    /// let a: BTreeSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
+    /// let a: BTreeSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
     /// let mut b: BTreeSet<int> = BTreeSet::new();
     ///
     /// assert_eq!(a.is_disjoint(&b), true);
@@ -332,7 +332,7 @@ pub fn is_disjoint(&self, other: &BTreeSet<T>) -> bool {
     /// ```
     /// use std::collections::BTreeSet;
     ///
-    /// let sup: BTreeSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
+    /// let sup: BTreeSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
     /// let mut set: BTreeSet<int> = BTreeSet::new();
     ///
     /// assert_eq!(set.is_subset(&sup), true);
@@ -374,7 +374,7 @@ pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
     /// ```
     /// use std::collections::BTreeSet;
     ///
-    /// let sub: BTreeSet<int> = [1i, 2].iter().map(|&x| x).collect();
+    /// let sub: BTreeSet<int> = [1, 2].iter().map(|&x| x).collect();
     /// let mut set: BTreeSet<int> = BTreeSet::new();
     ///
     /// assert_eq!(set.is_superset(&sub), false);
@@ -401,8 +401,8 @@ pub fn is_superset(&self, other: &BTreeSet<T>) -> bool {
     ///
     /// let mut set = BTreeSet::new();
     ///
-    /// assert_eq!(set.insert(2i), true);
-    /// assert_eq!(set.insert(2i), false);
+    /// assert_eq!(set.insert(2), true);
+    /// assert_eq!(set.insert(2), false);
     /// assert_eq!(set.len(), 1);
     /// ```
     #[stable]
@@ -424,7 +424,7 @@ pub fn insert(&mut self, value: T) -> bool {
     ///
     /// let mut set = BTreeSet::new();
     ///
-    /// set.insert(2i);
+    /// set.insert(2);
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
index ca8e75ac43c8d6f84ebe1f3d6331b2b3d251e542..5aec9973c811224338b236d7b41fb86d48c4ea63 100644 (file)
@@ -230,9 +230,9 @@ pub fn new() -> DList<T> {
     ///
     /// let mut a = DList::new();
     /// let mut b = DList::new();
-    /// a.push_back(1i);
+    /// a.push_back(1);
     /// a.push_back(2);
-    /// b.push_back(3i);
+    /// b.push_back(3);
     /// b.push_back(4);
     ///
     /// a.append(b);
@@ -375,7 +375,7 @@ pub fn pop_front(&mut self) -> Option<T> {
     /// use std::collections::DList;
     ///
     /// let mut d = DList::new();
-    /// d.push_back(1i);
+    /// d.push_back(1);
     /// d.push_back(3);
     /// assert_eq!(3, *d.back().unwrap());
     /// ```
@@ -394,7 +394,7 @@ pub fn push_back(&mut self, elt: T) {
     ///
     /// let mut d = DList::new();
     /// assert_eq!(d.pop_back(), None);
-    /// d.push_back(1i);
+    /// d.push_back(1);
     /// d.push_back(3);
     /// assert_eq!(d.pop_back(), Some(3));
     /// ```
@@ -551,7 +551,7 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// {
     ///     let vec: Vec<int> = list.into_iter().collect();
-    ///     assert_eq!(vec, vec![1i, 2, 3, 4]);
+    ///     assert_eq!(vec, vec![1, 2, 3, 4]);
     /// }
     /// ```
     #[inline]
index 944b224fed8546d6c9b6ed5e7522baabf21c5bcc..db2367950387b4a125d74446770a90fb07e6dc35 100644 (file)
@@ -103,7 +103,6 @@ mod std {
 mod prelude {
     // from core.
     pub use core::borrow::IntoCow;
-    pub use core::char::Char;
     pub use core::clone::Clone;
     pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
     pub use core::cmp::Ordering::{Less, Equal, Greater};
@@ -127,7 +126,7 @@ mod prelude {
 
     // from other crates.
     pub use alloc::boxed::Box;
-    pub use unicode::char::UnicodeChar;
+    pub use unicode::char::CharExt;
 
     // from collections.
     pub use slice::SliceConcatExt;
index e86c40bed212f90b71f79c96fd9cadba8bad205f..8a83bf25e9b098404644bd38aa9ec6af3df20caf 100644 (file)
@@ -17,7 +17,7 @@
 use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt;
-use core::iter::{self, FromIterator, RandomAccessIterator};
+use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
 use core::kinds::marker;
 use core::mem;
 use core::num::{Int, UnsignedInt};
 
 use alloc::heap;
 
-static INITIAL_CAPACITY: uint = 8u; // 2^3
-static MINIMUM_CAPACITY: uint = 2u;
-
-// FIXME(conventions): implement shrink_to_fit. Awkward with the current design, but it should
-// be scrapped anyway. Defer to rewrite?
+static INITIAL_CAPACITY: uint = 7u; // 2^3 - 1
+static MINIMUM_CAPACITY: uint = 1u; // 2 - 1
 
 /// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
 #[stable]
@@ -127,7 +124,20 @@ unsafe fn copy(&self, dst: uint, src: uint, len: uint) {
                       self.cap);
         ptr::copy_memory(
             self.ptr.offset(dst as int),
-            self.ptr.offset(src as int) as *const T,
+            self.ptr.offset(src as int),
+            len);
+    }
+
+    /// Copies a contiguous block of memory len long from src to dst
+    #[inline]
+    unsafe fn copy_nonoverlapping(&self, dst: uint, src: uint, len: uint) {
+        debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+                      self.cap);
+        debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+                      self.cap);
+        ptr::copy_nonoverlapping_memory(
+            self.ptr.offset(dst as int),
+            self.ptr.offset(src as int),
             len);
     }
 }
@@ -143,7 +153,8 @@ pub fn new() -> RingBuf<T> {
     #[stable]
     pub fn with_capacity(n: uint) -> RingBuf<T> {
         // +1 since the ringbuffer always leaves one space empty
-        let cap = cmp::max(n + 1, MINIMUM_CAPACITY).next_power_of_two();
+        let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+        assert!(cap > n, "capacity overflow");
         let size = cap.checked_mul(mem::size_of::<T>())
                       .expect("capacity overflow");
 
@@ -173,7 +184,7 @@ pub fn with_capacity(n: uint) -> RingBuf<T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(3i);
+    /// buf.push_back(3);
     /// buf.push_back(4);
     /// buf.push_back(5);
     /// assert_eq!(buf.get(1).unwrap(), &4);
@@ -196,7 +207,7 @@ pub fn get(&self, i: uint) -> Option<&T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(3i);
+    /// buf.push_back(3);
     /// buf.push_back(4);
     /// buf.push_back(5);
     /// match buf.get_mut(1) {
@@ -230,7 +241,7 @@ pub fn get_mut(&mut self, i: uint) -> Option<&mut T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(3i);
+    /// buf.push_back(3);
     /// buf.push_back(4);
     /// buf.push_back(5);
     /// buf.swap(0, 2);
@@ -346,23 +357,16 @@ pub fn reserve(&mut self, additional: uint) {
                 // Nop
             } else if self.head < oldcap - self.tail { // B
                 unsafe {
-                    ptr::copy_nonoverlapping_memory(
-                        self.ptr.offset(oldcap as int),
-                        self.ptr as *const T,
-                        self.head
-                    );
+                    self.copy_nonoverlapping(oldcap, 0, self.head);
                 }
                 self.head += oldcap;
                 debug_assert!(self.head > self.tail);
             } else { // C
+                let new_tail = count - (oldcap - self.tail);
                 unsafe {
-                    ptr::copy_nonoverlapping_memory(
-                        self.ptr.offset((count - (oldcap - self.tail)) as int),
-                        self.ptr.offset(self.tail as int) as *const T,
-                        oldcap - self.tail
-                    );
+                    self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
                 }
-                self.tail = count - (oldcap - self.tail);
+                self.tail = new_tail;
                 debug_assert!(self.head < self.tail);
             }
             debug_assert!(self.head < self.cap);
@@ -371,6 +375,116 @@ pub fn reserve(&mut self, additional: uint) {
         }
     }
 
+    /// Shrinks the capacity of the ringbuf as much as possible.
+    ///
+    /// It will drop down as close as possible to the length but the allocator may still inform the
+    /// ringbuf that there is space for a few more elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::RingBuf;
+    ///
+    /// let mut buf = RingBuf::with_capacity(15);
+    /// buf.extend(range(0u, 4));
+    /// assert_eq!(buf.capacity(), 15);
+    /// buf.shrink_to_fit();
+    /// assert!(buf.capacity() >= 4);
+    /// ```
+    pub fn shrink_to_fit(&mut self) {
+        // +1 since the ringbuffer always leaves one space empty
+        // len + 1 can't overflow for an existing, well-formed ringbuf.
+        let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+        if target_cap < self.cap {
+            // There are three cases of interest:
+            //   All elements are out of desired bounds
+            //   Elements are contiguous, and head is out of desired bounds
+            //   Elements are discontiguous, and tail is out of desired bounds
+            //
+            // At all other times, element positions are unaffected.
+            //
+            // Indicates that elements at the head should be moved.
+            let head_outside = self.head == 0 || self.head >= target_cap;
+            // Move elements from out of desired bounds (positions after target_cap)
+            if self.tail >= target_cap && head_outside {
+                //                    T             H
+                //   [. . . . . . . . o o o o o o o . ]
+                //    T             H
+                //   [o o o o o o o . ]
+                unsafe {
+                    self.copy_nonoverlapping(0, self.tail, self.len());
+                }
+                self.head = self.len();
+                self.tail = 0;
+            } else if self.tail != 0 && self.tail < target_cap && head_outside {
+                //          T             H
+                //   [. . . o o o o o o o . . . . . . ]
+                //        H T
+                //   [o o . o o o o o ]
+                let len = self.wrap_index(self.head - target_cap);
+                unsafe {
+                    self.copy_nonoverlapping(0, target_cap, len);
+                }
+                self.head = len;
+                debug_assert!(self.head < self.tail);
+            } else if self.tail >= target_cap {
+                //              H                 T
+                //   [o o o o o . . . . . . . . . o o ]
+                //              H T
+                //   [o o o o o . o o ]
+                debug_assert!(self.wrap_index(self.head - 1) < target_cap);
+                let len = self.cap - self.tail;
+                let new_tail = target_cap - len;
+                unsafe {
+                    self.copy_nonoverlapping(new_tail, self.tail, len);
+                }
+                self.tail = new_tail;
+                debug_assert!(self.head < self.tail);
+            }
+
+            if mem::size_of::<T>() != 0 {
+                let old = self.cap * mem::size_of::<T>();
+                let new_size = target_cap * mem::size_of::<T>();
+                unsafe {
+                    self.ptr = heap::reallocate(self.ptr as *mut u8,
+                                                old,
+                                                new_size,
+                                                mem::min_align_of::<T>()) as *mut T;
+                    if self.ptr.is_null() { ::alloc::oom() }
+                }
+            }
+            self.cap = target_cap;
+            debug_assert!(self.head < self.cap);
+            debug_assert!(self.tail < self.cap);
+            debug_assert!(self.cap.count_ones() == 1);
+        }
+    }
+
+    /// Shorten a ringbuf, dropping excess elements from the back.
+    ///
+    /// If `len` is greater than the ringbuf's current length, this has no
+    /// effect.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::RingBuf;
+    ///
+    /// let mut buf = RingBuf::new();
+    /// buf.push_back(5i);
+    /// buf.push_back(10i);
+    /// buf.push_back(15);
+    /// buf.truncate(1);
+    /// assert_eq!(buf.len(), 1);
+    /// assert_eq!(Some(&5), buf.get(0));
+    /// ```
+    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    pub fn truncate(&mut self, len: uint) {
+        for _ in range(len, self.len()) {
+            self.pop_back();
+        }
+    }
+
     /// Returns a front-to-back iterator.
     ///
     /// # Examples
@@ -379,7 +493,7 @@ pub fn reserve(&mut self, additional: uint) {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(5i);
+    /// buf.push_back(5);
     /// buf.push_back(3);
     /// buf.push_back(4);
     /// let b: &[_] = &[&5, &3, &4];
@@ -402,7 +516,7 @@ pub fn iter(&self) -> Iter<T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(5i);
+    /// buf.push_back(5);
     /// buf.push_back(3);
     /// buf.push_back(4);
     /// for num in buf.iter_mut() {
@@ -481,7 +595,7 @@ pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [T], &'a mut [T]) {
     ///
     /// let mut v = RingBuf::new();
     /// assert_eq!(v.len(), 0);
-    /// v.push_back(1i);
+    /// v.push_back(1);
     /// assert_eq!(v.len(), 1);
     /// ```
     #[stable]
@@ -496,7 +610,7 @@ pub fn len(&self) -> uint { count(self.tail, self.head, self.cap) }
     ///
     /// let mut v = RingBuf::new();
     /// assert!(v.is_empty());
-    /// v.push_front(1i);
+    /// v.push_front(1);
     /// assert!(!v.is_empty());
     /// ```
     #[stable]
@@ -511,7 +625,7 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
     /// use std::collections::RingBuf;
     ///
     /// let mut v = RingBuf::new();
-    /// v.push_back(1i);
+    /// v.push_back(1);
     /// assert_eq!(v.drain().next(), Some(1));
     /// assert!(v.is_empty());
     /// ```
@@ -531,7 +645,7 @@ pub fn drain(&mut self) -> Drain<T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut v = RingBuf::new();
-    /// v.push_back(1i);
+    /// v.push_back(1);
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
@@ -552,9 +666,9 @@ pub fn clear(&mut self) {
     /// let mut d = RingBuf::new();
     /// assert_eq!(d.front(), None);
     ///
-    /// d.push_back(1i);
-    /// d.push_back(2i);
-    /// assert_eq!(d.front(), Some(&1i));
+    /// d.push_back(1);
+    /// d.push_back(2);
+    /// assert_eq!(d.front(), Some(&1));
     /// ```
     #[stable]
     pub fn front(&self) -> Option<&T> {
@@ -572,13 +686,13 @@ pub fn front(&self) -> Option<&T> {
     /// let mut d = RingBuf::new();
     /// assert_eq!(d.front_mut(), None);
     ///
-    /// d.push_back(1i);
-    /// d.push_back(2i);
+    /// d.push_back(1);
+    /// d.push_back(2);
     /// match d.front_mut() {
-    ///     Some(x) => *x = 9i,
+    ///     Some(x) => *x = 9,
     ///     None => (),
     /// }
-    /// assert_eq!(d.front(), Some(&9i));
+    /// assert_eq!(d.front(), Some(&9));
     /// ```
     #[stable]
     pub fn front_mut(&mut self) -> Option<&mut T> {
@@ -596,9 +710,9 @@ pub fn front_mut(&mut self) -> Option<&mut T> {
     /// let mut d = RingBuf::new();
     /// assert_eq!(d.back(), None);
     ///
-    /// d.push_back(1i);
-    /// d.push_back(2i);
-    /// assert_eq!(d.back(), Some(&2i));
+    /// d.push_back(1);
+    /// d.push_back(2);
+    /// assert_eq!(d.back(), Some(&2));
     /// ```
     #[stable]
     pub fn back(&self) -> Option<&T> {
@@ -616,13 +730,13 @@ pub fn back(&self) -> Option<&T> {
     /// let mut d = RingBuf::new();
     /// assert_eq!(d.back(), None);
     ///
-    /// d.push_back(1i);
-    /// d.push_back(2i);
+    /// d.push_back(1);
+    /// d.push_back(2);
     /// match d.back_mut() {
-    ///     Some(x) => *x = 9i,
+    ///     Some(x) => *x = 9,
     ///     None => (),
     /// }
-    /// assert_eq!(d.back(), Some(&9i));
+    /// assert_eq!(d.back(), Some(&9));
     /// ```
     #[stable]
     pub fn back_mut(&mut self) -> Option<&mut T> {
@@ -639,11 +753,11 @@ pub fn back_mut(&mut self) -> Option<&mut T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut d = RingBuf::new();
-    /// d.push_back(1i);
-    /// d.push_back(2i);
+    /// d.push_back(1);
+    /// d.push_back(2);
     ///
-    /// assert_eq!(d.pop_front(), Some(1i));
-    /// assert_eq!(d.pop_front(), Some(2i));
+    /// assert_eq!(d.pop_front(), Some(1));
+    /// assert_eq!(d.pop_front(), Some(2));
     /// assert_eq!(d.pop_front(), None);
     /// ```
     #[stable]
@@ -665,9 +779,9 @@ pub fn pop_front(&mut self) -> Option<T> {
     /// use std::collections::RingBuf;
     ///
     /// let mut d = RingBuf::new();
-    /// d.push_front(1i);
-    /// d.push_front(2i);
-    /// assert_eq!(d.front(), Some(&2i));
+    /// d.push_front(1);
+    /// d.push_front(2);
+    /// assert_eq!(d.front(), Some(&2));
     /// ```
     #[stable]
     pub fn push_front(&mut self, t: T) {
@@ -689,7 +803,7 @@ pub fn push_front(&mut self, t: T) {
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(1i);
+    /// buf.push_back(1);
     /// buf.push_back(3);
     /// assert_eq!(3, *buf.back().unwrap());
     /// ```
@@ -715,7 +829,7 @@ pub fn push_back(&mut self, t: T) {
     ///
     /// let mut buf = RingBuf::new();
     /// assert_eq!(buf.pop_back(), None);
-    /// buf.push_back(1i);
+    /// buf.push_back(1);
     /// buf.push_back(3);
     /// assert_eq!(buf.pop_back(), Some(3));
     /// ```
@@ -735,6 +849,70 @@ fn is_contiguous(&self) -> bool {
         self.tail <= self.head
     }
 
+    /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
+    /// element.
+    ///
+    /// This does not preserve ordering, but is O(1).
+    ///
+    /// Returns `None` if `index` is out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::RingBuf;
+    ///
+    /// let mut buf = RingBuf::new();
+    /// assert_eq!(buf.swap_back_remove(0), None);
+    /// buf.push_back(5i);
+    /// buf.push_back(99);
+    /// buf.push_back(15);
+    /// buf.push_back(20);
+    /// buf.push_back(10);
+    /// assert_eq!(buf.swap_back_remove(1), Some(99));
+    /// ```
+    #[unstable = "the naming of this function may be altered"]
+    pub fn swap_back_remove(&mut self, index: uint) -> Option<T> {
+        let length = self.len();
+        if length > 0 && index < length - 1 {
+            self.swap(index, length - 1);
+        } else if index >= length {
+            return None;
+        }
+        self.pop_back()
+    }
+
+    /// 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).
+    ///
+    /// Returns `None` if `index` is out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::RingBuf;
+    ///
+    /// let mut buf = RingBuf::new();
+    /// assert_eq!(buf.swap_front_remove(0), None);
+    /// buf.push_back(15i);
+    /// buf.push_back(5);
+    /// buf.push_back(10);
+    /// buf.push_back(99);
+    /// buf.push_back(20i);
+    /// assert_eq!(buf.swap_front_remove(3), Some(99));
+    /// ```
+    #[unstable = "the naming of this function may be altered"]
+    pub fn swap_front_remove(&mut self, index: uint) -> Option<T> {
+        let length = self.len();
+        if length > 0 && index < length && index != 0 {
+            self.swap(index, 0);
+        } else if index >= length {
+            return None;
+        }
+        self.pop_front()
+    }
+
     /// Inserts an element at position `i` within the ringbuf. Whichever
     /// end is closer to the insertion point will be moved to make room,
     /// and all the affected elements will be moved to new positions.
@@ -743,12 +921,12 @@ fn is_contiguous(&self) -> bool {
     ///
     /// Panics if `i` is greater than ringbuf's length
     ///
-    /// # Example
+    /// # Examples
     /// ```rust
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(10i);
+    /// buf.push_back(10);
     /// buf.push_back(12);
     /// buf.insert(1,11);
     /// assert_eq!(Some(&11), buf.get(1));
@@ -945,14 +1123,14 @@ pub fn insert(&mut self, i: uint, t: T) {
     /// room, and all the affected elements will be moved to new positions.
     /// Returns `None` if `i` is out of bounds.
     ///
-    /// # Example
+    /// # Examples
     /// ```rust
     /// use std::collections::RingBuf;
     ///
     /// let mut buf = RingBuf::new();
-    /// buf.push_back(5i);
-    /// buf.push_back(10i);
-    /// buf.push_back(12i);
+    /// buf.push_back(5);
+    /// buf.push_back(10);
+    /// buf.push_back(12);
     /// buf.push_back(15);
     /// buf.remove(2);
     /// assert_eq!(Some(&15), buf.get(2));
@@ -990,7 +1168,7 @@ pub fn remove(&mut self, i: uint) -> Option<T> {
         let distance_to_tail = i;
         let distance_to_head = self.len() - i;
 
-        let contiguous = self.tail <= self.head;
+        let contiguous = self.is_contiguous();
 
         match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
             (true, true, _) => unsafe {
@@ -1105,6 +1283,37 @@ pub fn remove(&mut self, i: uint) -> Option<T> {
     }
 }
 
+impl<T: Clone> RingBuf<T> {
+    /// Modifies the ringbuf in-place so that `len()` is equal to new_len,
+    /// either by removing excess elements or by appending copies of a value to the back.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::RingBuf;
+    ///
+    /// let mut buf = RingBuf::new();
+    /// buf.push_back(5i);
+    /// buf.push_back(10i);
+    /// 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()) {
+    ///     assert_eq!(a, b);
+    /// }
+    /// ```
+    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    pub fn resize(&mut self, new_len: uint, value: T) {
+        let len = self.len();
+
+        if new_len > len {
+            self.extend(repeat(value).take(new_len - len))
+        } else {
+            self.truncate(new_len);
+        }
+    }
+}
+
 /// Returns the index in the underlying buffer for a given logical element index.
 #[inline]
 fn wrap_index(index: uint, size: uint) -> uint {
@@ -1360,17 +1569,6 @@ fn hash(&self, state: &mut S) {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<A> Index<uint, A> for RingBuf<A> {
-    #[inline]
-    fn index<'a>(&'a self, i: &uint) -> &'a A {
-        self.get(*i).expect("Out of bounds access")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<A> Index<uint> for RingBuf<A> {
     type Output = A;
@@ -1381,17 +1579,6 @@ fn index<'a>(&'a self, i: &uint) -> &'a A {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<A> IndexMut<uint, A> for RingBuf<A> {
-    #[inline]
-    fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A {
-        self.get_mut(*i).expect("Out of bounds access")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<A> IndexMut<uint> for RingBuf<A> {
     type Output = A;
@@ -2292,6 +2479,50 @@ fn test_get_mut() {
         assert_eq!(ring.get_mut(2), None);
     }
 
+    #[test]
+    fn test_swap_front_back_remove() {
+        fn test(back: bool) {
+            // This test checks that every single combination of tail position and length is tested.
+            // Capacity 15 should be large enough to cover every case.
+            let mut tester = RingBuf::with_capacity(15);
+            let usable_cap = tester.capacity();
+            let final_len = usable_cap / 2;
+
+            for len in range(0, final_len) {
+                let expected = if back {
+                    range(0, len).collect()
+                } else {
+                    range(0, len).rev().collect()
+                };
+                for tail_pos in range(0, usable_cap) {
+                    tester.tail = tail_pos;
+                    tester.head = tail_pos;
+                    if back {
+                        for i in range(0, len * 2) {
+                            tester.push_front(i);
+                        }
+                        for i in range(0, len) {
+                            assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i));
+                        }
+                    } else {
+                        for i in range(0, len * 2) {
+                            tester.push_back(i);
+                        }
+                        for i in range(0, len) {
+                            let idx = tester.len() - 1 - i;
+                            assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
+                        }
+                    }
+                    assert!(tester.tail < tester.cap);
+                    assert!(tester.head < tester.cap);
+                    assert_eq!(tester, expected);
+                }
+            }
+        }
+        test(true);
+        test(false);
+    }
+
     #[test]
     fn test_insert() {
         // This test checks that every single combination of tail position, length, and
@@ -2363,6 +2594,38 @@ fn test_remove() {
         }
     }
 
+    #[test]
+    fn test_shrink_to_fit() {
+        // This test checks that every single combination of head and tail position,
+        // is tested. Capacity 15 should be large enough to cover every case.
+
+        let mut tester = RingBuf::with_capacity(15);
+        // can't guarantee we got 15, so have to get what we got.
+        // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+        // this test isn't covering what it wants to
+        let cap = tester.capacity();
+        tester.reserve(63);
+        let max_cap = tester.capacity();
+
+        for len in range(0, cap + 1) {
+            // 0, 1, 2, .., len - 1
+            let expected = iter::count(0, 1).take(len).collect();
+            for tail_pos in range(0, max_cap + 1) {
+                tester.tail = tail_pos;
+                tester.head = tail_pos;
+                tester.reserve(63);
+                for i in range(0, len) {
+                    tester.push_back(i);
+                }
+                tester.shrink_to_fit();
+                assert!(tester.capacity() <= cap);
+                assert!(tester.tail < tester.cap);
+                assert!(tester.head < tester.cap);
+                assert_eq!(tester, expected);
+            }
+        }
+    }
+
     #[test]
     fn test_front() {
         let mut ring = RingBuf::new();
index 3602bfc10c3079b5b67a5914a7074b9c465f8c48..8050c44f54281b763a8b065d5816e288108653fc 100644 (file)
@@ -15,7 +15,7 @@
 //!
 //! ```rust
 //! // slicing a Vec
-//! let vec = vec!(1i, 2, 3);
+//! let vec = vec!(1, 2, 3);
 //! let int_slice = vec.as_slice();
 //! // coercing an array to a slice
 //! let str_slice: &[&str] = &["one", "two", "three"];
@@ -26,7 +26,7 @@
 //! block of memory that a mutable slice points to:
 //!
 //! ```rust
-//! let x: &mut[int] = &mut [1i, 2, 3];
+//! let x: &mut[int] = &mut [1, 2, 3];
 //! x[1] = 7;
 //! assert_eq!(x[0], 1);
 //! assert_eq!(x[1], 7);
@@ -54,9 +54,9 @@
 //! ```rust
 //! #![feature(slicing_syntax)]
 //! fn main() {
-//!     let numbers = [0i, 1i, 2i];
+//!     let numbers = [0, 1, 2];
 //!     let last_numbers = numbers[1..3];
-//!     // last_numbers is now &[1i, 2i]
+//!     // last_numbers is now &[1, 2]
 //! }
 //! ```
 //!
@@ -76,7 +76,7 @@
 //! type of the slice is `int`, the element type of the iterator is `&int`.
 //!
 //! ```rust
-//! let numbers = [0i, 1i, 2i];
+//! let numbers = [0, 1, 2];
 //! for &x in numbers.iter() {
 //!     println!("{} is a number!", x);
 //! }
 
 use alloc::boxed::Box;
 use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
-use core::clone::Clone;
-use core::cmp::Ordering::{self, Greater, Less};
-use core::cmp::{self, Ord, PartialEq};
-use core::iter::{Iterator, IteratorExt};
-use core::iter::{range, range_step, MultiplicativeIterator};
+use core::cmp;
+use core::iter::{range_step, MultiplicativeIterator};
 use core::kinds::Sized;
 use core::mem::size_of;
 use core::mem;
-use core::ops::{FnMut, SliceMut};
-use core::option::Option::{self, Some, None};
-use core::ptr::PtrExt;
+use core::ops::{FnMut,SliceMut};
+use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option};
+use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result};
 use core::ptr;
-use core::result::Result;
 use core::slice as core_slice;
 use self::Direction::*;
 
 use vec::Vec;
 
 pub use core::slice::{Chunks, AsSlice, Windows};
-pub use core::slice::{Iter, IterMut};
+pub use core::slice::{Iter, IterMut, PartialEqSliceExt};
 pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
 pub use core::slice::{from_raw_buf, from_raw_mut_buf};
 
+#[deprecated = "use Iter instead"]
+pub type Items<'a, T:'a> = Iter<'a, T>;
+
+#[deprecated = "use IterMut instead"]
+pub type MutItems<'a, T:'a> = IterMut<'a, T>;
+
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Allocating extension methods for slices.
 #[unstable = "needs associated types, may merge with other traits"]
-pub trait SliceExt for Sized? {
-    type Item;
-
+pub trait SliceExt<T> for Sized? {
     /// Sorts the slice, in place, using `compare` to compare
     /// elements.
     ///
@@ -132,7 +132,7 @@ pub trait SliceExt for Sized? {
     /// # Examples
     ///
     /// ```rust
-    /// let mut v = [5i, 4, 1, 3, 2];
+    /// let mut v = [5, 4, 1, 3, 2];
     /// v.sort_by(|a, b| a.cmp(b));
     /// assert!(v == [1, 2, 3, 4, 5]);
     ///
@@ -141,7 +141,7 @@ pub trait SliceExt for Sized? {
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
     #[stable]
-    fn sort_by<F>(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering;
+    fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering;
 
     /// Consumes `src` and moves as many elements as it can into `self`
     /// from the range [start,end).
@@ -158,14 +158,14 @@ pub trait SliceExt for Sized? {
     /// # Examples
     ///
     /// ```rust
-    /// let mut a = [1i, 2, 3, 4, 5];
-    /// let b = vec![6i, 7, 8];
+    /// 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 == [6i, 7, 8, 4, 5]);
+    /// assert!(a == [6, 7, 8, 4, 5]);
     /// ```
     #[experimental = "uncertain about this API approach"]
-    fn move_from(&mut self, src: Vec<Self::Item>, start: uint, end: uint) -> uint;
+    fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint;
 
     /// Returns a subslice spanning the interval [`start`, `end`).
     ///
@@ -174,7 +174,7 @@ pub trait SliceExt for Sized? {
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice(&self, start: uint, end: uint) -> &[Self::Item];
+    fn slice(&self, start: uint, end: uint) -> &[T];
 
     /// Returns a subslice from `start` to the end of the slice.
     ///
@@ -182,7 +182,7 @@ pub trait SliceExt for Sized? {
     ///
     /// Slicing from `self.len()` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_from(&self, start: uint) -> &[Self::Item];
+    fn slice_from(&self, start: uint) -> &[T];
 
     /// Returns a subslice from the start of the slice to `end`.
     ///
@@ -190,7 +190,7 @@ pub trait SliceExt for Sized? {
     ///
     /// Slicing to `0` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_to(&self, end: uint) -> &[Self::Item];
+    fn slice_to(&self, end: uint) -> &[T];
 
     /// Divides one slice into two at an index.
     ///
@@ -200,32 +200,32 @@ pub trait SliceExt for Sized? {
     ///
     /// Panics if `mid > len`.
     #[stable]
-    fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]);
+    fn split_at(&self, mid: uint) -> (&[T], &[T]);
 
     /// Returns an iterator over the slice
     #[stable]
-    fn iter(&self) -> Iter<Self::Item>;
+    fn iter(&self) -> Iter<T>;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`.  The matched element is not contained in the subslices.
     #[stable]
-    fn split<F>(&self, pred: F) -> Split<Self::Item, F>
-                where F: FnMut(&Self::Item) -> bool;
+    fn split<F>(&self, pred: F) -> Split<T, F>
+                where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
     #[stable]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<Self::Item, F>
-                 where F: FnMut(&Self::Item) -> bool;
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
+                 where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     #[stable]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
-                  where F: FnMut(&Self::Item) -> bool;
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
+                  where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over all contiguous windows of length
     /// `size`. The windows overlap. If the slice is shorter than
@@ -241,13 +241,13 @@ fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
     /// `[3,4]`):
     ///
     /// ```rust
-    /// let v = &[1i, 2, 3, 4];
+    /// let v = &[1, 2, 3, 4];
     /// for win in v.windows(2) {
     ///     println!("{}", win);
     /// }
     /// ```
     #[stable]
-    fn windows(&self, size: uint) -> Windows<Self::Item>;
+    fn windows(&self, size: uint) -> Windows<T>;
 
     /// Returns an iterator over `size` elements of the slice at a
     /// time. The chunks do not overlap. If `size` does not divide the
@@ -264,39 +264,49 @@ fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
     /// `[3,4]`, `[5]`):
     ///
     /// ```rust
-    /// let v = &[1i, 2, 3, 4, 5];
+    /// let v = &[1, 2, 3, 4, 5];
     /// for win in v.chunks(2) {
     ///     println!("{}", win);
     /// }
     /// ```
     #[stable]
-    fn chunks(&self, size: uint) -> Chunks<Self::Item>;
+    fn chunks(&self, size: uint) -> Chunks<T>;
 
     /// Returns the element of a slice at the given index, or `None` if the
     /// index is out of bounds.
     #[stable]
-    fn get(&self, index: uint) -> Option<&Self::Item>;
+    fn get(&self, index: uint) -> Option<&T>;
 
     /// Returns the first element of a slice, or `None` if it is empty.
     #[stable]
-    fn first(&self) -> Option<&Self::Item>;
+    fn first(&self) -> Option<&T>;
+
+    /// Deprecated: renamed to `first`.
+    #[deprecated = "renamed to `first`"]
+    fn head(&self) -> Option<&T> { self.first() }
 
     /// Returns all but the first element of a slice.
     #[experimental = "likely to be renamed"]
-    fn tail(&self) -> &[Self::Item];
+    fn tail(&self) -> &[T];
 
     /// Returns all but the last element of a slice.
     #[experimental = "likely to be renamed"]
-    fn init(&self) -> &[Self::Item];
+    fn init(&self) -> &[T];
 
     /// Returns the last element of a slice, or `None` if it is empty.
     #[stable]
-    fn last(&self) -> Option<&Self::Item>;
+    fn last(&self) -> Option<&T>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
     #[stable]
-    unsafe fn get_unchecked(&self, index: uint) -> &Self::Item;
+    unsafe fn get_unchecked(&self, index: uint) -> &T;
+
+    /// Deprecated: renamed to `get_unchecked`.
+    #[deprecated = "renamed to get_unchecked"]
+    unsafe fn unsafe_get(&self, index: uint) -> &T {
+        self.get_unchecked(index)
+    }
 
     /// Returns an unsafe pointer to the slice's buffer
     ///
@@ -306,7 +316,7 @@ fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
     #[stable]
-    fn as_ptr(&self) -> *const Self::Item;
+    fn as_ptr(&self) -> *const T;
 
     /// Binary search a sorted slice with a comparator function.
     ///
@@ -327,7 +337,7 @@ fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
     /// found; the fourth could match any position in `[1,4]`.
     ///
     /// ```rust
-    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
     /// let s = s.as_slice();
     ///
     /// let seek = 13;
@@ -342,14 +352,14 @@ fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
     /// ```
     #[stable]
     fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
-        F: FnMut(&Self::Item) -> Ordering;
+        F: FnMut(&T) -> Ordering;
 
     /// Return the number of elements in the slice
     ///
     /// # Example
     ///
     /// ```
-    /// let a = [1i, 2, 3];
+    /// let a = [1, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
     #[stable]
@@ -360,7 +370,7 @@ fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
     /// # Example
     ///
     /// ```
-    /// let a = [1i, 2, 3];
+    /// let a = [1, 2, 3];
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
@@ -369,12 +379,12 @@ fn is_empty(&self) -> bool { self.len() == 0 }
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
     #[stable]
-    fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>;
+    fn get_mut(&mut self, index: uint) -> Option<&mut T>;
 
     /// Work with `self` as a mut slice.
     /// Primarily intended for getting a &mut [T] from a [T; N].
     #[stable]
-    fn as_mut_slice(&mut self) -> &mut [Self::Item];
+    fn as_mut_slice(&mut self) -> &mut [T];
 
     /// Returns a mutable subslice spanning the interval [`start`, `end`).
     ///
@@ -383,7 +393,7 @@ fn is_empty(&self) -> bool { self.len() == 0 }
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item];
+    fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T];
 
     /// Returns a mutable subslice from `start` to the end of the slice.
     ///
@@ -391,7 +401,7 @@ fn is_empty(&self) -> bool { self.len() == 0 }
     ///
     /// Slicing from `self.len()` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item];
+    fn slice_from_mut(&mut self, start: uint) -> &mut [T];
 
     /// Returns a mutable subslice from the start of the slice to `end`.
     ///
@@ -399,48 +409,54 @@ fn is_empty(&self) -> bool { self.len() == 0 }
     ///
     /// Slicing to `0` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item];
+    fn slice_to_mut(&mut self, end: uint) -> &mut [T];
 
     /// Returns an iterator that allows modifying each value
     #[stable]
-    fn iter_mut(&mut self) -> IterMut<Self::Item>;
+    fn iter_mut(&mut self) -> IterMut<T>;
 
     /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
     #[stable]
-    fn first_mut(&mut self) -> Option<&mut Self::Item>;
+    fn first_mut(&mut self) -> Option<&mut T>;
+
+    /// Depreated: renamed to `first_mut`.
+    #[deprecated = "renamed to first_mut"]
+    fn head_mut(&mut self) -> Option<&mut T> {
+        self.first_mut()
+    }
 
     /// Returns all but the first element of a mutable slice
     #[experimental = "likely to be renamed or removed"]
-    fn tail_mut(&mut self) -> &mut [Self::Item];
+    fn tail_mut(&mut self) -> &mut [T];
 
     /// Returns all but the last element of a mutable slice
     #[experimental = "likely to be renamed or removed"]
-    fn init_mut(&mut self) -> &mut [Self::Item];
+    fn init_mut(&mut self) -> &mut [T];
 
     /// Returns a mutable pointer to the last item in the slice.
     #[stable]
-    fn last_mut(&mut self) -> Option<&mut Self::Item>;
+    fn last_mut(&mut self) -> Option<&mut T>;
 
     /// Returns an iterator over mutable subslices separated by elements that
     /// match `pred`.  The matched element is not contained in the subslices.
     #[stable]
-    fn split_mut<F>(&mut self, pred: F) -> SplitMut<Self::Item, F>
-                    where F: FnMut(&Self::Item) -> bool;
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
+                    where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
     #[stable]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<Self::Item, F>
-                     where F: FnMut(&Self::Item) -> bool;
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
+                     where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     #[stable]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
-                      where F: FnMut(&Self::Item) -> bool;
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
+                      where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
     /// The chunks are mutable and do not overlap. If `chunk_size` does
@@ -451,7 +467,7 @@ fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
     ///
     /// Panics if `chunk_size` is 0.
     #[stable]
-    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<Self::Item>;
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>;
 
     /// Swaps two elements in a slice.
     ///
@@ -487,45 +503,51 @@ fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
     /// # Example
     ///
     /// ```rust
-    /// let mut v = [1i, 2, 3, 4, 5, 6];
+    /// let mut v = [1, 2, 3, 4, 5, 6];
     ///
     /// // scoped to restrict the lifetime of the borrows
     /// {
     ///    let (left, right) = v.split_at_mut(0);
     ///    assert!(left == []);
-    ///    assert!(right == [1i, 2, 3, 4, 5, 6]);
+    ///    assert!(right == [1, 2, 3, 4, 5, 6]);
     /// }
     ///
     /// {
     ///     let (left, right) = v.split_at_mut(2);
-    ///     assert!(left == [1i, 2]);
-    ///     assert!(right == [3i, 4, 5, 6]);
+    ///     assert!(left == [1, 2]);
+    ///     assert!(right == [3, 4, 5, 6]);
     /// }
     ///
     /// {
     ///     let (left, right) = v.split_at_mut(6);
-    ///     assert!(left == [1i, 2, 3, 4, 5, 6]);
+    ///     assert!(left == [1, 2, 3, 4, 5, 6]);
     ///     assert!(right == []);
     /// }
     /// ```
     #[stable]
-    fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]);
+    fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]);
 
     /// Reverse the order of elements in a slice, in place.
     ///
     /// # Example
     ///
     /// ```rust
-    /// let mut v = [1i, 2, 3];
+    /// let mut v = [1, 2, 3];
     /// v.reverse();
-    /// assert!(v == [3i, 2, 1]);
+    /// assert!(v == [3, 2, 1]);
     /// ```
     #[stable]
     fn reverse(&mut self);
 
     /// Returns an unsafe mutable pointer to the element in index
     #[stable]
-    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item;
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T;
+
+    /// Deprecated: renamed to `get_unchecked_mut`.
+    #[deprecated = "renamed to get_unchecked_mut"]
+    unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T {
+        self.get_unchecked_mut(index)
+    }
 
     /// Return an unsafe mutable pointer to the slice's buffer.
     ///
@@ -536,173 +558,11 @@ fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
     /// would also make any pointers to it invalid.
     #[inline]
     #[stable]
-    fn as_mut_ptr(&mut self) -> *mut Self::Item;
-
-    /// Copies `self` into a new `Vec`.
-    #[stable]
-    fn to_vec(&self) -> Vec<Self::Item> where Self::Item: Clone;
-
-    /// Creates an iterator that yields every possible permutation of the
-    /// vector in succession.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// for p in perms {
-    ///   println!("{}", p);
-    /// }
-    /// ```
-    ///
-    /// Iterating through permutations one by one.
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
-    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
-    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
-    /// ```
-    #[unstable]
-    fn permutations(&self) -> Permutations<Self::Item> where Self::Item: Clone;
-
-    /// 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
-    ///
-    /// ```rust
-    /// let mut dst = [0i, 0, 0];
-    /// let src = [1i, 2];
-    ///
-    /// assert!(dst.clone_from_slice(&src) == 2);
-    /// assert!(dst == [1, 2, 0]);
-    ///
-    /// let src2 = [3i, 4, 5, 6];
-    /// assert!(dst.clone_from_slice(&src2) == 3);
-    /// assert!(dst == [3i, 4, 5]);
-    /// ```
-    #[experimental]
-    fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone;
-
-    /// Sorts the slice, in place.
-    ///
-    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let mut v = [-5i, 4, 1, -3, 2];
-    ///
-    /// v.sort();
-    /// assert!(v == [-5i, -3, 1, 2, 4]);
-    /// ```
-    #[stable]
-    fn sort(&mut self) where Self::Item: Ord;
-
-    /// Binary search a sorted slice for a given element.
-    ///
-    /// If the value is found then `Ok` is returned, containing the
-    /// index of the matching element; if the value is not 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 = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
-    ///
-    /// assert_eq!(s.binary_search(&13),  Ok(9));
-    /// assert_eq!(s.binary_search(&4),   Err(7));
-    /// assert_eq!(s.binary_search(&100), Err(13));
-    /// let r = s.binary_search(&1);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable]
-    fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord;
-
-    /// Deprecated: use `binary_search` instead.
-    #[deprecated = "use binary_search instead"]
-    fn binary_search_elem(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord {
-        self.binary_search(x)
-    }
-
-    /// Mutates the slice to the next lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// last-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [0i, 1, 2];
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [1i, 0, 2];
-    /// assert!(v == b);
-    /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
-    fn next_permutation(&mut self) -> bool where Self::Item: Ord;
-
-    /// Mutates the slice to the previous lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// first-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [1i, 0, 2];
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 1, 2];
-    /// assert!(v == b);
-    /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
-    fn prev_permutation(&mut self) -> bool where Self::Item: Ord;
-
-    /// Find the first index containing a matching value.
-    #[experimental]
-    fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
-
-    /// Find the last index containing a matching value.
-    #[experimental]
-    fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
-
-    /// Return true if the slice contains an element with the given value.
-    #[stable]
-    fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
-
-    /// Returns true if `needle` is a prefix of the slice.
-    #[stable]
-    fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
-
-    /// Returns true if `needle` is a suffix of the slice.
-    #[stable]
-    fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
-
-    /// Convert `self` into a vector without clones or allocation.
-    #[experimental]
-    fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
+    fn as_mut_ptr(&mut self) -> *mut T;
 }
 
 #[unstable = "trait is unstable"]
-impl<T> SliceExt for [T] {
-    type Item = T;
-
+impl<T> SliceExt<T> for [T] {
     #[inline]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
         merge_sort(self, compare)
@@ -917,76 +777,229 @@ unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
     fn as_mut_ptr(&mut self) -> *mut T {
         core_slice::SliceExt::as_mut_ptr(self)
     }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Extension traits for slices over specifc kinds of data
+////////////////////////////////////////////////////////////////////////////////
+
+/// Extension methods for boxed slices.
+#[experimental = "likely to merge into SliceExt if it survives"]
+pub trait BoxedSliceExt<T> {
+    /// Convert `self` into a vector without clones or allocation.
+    #[experimental]
+    fn into_vec(self) -> Vec<T>;
+}
+
+#[experimental = "trait is experimental"]
+impl<T> BoxedSliceExt<T> for Box<[T]> {
+    fn into_vec(mut self) -> Vec<T> {
+        unsafe {
+            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
+            mem::forget(self);
+            xs
+        }
+    }
+}
+
+/// Allocating extension methods for slices containing `Clone` elements.
+#[unstable = "likely to be merged into SliceExt"]
+pub trait CloneSliceExt<T> for Sized? {
+    /// Copies `self` into a new `Vec`.
+    #[stable]
+    fn to_vec(&self) -> Vec<T>;
+
+    /// Deprecated: use `iter().cloned().partition(f)` instead.
+    #[deprecated = "use iter().cloned().partition(f) instead"]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
 
+    /// Creates an iterator that yields every possible permutation of the
+    /// vector in succession.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let v = [1, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// for p in perms {
+    ///   println!("{}", p);
+    /// }
+    /// ```
+    ///
+    /// Iterating through permutations one by one.
+    ///
+    /// ```rust
+    /// 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());
+    /// ```
+    #[unstable]
+    fn permutations(&self) -> Permutations<T>;
+
+    /// 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
+    ///
+    /// ```rust
+    /// let mut dst = [0, 0, 0];
+    /// let src = [1, 2];
+    ///
+    /// 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]);
+    /// ```
+    #[experimental]
+    fn clone_from_slice(&mut self, &[T]) -> uint;
+}
+
+
+#[unstable = "trait is unstable"]
+impl<T: Clone> CloneSliceExt<T> for [T] {
     /// Returns a copy of `v`.
     #[inline]
-    fn to_vec(&self) -> Vec<T> where T: Clone {
+    fn to_vec(&self) -> Vec<T> {
         let mut vector = Vec::with_capacity(self.len());
         vector.push_all(self);
         vector
     }
 
+
+    #[inline]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+        self.iter().cloned().partition(f)
+    }
+
     /// Returns an iterator over all permutations of a vector.
-    fn permutations(&self) -> Permutations<T> where T: Clone {
+    fn permutations(&self) -> Permutations<T> {
         Permutations{
             swaps: ElementSwaps::new(self.len()),
             v: self.to_vec(),
         }
     }
 
-    fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
-        core_slice::SliceExt::clone_from_slice(self, src)
-    }
-
-    #[inline]
-    fn sort(&mut self) where T: Ord {
-        self.sort_by(|a, b| a.cmp(b))
+    fn clone_from_slice(&mut self, src: &[T]) -> uint {
+        core_slice::CloneSliceExt::clone_from_slice(self, src)
     }
+}
 
-    fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
-        core_slice::SliceExt::binary_search(self, x)
-    }
+/// Allocating extension methods for slices on Ord values.
+#[unstable = "likely to merge with SliceExt"]
+pub trait OrdSliceExt<T> for Sized? {
+    /// 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]
+    fn sort(&mut self);
 
-    fn next_permutation(&mut self) -> bool where T: Ord {
-        core_slice::SliceExt::next_permutation(self)
-    }
+    /// Binary search a sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not 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 s = s.as_slice();
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable]
+    fn binary_search(&self, x: &T) -> Result<uint, uint>;
 
-    fn prev_permutation(&mut self) -> bool where T: Ord {
-        core_slice::SliceExt::prev_permutation(self)
+    /// Deprecated: use `binary_search` instead.
+    #[deprecated = "use binary_search instead"]
+    fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
+        self.binary_search(x)
     }
 
-    fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
-        core_slice::SliceExt::position_elem(self, t)
-    }
+    /// Mutates the slice to the next lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// last-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [0, 1, 2];
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [0, 2, 1];
+    /// assert!(v == b);
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [1, 0, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn next_permutation(&mut self) -> bool;
 
-    fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
-        core_slice::SliceExt::rposition_elem(self, t)
-    }
+    /// Mutates the slice to the previous lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// first-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [1, 0, 2];
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0, 2, 1];
+    /// assert!(v == b);
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0, 1, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn prev_permutation(&mut self) -> bool;
+}
 
-    fn contains(&self, x: &T) -> bool where T: PartialEq {
-        core_slice::SliceExt::contains(self, x)
+#[unstable = "trait is unstable"]
+impl<T: Ord> OrdSliceExt<T> for [T] {
+    #[inline]
+    fn sort(&mut self) {
+        self.sort_by(|a, b| a.cmp(b))
     }
 
-    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        core_slice::SliceExt::starts_with(self, needle)
+    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+        core_slice::OrdSliceExt::binary_search(self, x)
     }
 
-    fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        core_slice::SliceExt::ends_with(self, needle)
+    fn next_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::next_permutation(self)
     }
 
-    fn into_vec(mut self: Box<Self>) -> Vec<T> {
-        unsafe {
-            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
-            mem::forget(self);
-            xs
-        }
+    fn prev_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::prev_permutation(self)
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Extension traits for slices over specifc kinds of data
-////////////////////////////////////////////////////////////////////////////////
 #[unstable = "U should be an associated type"]
 /// An extension trait for concatenating slices
 pub trait SliceConcatExt<Sized? T, U> for Sized? {
@@ -994,10 +1007,20 @@ pub trait SliceConcatExt<Sized? T, U> for Sized? {
     #[stable]
     fn concat(&self) -> U;
 
+    #[deprecated = "renamed to concat"]
+    fn concat_vec(&self) -> U {
+        self.concat()
+    }
+
     /// Flattens a slice of `T` into a single value `U`, placing a
     /// given seperator between each.
     #[stable]
     fn connect(&self, sep: &T) -> U;
+
+    #[deprecated = "renamed to connect"]
+    fn connect_vec(&self, sep: &T) -> U {
+        self.connect(sep)
+    }
 }
 
 impl<T: Clone, V: AsSlice<T>> SliceConcatExt<T, Vec<T>> for [V] {
@@ -1033,7 +1056,7 @@ fn connect(&self, sep: &T) -> Vec<T> {
 /// The last generated swap is always (0, 1), and it returns the
 /// sequence to its initial order.
 #[experimental]
-#[derive(Clone)]
+#[deriving(Clone)]
 pub struct ElementSwaps {
     sdir: Vec<SizeDirection>,
     /// If `true`, emit the last swap that returns the sequence to initial
@@ -1080,19 +1103,17 @@ fn to_owned(&self) -> Vec<T> { self.to_vec() }
 // Iterators
 ////////////////////////////////////////////////////////////////////////////////
 
-#[derive(Copy, Clone)]
+#[deriving(Copy, Clone)]
 enum Direction { Pos, Neg }
 
 /// An `Index` and `Direction` together.
-#[derive(Copy, Clone)]
+#[deriving(Copy, Clone)]
 struct SizeDirection {
     size: uint,
     dir: Direction,
 }
 
-impl Iterator for ElementSwaps {
-    type Item = (uint, uint);
-
+impl Iterator<(uint, uint)> for ElementSwaps {
     #[inline]
     fn next(&mut self) -> Option<(uint, uint)> {
         fn new_pos(i: uint, s: Direction) -> uint {
@@ -1159,9 +1180,7 @@ pub struct Permutations<T> {
 }
 
 #[unstable = "trait is unstable"]
-impl<T: Clone> Iterator for Permutations<T> {
-    type Item = Vec<T>;
-
+impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
     #[inline]
     fn next(&mut self) -> Option<Vec<T>> {
         match self.swaps.next() {
@@ -1388,12 +1407,21 @@ unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
     }
 }
 
+/// Deprecated, unsafe operations
+#[deprecated]
+pub mod raw {
+    pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
+    pub use core::slice::raw::{shift_ptr, pop_ptr};
+}
+
 #[cfg(test)]
 mod tests {
+    use std::boxed::Box;
     use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal};
-    use prelude::{SliceExt, Iterator, IteratorExt};
-    use prelude::AsSlice;
+    use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt};
+    use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice};
     use prelude::{RandomAccessIterator, Ord, SliceConcatExt};
+    use core::cell::Cell;
     use core::default::Default;
     use core::mem;
     use std::rand::{Rng, thread_rng};
@@ -1407,7 +1435,7 @@ fn is_odd(n: &uint) -> bool { *n % 2u == 1u }
     #[test]
     fn test_from_fn() {
         // Test on-stack from_fn.
-        let mut v = range(0, 3).map(square).collect::<Vec<_>>();
+        let mut v = Vec::from_fn(3u, square);
         {
             let v = v.as_slice();
             assert_eq!(v.len(), 3u);
@@ -1417,7 +1445,7 @@ fn test_from_fn() {
         }
 
         // Test on-heap from_fn.
-        v = range(0, 5).map(square).collect::<Vec<_>>();
+        v = Vec::from_fn(5u, square);
         {
             let v = v.as_slice();
             assert_eq!(v.len(), 5u);
@@ -1432,7 +1460,7 @@ fn test_from_fn() {
     #[test]
     fn test_from_elem() {
         // Test on-stack from_elem.
-        let mut v = vec![10u, 10u];
+        let mut v = Vec::from_elem(2u, 10u);
         {
             let v = v.as_slice();
             assert_eq!(v.len(), 2u);
@@ -1441,7 +1469,7 @@ fn test_from_elem() {
         }
 
         // Test on-heap from_elem.
-        v = vec![20u, 20u, 20u, 20u, 20u, 20u];
+        v = Vec::from_elem(6u, 20u);
         {
             let v = v.as_slice();
             assert_eq!(v[0], 20u);
@@ -1483,23 +1511,23 @@ fn test_get() {
     }
 
     #[test]
-    fn test_first() {
+    fn test_head() {
         let mut a = vec![];
-        assert_eq!(a.as_slice().first(), None);
+        assert_eq!(a.as_slice().head(), None);
         a = vec![11i];
-        assert_eq!(a.as_slice().first().unwrap(), &11);
+        assert_eq!(a.as_slice().head().unwrap(), &11);
         a = vec![11i, 12];
-        assert_eq!(a.as_slice().first().unwrap(), &11);
+        assert_eq!(a.as_slice().head().unwrap(), &11);
     }
 
     #[test]
-    fn test_first_mut() {
+    fn test_head_mut() {
         let mut a = vec![];
-        assert_eq!(a.first_mut(), None);
+        assert_eq!(a.head_mut(), None);
         a = vec![11i];
-        assert_eq!(*a.first_mut().unwrap(), 11);
+        assert_eq!(*a.head_mut().unwrap(), 11);
         a = vec![11i, 12];
-        assert_eq!(*a.first_mut().unwrap(), 11);
+        assert_eq!(*a.head_mut().unwrap(), 11);
     }
 
     #[test]
@@ -1703,6 +1731,42 @@ fn test_push() {
         assert_eq!(v.as_slice()[1], 2);
     }
 
+    #[test]
+    fn test_grow() {
+        // Test on-stack grow().
+        let mut v = vec![];
+        v.grow(2u, 1i);
+        {
+            let v = v.as_slice();
+            assert_eq!(v.len(), 2u);
+            assert_eq!(v[0], 1);
+            assert_eq!(v[1], 1);
+        }
+
+        // Test on-heap grow().
+        v.grow(3u, 2i);
+        {
+            let v = v.as_slice();
+            assert_eq!(v.len(), 5u);
+            assert_eq!(v[0], 1);
+            assert_eq!(v[1], 1);
+            assert_eq!(v[2], 2);
+            assert_eq!(v[3], 2);
+            assert_eq!(v[4], 2);
+        }
+    }
+
+    #[test]
+    fn test_grow_fn() {
+        let mut v = vec![];
+        v.grow_fn(3u, square);
+        let v = v.as_slice();
+        assert_eq!(v.len(), 3u);
+        assert_eq!(v[0], 0u);
+        assert_eq!(v[1], 1u);
+        assert_eq!(v[2], 4u);
+    }
+
     #[test]
     fn test_truncate() {
         let mut v = vec![box 6i,box 5,box 4];
@@ -2035,6 +2099,22 @@ fn test_sort_stability() {
         }
     }
 
+    #[test]
+    fn test_partition() {
+        assert_eq!((vec![]).partition(|x: &int| *x < 3), (vec![], vec![]));
+        assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+        assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+        assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+    }
+
+    #[test]
+    fn test_partitioned() {
+        assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![]));
+        assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+        assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+        assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+    }
+
     #[test]
     fn test_concat() {
         let v: [Vec<int>; 0] = [];
@@ -2052,14 +2132,14 @@ fn test_concat() {
     #[test]
     fn test_connect() {
         let v: [Vec<int>; 0] = [];
-        assert_eq!(v.connect(&0), vec![]);
-        assert_eq!([vec![1i], vec![2i, 3]].connect(&0), vec![1, 0, 2, 3]);
-        assert_eq!([vec![1i], vec![2i], vec![3i]].connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect_vec(&0), vec![]);
+        assert_eq!([vec![1i], vec![2i, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+        assert_eq!([vec![1i], vec![2i], vec![3i]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
 
         let v: [&[int]; 2] = [&[1], &[2, 3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
+        assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]);
         let v: [&[int]; 3] = [&[1], &[2], &[3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]);
     }
 
     #[test]
@@ -2132,6 +2212,55 @@ fn test_slice_2() {
         assert_eq!(v[1], 3);
     }
 
+
+    #[test]
+    #[should_fail]
+    fn test_from_fn_fail() {
+        Vec::from_fn(100, |v| {
+            if v == 50 { panic!() }
+            box 0i
+        });
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_from_elem_fail() {
+
+        struct S {
+            f: Cell<int>,
+            boxes: (Box<int>, Rc<int>)
+        }
+
+        impl Clone for S {
+            fn clone(&self) -> S {
+                self.f.set(self.f.get() + 1);
+                if self.f.get() == 10 { panic!() }
+                S {
+                    f: self.f.clone(),
+                    boxes: self.boxes.clone(),
+                }
+            }
+        }
+
+        let s = S {
+            f: Cell::new(0),
+            boxes: (box 0, Rc::new(0)),
+        };
+        let _ = Vec::from_elem(100, s);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_grow_fn_fail() {
+        let mut v = vec![];
+        v.grow_fn(100, |i| {
+            if i == 50 {
+                panic!()
+            }
+            (box 0i, Rc::new(0i))
+        })
+    }
+
     #[test]
     #[should_fail]
     fn test_permute_fail() {
@@ -2549,7 +2678,7 @@ fn test_mut_split_at() {
         assert!(values == [2, 3, 5, 6, 7]);
     }
 
-    #[derive(Clone, PartialEq)]
+    #[deriving(Clone, PartialEq)]
     struct Foo;
 
     #[test]
@@ -2720,7 +2849,6 @@ mod bench {
     use prelude::*;
     use core::mem;
     use core::ptr;
-    use core::iter::repeat;
     use std::rand::{weak_rng, Rng};
     use test::{Bencher, black_box};
 
@@ -2728,7 +2856,7 @@ mod bench {
     fn iterator(b: &mut Bencher) {
         // peculiar numbers to stop LLVM from optimising the summation
         // out.
-        let v = range(0u, 100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect::<Vec<_>>();
+        let v = Vec::from_fn(100, |i| i ^ (i << 1) ^ (i >> 1));
 
         b.iter(|| {
             let mut sum = 0;
@@ -2742,7 +2870,7 @@ fn iterator(b: &mut Bencher) {
 
     #[bench]
     fn mut_iterator(b: &mut Bencher) {
-        let mut v = repeat(0i).take(100).collect::<Vec<_>>();
+        let mut v = Vec::from_elem(100, 0i);
 
         b.iter(|| {
             let mut i = 0i;
@@ -2756,7 +2884,7 @@ fn mut_iterator(b: &mut Bencher) {
     #[bench]
     fn concat(b: &mut Bencher) {
         let xss: Vec<Vec<uint>> =
-            range(0, 100u).map(|i| range(0, i).collect()).collect();
+            Vec::from_fn(100, |i| range(0u, i).collect());
         b.iter(|| {
             xss.as_slice().concat();
         });
@@ -2765,9 +2893,9 @@ fn concat(b: &mut Bencher) {
     #[bench]
     fn connect(b: &mut Bencher) {
         let xss: Vec<Vec<uint>> =
-            range(0, 100u).map(|i| range(0, i).collect()).collect();
+            Vec::from_fn(100, |i| range(0u, i).collect());
         b.iter(|| {
-            xss.as_slice().connect(&0)
+            xss.as_slice().connect_vec(&0)
         });
     }
 
@@ -2782,7 +2910,7 @@ fn push(b: &mut Bencher) {
 
     #[bench]
     fn starts_with_same_vector(b: &mut Bencher) {
-        let vec: Vec<uint> = range(0, 100).collect();
+        let vec: Vec<uint> = Vec::from_fn(100, |i| i);
         b.iter(|| {
             vec.as_slice().starts_with(vec.as_slice())
         })
@@ -2798,8 +2926,8 @@ fn starts_with_single_element(b: &mut Bencher) {
 
     #[bench]
     fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
-        let vec: Vec<uint> = range(0, 100).collect();
-        let mut match_vec: Vec<uint> = range(0, 99).collect();
+        let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+        let mut match_vec: Vec<uint> = Vec::from_fn(99, |i| i);
         match_vec.push(0);
         b.iter(|| {
             vec.as_slice().starts_with(match_vec.as_slice())
@@ -2808,7 +2936,7 @@ fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
 
     #[bench]
     fn ends_with_same_vector(b: &mut Bencher) {
-        let vec: Vec<uint> = range(0, 100).collect();
+        let vec: Vec<uint> = Vec::from_fn(100, |i| i);
         b.iter(|| {
             vec.as_slice().ends_with(vec.as_slice())
         })
@@ -2824,8 +2952,8 @@ fn ends_with_single_element(b: &mut Bencher) {
 
     #[bench]
     fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
-        let vec: Vec<uint> = range(0, 100).collect();
-        let mut match_vec: Vec<uint> = range(0, 100).collect();
+        let vec: Vec<uint> = Vec::from_fn(100, |i| i);
+        let mut match_vec: Vec<uint> = Vec::from_fn(100, |i| i);
         match_vec.as_mut_slice()[0] = 200;
         b.iter(|| {
             vec.as_slice().starts_with(match_vec.as_slice())
@@ -2834,7 +2962,7 @@ fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
 
     #[bench]
     fn contains_last_element(b: &mut Bencher) {
-        let vec: Vec<uint> = range(0, 100).collect();
+        let vec: Vec<uint> = Vec::from_fn(100, |i| i);
         b.iter(|| {
             vec.contains(&99u)
         })
@@ -2843,7 +2971,7 @@ fn contains_last_element(b: &mut Bencher) {
     #[bench]
     fn zero_1kb_from_elem(b: &mut Bencher) {
         b.iter(|| {
-            repeat(0u8).take(1024).collect::<Vec<_>>()
+            Vec::from_elem(1024, 0u8)
         });
     }
 
@@ -2891,24 +3019,24 @@ fn zero_1kb_mut_iter(b: &mut Bencher) {
     fn random_inserts(b: &mut Bencher) {
         let mut rng = weak_rng();
         b.iter(|| {
-            let mut v = repeat((0u, 0u)).take(30).collect::<Vec<_>>();
-            for _ in range(0u, 100) {
-                let l = v.len();
-                v.insert(rng.gen::<uint>() % (l + 1),
-                         (1, 1));
-            }
-        })
+                let mut v = Vec::from_elem(30, (0u, 0u));
+                for _ in range(0u, 100) {
+                    let l = v.len();
+                    v.insert(rng.gen::<uint>() % (l + 1),
+                             (1, 1));
+                }
+            })
     }
     #[bench]
     fn random_removes(b: &mut Bencher) {
         let mut rng = weak_rng();
         b.iter(|| {
-            let mut v = repeat((0u, 0u)).take(130).collect::<Vec<_>>();
-            for _ in range(0u, 100) {
-                let l = v.len();
-                v.remove(rng.gen::<uint>() % l);
-            }
-        })
+                let mut v = Vec::from_elem(130, (0u, 0u));
+                for _ in range(0u, 100) {
+                    let l = v.len();
+                    v.remove(rng.gen::<uint>() % l);
+                }
+            })
     }
 
     #[bench]
@@ -2943,7 +3071,7 @@ fn sort_random_large(b: &mut Bencher) {
 
     #[bench]
     fn sort_sorted(b: &mut Bencher) {
-        let mut v = range(0u, 10000).collect::<Vec<_>>();
+        let mut v = Vec::from_fn(10000, |i| i);
         b.iter(|| {
             v.sort();
         });
@@ -2987,7 +3115,7 @@ fn sort_big_random_large(b: &mut Bencher) {
 
     #[bench]
     fn sort_big_sorted(b: &mut Bencher) {
-        let mut v = range(0, 10000u).map(|i| (i, i, i, i)).collect::<Vec<_>>();
+        let mut v = Vec::from_fn(10000u, |i| (i, i, i, i));
         b.iter(|| {
             v.sort();
         });
index ed6a957d2acfacbbecfe4de8238e9c85e92f25e3..ecf17820d2d8f72c58f44bc97d18c59a3b8666e9 100644 (file)
@@ -55,7 +55,7 @@
 use self::DecompositionType::*;
 
 use core::borrow::{BorrowFrom, ToOwned};
-use core::char::Char;
+use core::char::CharExt;
 use core::clone::Clone;
 use core::iter::AdditiveIterator;
 use core::iter::{range, Iterator, IteratorExt};
index e7451331908aed9e8fdf2fefb3ed60790b63e9dc..11e6c48cfdbad52209f5eaefbe1c34f22183baa3 100644 (file)
@@ -320,30 +320,6 @@ pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> Stri
         }
     }
 
-    /// Creates a `String` from a null-terminated `*const u8` buffer.
-    ///
-    /// This function is unsafe because we dereference memory until we find the
-    /// NUL character, which is not guaranteed to be present. Additionally, the
-    /// slice is not checked to see whether it contains valid UTF-8
-    #[unstable = "just renamed from `mod raw`"]
-    pub unsafe fn from_raw_buf(buf: *const u8) -> String {
-        String::from_str(str::from_c_str(buf as *const i8))
-    }
-
-    /// Creates a `String` from a `*const u8` buffer of the given length.
-    ///
-    /// This function is unsafe because it blindly assumes the validity of the
-    /// pointer `buf` for `len` bytes of memory. This function will copy the
-    /// memory from `buf` into a new allocation (owned by the returned
-    /// `String`).
-    ///
-    /// This function is also unsafe because it does not validate that the
-    /// buffer is valid UTF-8 encoded data.
-    #[unstable = "just renamed from `mod raw`"]
-    pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
-        String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
-    }
-
     /// Converts a vector of bytes to a new `String` without checking if
     /// it contains valid UTF-8. This is unsafe because it assumes that
     /// the UTF-8-ness of the vector has already been validated.
@@ -1126,24 +1102,6 @@ fn test_from_utf16_lossy() {
                    String::from_str("\u{FFFD}𐒋\u{FFFD}"));
     }
 
-    #[test]
-    fn test_from_buf_len() {
-        unsafe {
-            let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
-            assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
-        }
-    }
-
-    #[test]
-    fn test_from_buf() {
-        unsafe {
-            let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
-            let b = a.as_ptr();
-            let c = String::from_raw_buf(b);
-            assert_eq!(c, String::from_str("AAAAAAA"));
-        }
-    }
-
     #[test]
     fn test_push_bytes() {
         let mut s = String::from_str("ABC");
index b8f97799c971872b1245b2ed15e0110afa35d54d..e0ed8e27e991c168464e4baac23c680ce9bfb816 100644 (file)
 //! ```
 //! let ys: Vec<i32> = vec![];
 //!
-//! let zs = vec![1i32, 2, 3, 4, 5];
+//! let zs = vec![1, 2, 3, 4, 5];
 //! ```
 //!
 //! Push:
 //!
 //! ```
-//! let mut xs = vec![1i32, 2];
+//! let mut xs = vec![1, 2];
 //!
 //! xs.push(3);
 //! ```
@@ -39,7 +39,7 @@
 //! And pop:
 //!
 //! ```
-//! let mut xs = vec![1i32, 2];
+//! let mut xs = vec![1, 2];
 //!
 //! let two = xs.pop();
 //! ```
@@ -71,8 +71,8 @@
 ///
 /// ```
 /// let mut vec = Vec::new();
-/// vec.push(1i);
-/// vec.push(2i);
+/// vec.push(1);
+/// vec.push(2);
 ///
 /// assert_eq!(vec.len(), 2);
 /// assert_eq!(vec[0], 1);
@@ -80,7 +80,7 @@
 /// assert_eq!(vec.pop(), Some(2));
 /// assert_eq!(vec.len(), 1);
 ///
-/// vec[0] = 7i;
+/// vec[0] = 7;
 /// assert_eq!(vec[0], 7);
 ///
 /// vec.push_all(&[1, 2, 3]);
 /// for x in vec.iter() {
 ///     println!("{}", x);
 /// }
-/// assert_eq!(vec, vec![7i, 1, 2, 3]);
+/// assert_eq!(vec, vec![7, 1, 2, 3]);
 /// ```
 ///
 /// The `vec!` macro is provided to make initialization more convenient:
 ///
 /// ```
-/// let mut vec = vec![1i, 2i, 3i];
+/// let mut vec = vec![1, 2, 3];
 /// vec.push(4);
 /// assert_eq!(vec, vec![1, 2, 3, 4]);
 /// ```
 /// ```
 /// let mut stack = Vec::new();
 ///
-/// stack.push(1i);
-/// stack.push(2i);
-/// stack.push(3i);
+/// stack.push(1);
+/// stack.push(2);
+/// stack.push(3);
 ///
 /// loop {
 ///     let top = match stack.pop() {
@@ -218,7 +218,7 @@ pub fn with_capacity(capacity: uint) -> Vec<T> {
     /// use std::mem;
     ///
     /// fn main() {
-    ///     let mut v = vec![1i, 2, 3];
+    ///     let mut v = vec![1, 2, 3];
     ///
     ///     // Pull out the various important pieces of information about `v`
     ///     let p = v.as_mut_ptr();
@@ -237,7 +237,7 @@ pub fn with_capacity(capacity: uint) -> Vec<T> {
     ///
     ///         // Put everything back together into a Vec
     ///         let rebuilt = Vec::from_raw_parts(p, len, cap);
-    ///         assert_eq!(rebuilt, vec![4i, 5i, 6i]);
+    ///         assert_eq!(rebuilt, vec![4, 5, 6]);
     ///     }
     /// }
     /// ```
@@ -392,7 +392,7 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1i, 2, 3, 4];
+    /// let mut vec = vec![1, 2, 3, 4];
     /// vec.truncate(2);
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
@@ -416,7 +416,7 @@ pub fn truncate(&mut self, len: uint) {
     /// ```
     /// fn foo(slice: &mut [int]) {}
     ///
-    /// let mut vec = vec![1i, 2];
+    /// let mut vec = vec![1, 2];
     /// foo(vec.as_mut_slice());
     /// ```
     #[inline]
@@ -519,7 +519,7 @@ pub fn swap_remove(&mut self, index: uint) -> T {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1i, 2, 3];
+    /// let mut vec = vec![1, 2, 3];
     /// vec.insert(1, 4);
     /// assert_eq!(vec, vec![1, 4, 2, 3]);
     /// vec.insert(4, 5);
@@ -557,7 +557,7 @@ pub fn insert(&mut self, index: uint, element: T) {
     /// # Examples
     ///
     /// ```
-    /// let mut v = vec![1i, 2, 3];
+    /// let mut v = vec![1, 2, 3];
     /// assert_eq!(v.remove(1), 2);
     /// assert_eq!(v, vec![1, 3]);
     /// ```
@@ -591,7 +591,7 @@ pub fn remove(&mut self, index: uint) -> T {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1i, 2, 3, 4];
+    /// let mut vec = vec![1, 2, 3, 4];
     /// vec.retain(|&x| x%2 == 0);
     /// assert_eq!(vec, vec![2, 4]);
     /// ```
@@ -624,7 +624,7 @@ pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
     /// # Examples
     ///
     /// ```rust
-    /// let mut vec = vec!(1i, 2);
+    /// let mut vec = vec!(1, 2);
     /// vec.push(3);
     /// assert_eq!(vec, vec!(1, 2, 3));
     /// ```
@@ -662,7 +662,7 @@ pub fn push(&mut self, value: T) {
     /// # Examples
     ///
     /// ```rust
-    /// let mut vec = vec![1i, 2, 3];
+    /// let mut vec = vec![1, 2, 3];
     /// assert_eq!(vec.pop(), Some(3));
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
@@ -716,7 +716,7 @@ pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
     /// # Examples
     ///
     /// ```
-    /// let mut v = vec![1i, 2, 3];
+    /// let mut v = vec![1, 2, 3];
     ///
     /// v.clear();
     ///
@@ -733,7 +733,7 @@ pub fn clear(&mut self) {
     /// # Examples
     ///
     /// ```
-    /// let a = vec![1i, 2, 3];
+    /// let a = vec![1, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
     #[inline]
@@ -748,7 +748,7 @@ pub fn len(&self) -> uint { self.len }
     /// let mut v = Vec::new();
     /// assert!(v.is_empty());
     ///
-    /// v.push(1i);
+    /// v.push(1);
     /// assert!(!v.is_empty());
     /// ```
     #[stable]
@@ -965,7 +965,7 @@ impl<T: Clone> Vec<T> {
     /// vec.resize(3, "world");
     /// assert_eq!(vec, vec!["hello", "world", "world"]);
     ///
-    /// let mut vec = vec![1i, 2, 3, 4];
+    /// let mut vec = vec![1, 2, 3, 4];
     /// vec.resize(2, 0);
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
@@ -988,8 +988,8 @@ pub fn resize(&mut self, new_len: uint, value: T) {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1i];
-    /// vec.push_all(&[2i, 3, 4]);
+    /// let mut vec = vec![1];
+    /// vec.push_all(&[2, 3, 4]);
     /// assert_eq!(vec, vec![1, 2, 3, 4]);
     /// ```
     #[inline]
@@ -1021,11 +1021,11 @@ impl<T: PartialEq> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// let mut vec = vec![1i, 2, 2, 3, 2];
+    /// let mut vec = vec![1, 2, 2, 3, 2];
     ///
     /// vec.dedup();
     ///
-    /// assert_eq!(vec, vec![1i, 2, 3, 2]);
+    /// assert_eq!(vec, vec![1, 2, 3, 2]);
     /// ```
     #[stable]
     pub fn dedup(&mut self) {
@@ -1190,17 +1190,6 @@ fn hash(&self, state: &mut S) {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[experimental = "waiting on Index stability"]
-impl<T> Index<uint,T> for Vec<T> {
-    #[inline]
-    fn index<'a>(&'a self, index: &uint) -> &'a T {
-        &self.as_slice()[*index]
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[experimental = "waiting on Index stability"]
 impl<T> Index<uint> for Vec<T> {
     type Output = T;
@@ -1211,16 +1200,6 @@ fn index<'a>(&'a self, index: &uint) -> &'a T {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IndexMut<uint,T> for Vec<T> {
-    #[inline]
-    fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T {
-        &mut self.as_mut_slice()[*index]
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 impl<T> IndexMut<uint> for Vec<T> {
     type Output = T;
 
@@ -1399,7 +1378,7 @@ impl<T> AsSlice<T> for Vec<T> {
     /// ```
     /// fn foo(slice: &[int]) {}
     ///
-    /// let vec = vec![1i, 2];
+    /// let vec = vec![1, 2];
     /// foo(vec.as_slice());
     /// ```
     #[inline]
index ab6c6b7ca55bf55397f287d94d4b8faebe98f079..cc757b656238e978512314af45b1ee05bbe2437f 100644 (file)
@@ -517,17 +517,6 @@ fn extend<Iter: Iterator<Item=(uint, V)>>(&mut self, mut iter: Iter) {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<V> Index<uint, V> for VecMap<V> {
-    #[inline]
-    fn index<'a>(&'a self, i: &uint) -> &'a V {
-        self.get(i).expect("key not present")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 impl<V> Index<uint> for VecMap<V> {
     type Output = V;
 
@@ -537,17 +526,6 @@ fn index<'a>(&'a self, i: &uint) -> &'a V {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<V> IndexMut<uint, V> for VecMap<V> {
-    #[inline]
-    fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V {
-        self.get_mut(i).expect("key not present")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<V> IndexMut<uint> for VecMap<V> {
     type Output = V;
index 75feb4d88289e5faf1343176b6eb3c1f3b7327ee..33cb335d756451dfab847d2311ea7082bd71fb19 100644 (file)
@@ -35,7 +35,7 @@
 //!
 //! ```rust
 //! use std::fmt::Show;
-//! use std::any::{Any, AnyRefExt};
+//! use std::any::Any;
 //!
 //! // Logger function for any type that implements Show.
 //! fn log<T: Any+Show>(value: &T) {
@@ -102,24 +102,11 @@ fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
 // Implemented as three extension traits so that the methods can be generic.
 ///////////////////////////////////////////////////////////////////////////////
 
-/// Extension methods for a referenced `Any` trait object
-#[unstable = "this trait will not be necessary once DST lands, it will be a \
-              part of `impl Any`"]
-pub trait AnyRefExt<'a> {
+impl Any {
     /// Returns true if the boxed type is the same as `T`
     #[stable]
-    fn is<T: 'static>(self) -> bool;
-
-    /// Returns some reference to the boxed value if it is of type `T`, or
-    /// `None` if it isn't.
-    #[unstable = "naming conventions around acquiring references may change"]
-    fn downcast_ref<T: 'static>(self) -> Option<&'a T>;
-}
-
-#[stable]
-impl<'a> AnyRefExt<'a> for &'a Any {
     #[inline]
-    fn is<T: 'static>(self) -> bool {
+    pub fn is<T: 'static>(&self) -> bool {
         // Get TypeId of the type this function is instantiated with
         let t = TypeId::of::<T>();
 
@@ -130,8 +117,11 @@ fn is<T: 'static>(self) -> bool {
         t == boxed
     }
 
+    /// Returns some reference to the boxed value if it is of type `T`, or
+    /// `None` if it isn't.
+    #[unstable = "naming conventions around acquiring references may change"]
     #[inline]
-    fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
+    pub fn downcast_ref<'a, T: 'static>(&'a self) -> Option<&'a T> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
@@ -144,22 +134,12 @@ fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
             None
         }
     }
-}
 
-/// Extension methods for a mutable referenced `Any` trait object
-#[unstable = "this trait will not be necessary once DST lands, it will be a \
-              part of `impl Any`"]
-pub trait AnyMutRefExt<'a> {
     /// Returns some mutable reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
     #[unstable = "naming conventions around acquiring references may change"]
-    fn downcast_mut<T: 'static>(self) -> Option<&'a mut T>;
-}
-
-#[stable]
-impl<'a> AnyMutRefExt<'a> for &'a mut Any {
     #[inline]
-    fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> {
+    pub fn downcast_mut<'a, T: 'static>(&'a mut self) -> Option<&'a mut T> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
index 0ac0dc396cc1a304c566ca8fe41bb56c3696649c..ebc01ae14fc81a06044634a0ed712d9d55c637ba 100644 (file)
@@ -793,7 +793,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     /// use std::sync::atomic::AtomicPtr;
     ///
-    /// let ptr = &mut 5i;
+    /// let ptr = &mut 5;
     /// let atomic_ptr  = AtomicPtr::new(ptr);
     /// ```
     #[inline]
@@ -815,7 +815,7 @@ pub fn new(p: *mut T) -> AtomicPtr<T> {
     /// ```
     /// use std::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let ptr = &mut 5i;
+    /// let ptr = &mut 5;
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
     /// let value = some_ptr.load(Ordering::Relaxed);
@@ -837,10 +837,10 @@ pub fn load(&self, order: Ordering) -> *mut T {
     /// ```
     /// use std::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let ptr = &mut 5i;
+    /// let ptr = &mut 5;
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
-    /// let other_ptr = &mut 10i;
+    /// let other_ptr = &mut 10;
     ///
     /// some_ptr.store(other_ptr, Ordering::Relaxed);
     /// ```
@@ -863,10 +863,10 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
     /// ```
     /// use std::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let ptr = &mut 5i;
+    /// let ptr = &mut 5;
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
-    /// let other_ptr = &mut 10i;
+    /// let other_ptr = &mut 10;
     ///
     /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
     /// ```
@@ -888,11 +888,11 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
     /// ```
     /// use std::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let ptr = &mut 5i;
+    /// let ptr = &mut 5;
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
-    /// let other_ptr   = &mut 10i;
-    /// let another_ptr = &mut 10i;
+    /// let other_ptr   = &mut 10;
+    /// let another_ptr = &mut 10;
     ///
     /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
     /// ```
index 3423e76ea640832f3c1afc553b7456b0ab0d2987..291b7f2ece4455db05cd8777785240795501f5d2 100644 (file)
@@ -69,7 +69,7 @@
 
 /// Converts from `u32` to a `char`
 #[inline]
-#[unstable = "pending decisions about costructors for primitives"]
+#[stable]
 pub fn from_u32(i: u32) -> Option<char> {
     // catch out-of-bounds and surrogates
     if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
@@ -92,7 +92,7 @@ pub fn from_u32(i: u32) -> Option<char> {
 /// Panics if given an `radix` > 36.
 ///
 #[inline]
-#[unstable = "pending decisions about costructors for primitives"]
+#[unstable = "pending integer conventions"]
 pub fn from_digit(num: uint, radix: uint) -> Option<char> {
     if radix > 36 {
         panic!("from_digit: radix is too high (maximum 36)");
@@ -111,8 +111,8 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
 }
 
 /// Basic `char` manipulations.
-#[experimental = "trait organization may change"]
-pub trait Char {
+#[stable]
+pub trait CharExt {
     /// Checks if a `char` parses as a numeric digit in the given radix.
     ///
     /// Compared to `is_numeric()`, this function only recognizes the characters
@@ -126,7 +126,7 @@ pub trait Char {
     /// # Panics
     ///
     /// Panics if given a radix > 36.
-    #[unstable = "pending error conventions"]
+    #[unstable = "pending integer conventions"]
     fn is_digit(self, radix: uint) -> bool;
 
     /// Converts a character to the corresponding digit.
@@ -140,7 +140,7 @@ pub trait Char {
     /// # Panics
     ///
     /// Panics if given a radix outside the range [0..36].
-    #[unstable = "pending error conventions, trait organization"]
+    #[unstable = "pending integer conventions"]
     fn to_digit(self, radix: uint) -> Option<uint>;
 
     /// Returns an iterator that yields the hexadecimal Unicode escape
@@ -149,7 +149,7 @@ pub trait Char {
     /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
     /// where `NNNN` is the shortest hexadecimal representation of the code
     /// point.
-    #[unstable = "pending error conventions, trait organization"]
+    #[stable]
     fn escape_unicode(self) -> EscapeUnicode;
 
     /// Returns an iterator that yields the 'default' ASCII and
@@ -164,17 +164,17 @@ pub trait Char {
     ///   escaped.
     /// * Any other chars in the range [0x20,0x7e] are not escaped.
     /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
-    #[unstable = "pending error conventions, trait organization"]
+    #[stable]
     fn escape_default(self) -> EscapeDefault;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-8.
-    #[unstable = "pending trait organization"]
+    #[stable]
     fn len_utf8(self) -> uint;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-16.
-    #[unstable = "pending trait organization"]
+    #[stable]
     fn len_utf16(self) -> uint;
 
     /// Encodes this character as UTF-8 into the provided byte buffer,
@@ -182,29 +182,26 @@ pub trait Char {
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[unstable = "pending trait organization"]
-    fn encode_utf8(&self, dst: &mut [u8]) -> Option<uint>;
+    #[stable]
+    fn encode_utf8(self, dst: &mut [u8]) -> Option<uint>;
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer,
     /// and then returns the number of `u16`s written.
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[unstable = "pending trait organization"]
-    fn encode_utf16(&self, dst: &mut [u16]) -> Option<uint>;
+    #[stable]
+    fn encode_utf16(self, dst: &mut [u16]) -> Option<uint>;
 }
 
-#[experimental = "trait is experimental"]
-impl Char for char {
-    #[unstable = "pending trait organization"]
+#[stable]
+impl CharExt for char {
+    #[unstable = "pending integer conventions"]
     fn is_digit(self, radix: uint) -> bool {
-        match self.to_digit(radix) {
-            Some(_) => true,
-            None    => false,
-        }
+        self.to_digit(radix).is_some()
     }
 
-    #[unstable = "pending trait organization"]
+    #[unstable = "pending integer conventions"]
     fn to_digit(self, radix: uint) -> Option<uint> {
         if radix > 36 {
             panic!("to_digit: radix is too high (maximum 36)");
@@ -219,12 +216,12 @@ fn to_digit(self, radix: uint) -> Option<uint> {
         else { None }
     }
 
-    #[unstable = "pending error conventions, trait organization"]
+    #[stable]
     fn escape_unicode(self) -> EscapeUnicode {
         EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
     }
 
-    #[unstable = "pending error conventions, trait organization"]
+    #[stable]
     fn escape_default(self) -> EscapeDefault {
         let init_state = match self {
             '\t' => EscapeDefaultState::Backslash('t'),
@@ -240,7 +237,7 @@ fn escape_default(self) -> EscapeDefault {
     }
 
     #[inline]
-    #[unstable = "pending trait organization"]
+    #[stable]
     fn len_utf8(self) -> uint {
         let code = self as u32;
         match () {
@@ -252,17 +249,17 @@ fn len_utf8(self) -> uint {
     }
 
     #[inline]
-    #[unstable = "pending trait organization"]
+    #[stable]
     fn len_utf16(self) -> uint {
         let ch = self as u32;
         if (ch & 0xFFFF_u32) == ch { 1 } else { 2 }
     }
 
     #[inline]
-    #[unstable = "pending error conventions, trait organization"]
-    fn encode_utf8<'a>(&self, dst: &'a mut [u8]) -> Option<uint> {
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> {
         // Marked #[inline] to allow llvm optimizing it away
-        let code = *self as u32;
+        let code = self as u32;
         if code < MAX_ONE_B && dst.len() >= 1 {
             dst[0] = code as u8;
             Some(1)
@@ -287,10 +284,10 @@ fn encode_utf8<'a>(&self, dst: &'a mut [u8]) -> Option<uint> {
     }
 
     #[inline]
-    #[unstable = "pending error conventions, trait organization"]
-    fn encode_utf16(&self, dst: &mut [u16]) -> Option<uint> {
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf16(self, dst: &mut [u16]) -> Option<uint> {
         // Marked #[inline] to allow llvm optimizing it away
-        let mut ch = *self as u32;
+        let mut ch = self as u32;
         if (ch & 0xFFFF_u32) == ch  && dst.len() >= 1 {
             // The BMP falls through (assuming non-surrogate, as it should)
             dst[0] = ch as u16;
@@ -310,6 +307,7 @@ fn encode_utf16(&self, dst: &mut [u16]) -> Option<uint> {
 /// An iterator over the characters that represent a `char`, as escaped by
 /// Rust's unicode escaping rules.
 #[derive(Clone)]
+#[stable]
 pub struct EscapeUnicode {
     c: char,
     state: EscapeUnicodeState
@@ -325,6 +323,7 @@ enum EscapeUnicodeState {
     Done,
 }
 
+#[stable]
 impl Iterator for EscapeUnicode {
     type Item = char;
 
@@ -370,6 +369,7 @@ fn next(&mut self) -> Option<char> {
 /// An iterator over the characters that represent a `char`, escaped
 /// for maximum portability.
 #[derive(Clone)]
+#[stable]
 pub struct EscapeDefault {
     state: EscapeDefaultState
 }
@@ -382,6 +382,7 @@ enum EscapeDefaultState {
     Unicode(EscapeUnicode),
 }
 
+#[stable]
 impl Iterator for EscapeDefault {
     type Item = char;
 
index 9e62226220c0ee84970da6e8273d8774f8fd018f..f63242b4f859a451d9bddabff995532c9d1ec900 100644 (file)
@@ -15,7 +15,7 @@
 pub use self::SignFormat::*;
 
 use char;
-use char::Char;
+use char::CharExt;
 use fmt;
 use iter::{IteratorExt, range};
 use num::{cast, Float, ToPrimitive};
index f49f87ff329f06ec39730882c8ccba7efe5c8fc1..102836f8d3024831044766fe17c0ec2062f66af3 100644 (file)
@@ -388,7 +388,7 @@ pub fn pad_integral(&mut self,
                         prefix: &str,
                         buf: &str)
                         -> Result {
-        use char::Char;
+        use char::CharExt;
         use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad};
 
         let mut width = buf.len();
@@ -504,7 +504,7 @@ pub fn pad(&mut self, s: &str) -> Result {
     fn with_padding<F>(&mut self, padding: uint, default: rt::Alignment, f: F) -> Result where
         F: FnOnce(&mut Formatter) -> Result,
     {
-        use char::Char;
+        use char::CharExt;
         let align = match self.align {
             rt::AlignUnknown => default,
             _ => self.align
@@ -613,7 +613,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 
 impl Show for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        use char::Char;
+        use char::CharExt;
 
         let mut utf8 = [0u8; 4];
         let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
index e0724fc2da5f5dc4536357efe6587d77397a08e8..c9646bb3d3506b33e4faf10a1a17138e57c47a2c 100644 (file)
@@ -145,7 +145,7 @@ fn digit(&self, x: u8) -> u8 {
 ///
 /// ```
 /// use std::fmt::radix;
-/// assert_eq!(format!("{}", radix(55i, 36)), "1j".to_string());
+/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
 /// ```
 #[unstable = "may be renamed or move to a different module"]
 pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
index 62bfa381c445eabb1fe031794b72e7c0392888fd..e7e32cec177ec48567f778618a92b1774bfddd77 100644 (file)
@@ -33,7 +33,7 @@
 //! translated to the `loop` below.
 //!
 //! ```rust
-//! let values = vec![1i, 2, 3];
+//! let values = vec![1, 2, 3];
 //!
 //! // "Syntactical sugar" taking advantage of an iterator
 //! for &x in values.iter() {
@@ -118,8 +118,8 @@ pub trait IteratorExt: Iterator + Sized {
     /// # Example
     ///
     /// ```rust
-    /// let a = [0i];
-    /// let b = [1i];
+    /// let a = [0];
+    /// let b = [1];
     /// let mut it = a.iter().chain(b.iter());
     /// assert_eq!(it.next().unwrap(), &0);
     /// assert_eq!(it.next().unwrap(), &1);
@@ -141,10 +141,10 @@ fn chain<U>(self, other: U) -> Chain<Self, U> where
     /// # Example
     ///
     /// ```rust
-    /// let a = [0i];
-    /// let b = [1i];
+    /// let a = [0];
+    /// let b = [1];
     /// let mut it = a.iter().zip(b.iter());
-    /// let (x0, x1) = (0i, 1i);
+    /// let (x0, x1) = (0, 1);
     /// assert_eq!(it.next().unwrap(), (&x0, &x1));
     /// assert!(it.next().is_none());
     /// ```
@@ -162,7 +162,7 @@ fn zip<B, U>(self, other: U) -> Zip<Self, U> where
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2];
+    /// let a = [1, 2];
     /// let mut it = a.iter().map(|&x| 2 * x);
     /// assert_eq!(it.next().unwrap(), 2);
     /// assert_eq!(it.next().unwrap(), 4);
@@ -183,7 +183,7 @@ fn map<B, F>(self, f: F) -> Map< <Self as Iterator>::Item, B, Self, F> where
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2];
+    /// let a = [1, 2];
     /// let mut it = a.iter().filter(|&x| *x > 1);
     /// assert_eq!(it.next().unwrap(), &2);
     /// assert!(it.next().is_none());
@@ -203,7 +203,7 @@ fn filter<P>(self, predicate: P) -> Filter< <Self as Iterator>::Item, Self, P> w
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2];
+    /// let a = [1, 2];
     /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None});
     /// assert_eq!(it.next().unwrap(), 4);
     /// assert!(it.next().is_none());
@@ -222,9 +222,9 @@ fn filter_map<B, F>(self, f: F) -> FilterMap< <Self as Iterator>::Item, B, Self,
     /// # Example
     ///
     /// ```rust
-    /// let a = [100i, 200];
+    /// let a = [100, 200];
     /// let mut it = a.iter().enumerate();
-    /// let (x100, x200) = (100i, 200i);
+    /// let (x100, x200) = (100, 200);
     /// assert_eq!(it.next().unwrap(), (0, &x100));
     /// assert_eq!(it.next().unwrap(), (1, &x200));
     /// assert!(it.next().is_none());
@@ -241,7 +241,7 @@ fn enumerate(self) -> Enumerate<Self> {
     /// # Example
     ///
     /// ```rust
-    /// let xs = [100i, 200, 300];
+    /// let xs = [100, 200, 300];
     /// let mut it = xs.iter().map(|x| *x).peekable();
     /// assert_eq!(*it.peek().unwrap(), 100);
     /// assert_eq!(it.next().unwrap(), 100);
@@ -265,7 +265,7 @@ fn peekable(self) -> Peekable< <Self as Iterator>::Item, Self> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 2, 1];
+    /// let a = [1, 2, 3, 2, 1];
     /// let mut it = a.iter().skip_while(|&a| *a < 3);
     /// assert_eq!(it.next().unwrap(), &3);
     /// assert_eq!(it.next().unwrap(), &2);
@@ -287,7 +287,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile< <Self as Iterator>::Item, Sel
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 2, 1];
+    /// let a = [1, 2, 3, 2, 1];
     /// let mut it = a.iter().take_while(|&a| *a < 3);
     /// assert_eq!(it.next().unwrap(), &1);
     /// assert_eq!(it.next().unwrap(), &2);
@@ -307,7 +307,7 @@ fn take_while<P>(self, predicate: P) -> TakeWhile< <Self as Iterator>::Item, Sel
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter().skip(3);
     /// assert_eq!(it.next().unwrap(), &4);
     /// assert_eq!(it.next().unwrap(), &5);
@@ -325,7 +325,7 @@ fn skip(self, n: uint) -> Skip<Self> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter().take(3);
     /// assert_eq!(it.next().unwrap(), &1);
     /// assert_eq!(it.next().unwrap(), &2);
@@ -346,7 +346,7 @@ fn take(self, n: uint) -> Take<Self> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter().scan(1, |fac, &x| {
     ///   *fac = *fac * x;
     ///   Some(*fac)
@@ -419,9 +419,9 @@ fn flat_map<B, U, F>(self, f: F) -> FlatMap< <Self as Iterator>::Item, B, Self,
     ///     }
     ///     sum
     /// }
-    /// let x = vec![1i,2,3,7,8,9];
+    /// let x = vec![1,2,3,7,8,9];
     /// assert_eq!(process(x.into_iter()), 6);
-    /// let x = vec![1i,2,3];
+    /// let x = vec![1,2,3];
     /// assert_eq!(process(x.into_iter()), 1006);
     /// ```
     #[inline]
@@ -482,7 +482,7 @@ fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let b: Vec<int> = a.iter().map(|&x| x).collect();
     /// assert!(a.as_slice() == b.as_slice());
     /// ```
@@ -498,7 +498,7 @@ fn collect<B: FromIterator< <Self as Iterator>::Item>>(self) -> B {
     /// do not.
     ///
     /// ```
-    /// let vec = vec![1i, 2i, 3i, 4i];
+    /// let vec = vec![1, 2, 3, 4];
     /// let (even, odd): (Vec<int>, Vec<int>) = vec.into_iter().partition(|&n| n % 2 == 0);
     /// assert_eq!(even, vec![2, 4]);
     /// assert_eq!(odd, vec![1, 3]);
@@ -528,7 +528,7 @@ fn partition<B, F>(mut self, mut f: F) -> (B, B) where
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert!(it.nth(2).unwrap() == &3);
     /// assert!(it.nth(2) == None);
@@ -549,7 +549,7 @@ fn nth(&mut self, mut n: uint) -> Option< <Self as Iterator>::Item> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().last().unwrap() == &5);
     /// ```
     #[inline]
@@ -566,7 +566,7 @@ fn last(mut self) -> Option< <Self as Iterator>::Item> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().fold(0, |a, &b| a + b) == 15);
     /// ```
     #[inline]
@@ -586,7 +586,7 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B where
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert!(it.count() == 5);
     /// ```
@@ -601,7 +601,7 @@ fn count(self) -> uint {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().all(|x| *x > 0));
     /// assert!(!a.iter().all(|x| *x > 2));
     /// ```
@@ -618,7 +618,7 @@ fn all<F>(mut self, mut f: F) -> bool where F: FnMut(<Self as Iterator>::Item) -
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert!(it.any(|x| *x == 3));
     /// assert!(!it.any(|x| *x == 3));
@@ -668,7 +668,7 @@ fn position<P>(&mut self, mut predicate: P) -> Option<uint> where
     /// ```rust
     /// use core::num::SignedInt;
     ///
-    /// let xs = [-3i, 0, 1, 5, -10];
+    /// let xs = [-3, 0, 1, 5, -10];
     /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
     /// ```
     #[inline]
@@ -697,7 +697,7 @@ fn max_by<B: Ord, F>(self, mut f: F) -> Option< <Self as Iterator>::Item> where
     /// ```rust
     /// use core::num::SignedInt;
     ///
-    /// let xs = [-3i, 0, 1, 5, -10];
+    /// let xs = [-3, 0, 1, 5, -10];
     /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
     /// ```
     #[inline]
@@ -950,7 +950,7 @@ pub trait AdditiveIterator<A> {
     /// ```rust
     /// use std::iter::AdditiveIterator;
     ///
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a: [i32] = [1, 2, 3, 4, 5];
     /// let mut it = a.iter().map(|&x| x);
     /// assert!(it.sum() == 15);
     /// ```
@@ -1033,7 +1033,7 @@ pub trait IteratorOrdExt<A> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().max().unwrap() == &5);
     /// ```
     fn max(self) -> Option<A>;
@@ -1043,7 +1043,7 @@ pub trait IteratorOrdExt<A> {
     /// # Example
     ///
     /// ```rust
-    /// let a = [1i, 2, 3, 4, 5];
+    /// let a = [1, 2, 3, 4, 5];
     /// assert!(a.iter().min().unwrap() == &1);
     /// ```
     fn min(self) -> Option<A>;
@@ -1069,16 +1069,16 @@ pub trait IteratorOrdExt<A> {
     /// let v: [int; 0] = [];
     /// assert_eq!(v.iter().min_max(), NoElements);
     ///
-    /// let v = [1i];
+    /// let v = [1];
     /// assert!(v.iter().min_max() == OneElement(&1));
     ///
-    /// let v = [1i, 2, 3, 4, 5];
+    /// let v = [1, 2, 3, 4, 5];
     /// assert!(v.iter().min_max() == MinMax(&1, &5));
     ///
-    /// let v = [1i, 2, 3, 4, 5, 6];
+    /// let v = [1, 2, 3, 4, 5, 6];
     /// assert!(v.iter().min_max() == MinMax(&1, &6));
     ///
-    /// let v = [1i, 1, 1, 1];
+    /// let v = [1, 1, 1, 1];
     /// assert!(v.iter().min_max() == MinMax(&1, &1));
     /// ```
     fn min_max(self) -> MinMaxResult<A>;
@@ -1179,10 +1179,10 @@ impl<T: Clone> MinMaxResult<T> {
     /// let r: MinMaxResult<int> = NoElements;
     /// assert_eq!(r.into_option(), None);
     ///
-    /// let r = OneElement(1i);
+    /// let r = OneElement(1);
     /// assert_eq!(r.into_option(), Some((1,1)));
     ///
-    /// let r = MinMax(1i,2i);
+    /// let r = MinMax(1, 2);
     /// assert_eq!(r.into_option(), Some((1,2)));
     /// ```
     pub fn into_option(self) -> Option<(T,T)> {
@@ -1261,7 +1261,7 @@ pub trait CloneIteratorExt {
     /// ```rust
     /// use std::iter::{CloneIteratorExt, count};
     ///
-    /// let a = count(1i,1i).take(1);
+    /// let a = count(1, 1).take(1);
     /// let mut cy = a.cycle();
     /// assert_eq!(cy.next(), Some(1));
     /// assert_eq!(cy.next(), Some(1));
@@ -2726,10 +2726,10 @@ pub trait Step: Ord {
     /// Change self to the previous object.
     fn step_back(&mut self);
     /// The steps_between two step objects.
-    /// a should always be less than b, so the result should never be negative.
+    /// start should always be less than end, so the result should never be negative.
     /// Return None if it is not possible to calculate steps_between without
     /// overflow.
-    fn steps_between(a: &Self, b: &Self) -> Option<uint>;
+    fn steps_between(start: &Self, end: &Self) -> Option<uint>;
 }
 
 macro_rules! step_impl {
@@ -2741,9 +2741,9 @@ impl Step for $t {
             #[inline]
             fn step_back(&mut self) { *self -= 1; }
             #[inline]
-            fn steps_between(a: &$t, b: &$t) -> Option<uint> {
-                debug_assert!(a < b);
-                Some((*a - *b) as uint)
+            fn steps_between(start: &$t, end: &$t) -> Option<uint> {
+                debug_assert!(end >= start);
+                Some((*end - *start) as uint)
             }
         }
     )*)
@@ -2758,7 +2758,7 @@ impl Step for $t {
             #[inline]
             fn step_back(&mut self) { *self -= 1; }
             #[inline]
-            fn steps_between(_a: &$t, _b: &$t) -> Option<uint> {
+            fn steps_between(_start: &$t, _end: &$t) -> Option<uint> {
                 None
             }
         }
index 2620928acc1acca5070786ac304568f20dbb194d..9cf3433e1ab896690b89614585f88477830f6ed1 100644 (file)
@@ -187,13 +187,13 @@ pub unsafe fn uninitialized<T>() -> T {
 /// ```
 /// use std::mem;
 ///
-/// let x = &mut 5i;
-/// let y = &mut 42i;
+/// let x = &mut 5;
+/// let y = &mut 42;
 ///
 /// mem::swap(x, y);
 ///
-/// assert_eq!(42i, *x);
-/// assert_eq!(5i, *y);
+/// assert_eq!(42, *x);
+/// assert_eq!(5, *y);
 /// ```
 #[inline]
 #[stable]
index 6c3b153c00057ce3b9a17ca6f91d21a6f2300191..485d320cf5cc8906153b461222e0bb9bac7a52cc 100644 (file)
@@ -15,7 +15,7 @@
 #![stable]
 #![allow(missing_docs)]
 
-use char::Char;
+use char::CharExt;
 use clone::Clone;
 use cmp::{PartialEq, Eq};
 use cmp::{PartialOrd, Ord};
@@ -336,7 +336,7 @@ fn saturating_sub(self, other: Self) -> Self {
     /// ```rust
     /// use std::num::Int;
     ///
-    /// assert_eq!(2i.pow(4), 16);
+    /// assert_eq!(2.pow(4), 16);
     /// ```
     #[inline]
     fn pow(self, mut exp: uint) -> Self {
index 2a7df5db5c900a13c3a94805f20e890114d3d785..17e4c5f8215a8a2314b61aceedc738a6e950ecdb 100644 (file)
@@ -717,15 +717,6 @@ fn shr(self, other: uint) -> $t { self >> other }
 
 shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
-// NOTE(stage0) remove trait after a snapshot
-#[cfg(stage0)]
-#[allow(missing_docs)]
-#[lang="index"]
-pub trait Index<Sized? Index, Sized? Result> for Sized? {
-    /// The method for the indexing (`Foo[Bar]`) operation
-    fn index<'a>(&'a self, index: &Index) -> &'a Result;
-}
-
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `arr[idx]` when used in an immutable context.
 ///
@@ -755,7 +746,6 @@ pub trait Index<Sized? Index, Sized? Result> for Sized? {
 ///     Foo[Foo];
 /// }
 /// ```
-#[cfg(not(stage0))]  // NOTE(stage0) remove cfg after a snapshot
 #[lang="index"]
 pub trait Index<Sized? Index> for Sized? {
     type Sized? Output;
@@ -764,15 +754,6 @@ pub trait Index<Sized? Index> for Sized? {
     fn index<'a>(&'a self, index: &Index) -> &'a Self::Output;
 }
 
-// NOTE(stage0) remove trait after a snapshot
-#[cfg(stage0)]
-#[allow(missing_docs)]
-#[lang="index_mut"]
-pub trait IndexMut<Sized? Index, Sized? Result> for Sized? {
-    /// The method for the indexing (`Foo[Bar]`) operation
-    fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
-}
-
 /// The `IndexMut` trait is used to specify the functionality of indexing
 /// operations like `arr[idx]`, when used in a mutable context.
 ///
@@ -802,7 +783,6 @@ pub trait IndexMut<Sized? Index, Sized? Result> for Sized? {
 ///     &mut Foo[Foo];
 /// }
 /// ```
-#[cfg(not(stage0))]  // NOTE(stage0) remove cfg after a snapshot
 #[lang="index_mut"]
 pub trait IndexMut<Sized? Index> for Sized? {
     type Sized? Output;
@@ -943,7 +923,7 @@ fn next(&mut self) -> Option<Idx> {
 
     #[inline]
     fn size_hint(&self) -> (uint, Option<uint>) {
-        if let Some(hint) = Step::steps_between(&self.end, &self.start) {
+        if let Some(hint) = Step::steps_between(&self.start, &self.end) {
             (hint, Some(hint))
         } else {
             (0, None)
index a9a1857ec97bf3764f91da9751ce60675447600d..9e55a3aa8c404f641c8c97cff3b8480aefe7f3f9 100644 (file)
@@ -470,10 +470,10 @@ pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -
     ///
     /// ```
     /// let x = Some("foo");
-    /// assert_eq!(x.ok_or(0i), Ok("foo"));
+    /// assert_eq!(x.ok_or(0), Ok("foo"));
     ///
     /// let x: Option<&str> = None;
-    /// assert_eq!(x.ok_or(0i), Err(0i));
+    /// assert_eq!(x.ok_or(0), Err(0));
     /// ```
     #[inline]
     #[experimental]
@@ -491,10 +491,10 @@ pub fn ok_or<E>(self, err: E) -> Result<T, E> {
     ///
     /// ```
     /// let x = Some("foo");
-    /// assert_eq!(x.ok_or_else(|| 0i), Ok("foo"));
+    /// assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
     ///
     /// let x: Option<&str> = None;
-    /// assert_eq!(x.ok_or_else(|| 0i), Err(0i));
+    /// assert_eq!(x.ok_or_else(|| 0), Err(0));
     /// ```
     #[inline]
     #[experimental]
@@ -728,8 +728,8 @@ impl<T: Default> Option<T> {
     /// let good_year = good_year_from_input.parse().unwrap_or_default();
     /// let bad_year = bad_year_from_input.parse().unwrap_or_default();
     ///
-    /// assert_eq!(1909i, good_year);
-    /// assert_eq!(0i, bad_year);
+    /// assert_eq!(1909, good_year);
+    /// assert_eq!(0, bad_year);
     /// ```
     #[inline]
     #[stable]
index 64f13a8f123a8a634f227205cd24cf0d02c3c577..d4aca1bb73c23659e987f6774abfc3c64708cef9 100644 (file)
@@ -38,7 +38,7 @@
 
 // Reexported types and traits
 
-pub use char::Char;
+pub use char::CharExt;
 pub use clone::Clone;
 pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 pub use iter::{Extend, IteratorExt};
index f17a775cf42407e2981e45b440793cf783c5a33c..7aed16173e988bbd852cc1fd1566de977f297eb5 100644 (file)
@@ -531,17 +531,6 @@ fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
     }
 }
 
-// NOTE(stage0) remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> ops::Index<uint, T> for [T] {
-    fn index(&self, &index: &uint) -> &T {
-        assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0) remove cfg after a snapshot
 impl<T> ops::Index<uint> for [T] {
     type Output = T;
 
@@ -552,17 +541,6 @@ fn index(&self, &index: &uint) -> &T {
     }
 }
 
-// NOTE(stage0) remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> ops::IndexMut<uint, T> for [T] {
-    fn index_mut(&mut self, &index: &uint) -> &mut T {
-        assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0) remove cfg after a snapshot
 impl<T> ops::IndexMut<uint> for [T] {
     type Output = T;
 
index d069744f8da54f109bba4c957240999bbbfa8258..8fdd66f83cee4c205d52827a970f6720222a5aca 100644 (file)
@@ -190,7 +190,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
 /// # Panics
 ///
 /// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[unstable = "may change location based on the outcome of the c_str module"]
+#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"]
 pub unsafe fn from_c_str(s: *const i8) -> &'static str {
     let s = s as *const u8;
     let mut len = 0u;
index e6608eee3ddfab565f6fb8f71f94705f72aa1198..b6fc6457fce4d8f3454c8ef0e90465f5802aa352 100644 (file)
@@ -30,7 +30,6 @@
 mod ops;
 mod option;
 mod ptr;
-mod raw;
 mod result;
 mod slice;
 mod str;
index 86fc25c9d918c2b765a2fe26645e0ec299668e0e..4a459992098a08b8a86dff85264e26614e760996 100644 (file)
@@ -220,6 +220,7 @@ fn test_ord() {
     assert!(big > None);
 }
 
+/* FIXME(#20575)
 #[test]
 fn test_collect() {
     let v: Option<Vec<int>> = range(0i, 0).map(|_| Some(0i)).collect();
@@ -234,12 +235,14 @@ fn test_collect() {
     assert!(v == None);
 
     // test that it does not take more elements than it needs
-    let mut functions = [|| Some(()), || None, || panic!()];
+    let mut functions: [Box<Fn() -> Option<()>>; 3] =
+        [box || Some(()), box || None, box || panic!()];
 
     let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
 
     assert!(v == None);
 }
+*/
 
 #[test]
 fn test_cloned() {
diff --git a/src/libcoretest/raw.rs b/src/libcoretest/raw.rs
deleted file mode 100644 (file)
index f2c23c7..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::raw::*;
-use core::mem;
-
-#[test]
-fn synthesize_closure() {
-    unsafe {
-        let x = 10;
-        let f: |int| -> int = |y| x + y;
-
-        assert_eq!(f(20), 30);
-
-        let original_closure: Closure = mem::transmute(f);
-
-        let actual_function_pointer = original_closure.code;
-        let environment = original_closure.env;
-
-        let new_closure = Closure {
-            code: actual_function_pointer,
-            env: environment
-        };
-
-        let new_f: |int| -> int = mem::transmute(new_closure);
-        assert_eq!(new_f(20), 30);
-    }
-}
index 415cd4e7dcfb80a75c05be7cf77452d6062bf703..52ea14dd05dd922ec87611c3b4d26ca0109dcd3b 100644 (file)
@@ -67,6 +67,7 @@ pub fn test_impl_map_err() {
     assert!(Err::<int, int>(1).map_err(|x| x + 1) == Err(2));
 }
 
+/* FIXME(#20575)
 #[test]
 fn test_collect() {
     let v: Result<Vec<int>, ()> = range(0i, 0).map(|_| Ok::<int, ()>(0)).collect();
@@ -81,11 +82,13 @@ fn test_collect() {
     assert!(v == Err(2));
 
     // test that it does not take more elements than it needs
-    let mut functions = [|| Ok(()), || Err(1i), || panic!()];
+    let mut functions: [Box<Fn() -> Result<(), int>>; 3] =
+        [box || Ok(()), box || Err(1i), box || panic!()];
 
     let v: Result<Vec<()>, int> = functions.iter_mut().map(|f| (*f)()).collect();
     assert!(v == Err(1));
 }
+*/
 
 #[test]
 pub fn test_fmt_default() {
index aa1550ae5b874cfbfd5d08dfcfb82e4af1d4ccf9..a0c9da3ae6d497a3ddeb818a189c0b2a597f956c 100644 (file)
 #![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/")]
-#![feature(phase, unboxed_closures)]
+#![feature(phase, unboxed_closures, associated_types)]
 
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
 
 extern crate libc;
 
 use libc::{c_void, size_t, c_int};
-use std::c_vec::CVec;
+use std::ops::Deref;
 use std::ptr::Unique;
+use std::slice;
+
+pub struct Bytes {
+    ptr: Unique<u8>,
+    len: uint,
+}
+
+impl Deref for Bytes {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) }
+    }
+}
+
+impl Drop for Bytes {
+    fn drop(&mut self) {
+        unsafe { libc::free(self.ptr.0 as *mut _); }
+    }
+}
 
 #[link(name = "miniz", kind = "static")]
 extern {
@@ -52,7 +71,7 @@ fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
 static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
 static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
 
-fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
     unsafe {
         let mut outsz : size_t = 0;
         let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
@@ -60,8 +79,8 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
                                              &mut outsz,
                                              flags);
         if !res.is_null() {
-            let res = Unique(res);
-            Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+            let res = Unique(res as *mut u8);
+            Some(Bytes { ptr: res, len: outsz as uint })
         } else {
             None
         }
@@ -69,16 +88,16 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
 }
 
 /// Compress a buffer, without writing any sort of header on the output.
-pub fn deflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
     deflate_bytes_internal(bytes, LZ_NORM)
 }
 
 /// Compress a buffer, using a header that zlib can understand.
-pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
     deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
 }
 
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
     unsafe {
         let mut outsz : size_t = 0;
         let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
@@ -86,8 +105,8 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
                                                &mut outsz,
                                                flags);
         if !res.is_null() {
-            let res = Unique(res);
-            Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+            let res = Unique(res as *mut u8);
+            Some(Bytes { ptr: res, len: outsz as uint })
         } else {
             None
         }
@@ -95,12 +114,12 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
 }
 
 /// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
     inflate_bytes_internal(bytes, 0)
 }
 
 /// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
     inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
 }
 
index f151102f28629992e50f398ffdd034bce1ee8e0e..e3bcf70e8c82ffa833368efa65c3497587cde717 100644 (file)
 //!         dot::Id::new(format!("N{}", n)).unwrap()
 //!     }
 //!     fn node_label<'b>(&'b self, n: &Nd) -> dot::LabelText<'b> {
-//!         dot::LabelStr(self.nodes[*n].as_slice().into_cow())
+//!         dot::LabelText::LabelStr(self.nodes[*n].as_slice().into_cow())
 //!     }
 //!     fn edge_label<'b>(&'b self, _: &Ed) -> dot::LabelText<'b> {
-//!         dot::LabelStr("&sube;".into_cow())
+//!         dot::LabelText::LabelStr("&sube;".into_cow())
 //!     }
 //! }
 //!
 //!     }
 //!     fn node_label<'b>(&'b self, n: &Nd<'b>) -> dot::LabelText<'b> {
 //!         let &(i, _) = n;
-//!         dot::LabelStr(self.nodes[i].as_slice().into_cow())
+//!         dot::LabelText::LabelStr(self.nodes[i].as_slice().into_cow())
 //!     }
 //!     fn edge_label<'b>(&'b self, _: &Ed<'b>) -> dot::LabelText<'b> {
-//!         dot::LabelStr("&sube;".into_cow())
+//!         dot::LabelText::LabelStr("&sube;".into_cow())
 //!     }
 //! }
 //!
 #![feature(globs, slicing_syntax)]
 #![feature(unboxed_closures)]
 
-pub use self::LabelText::*;
+use self::LabelText::*;
 
 use std::borrow::IntoCow;
 use std::io;
@@ -586,8 +586,8 @@ fn indent<W:Writer>(w: &mut W) -> io::IoResult<()> {
 #[cfg(test)]
 mod tests {
     use self::NodeLabels::*;
-    use super::{Id, LabelText, LabelStr, EscStr, Labeller};
-    use super::{Nodes, Edges, GraphWalk, render};
+    use super::{Id, Labeller, Nodes, Edges, GraphWalk, render};
+    use super::LabelText::{mod, LabelStr, EscStr};
     use std::io::IoResult;
     use std::borrow::IntoCow;
     use std::iter::repeat;
index 233d1c049f4e5e2bcdc69327f0c014a2e4069b98..f41a4a8b901a8f329e11fe9802572ccb4b88788b 100644 (file)
@@ -125,7 +125,7 @@ macro_rules! warn {
 /// #[phase(plugin, link)] extern crate log;
 ///
 /// fn main() {
-///     let ret = 3i;
+///     let ret = 3;
 ///     info!("this function is about to return: {}", ret);
 /// }
 /// ```
@@ -152,7 +152,7 @@ macro_rules! info {
 /// #[phase(plugin, link)] extern crate log;
 ///
 /// fn main() {
-///     debug!("x = {x}, y = {y}", x=10i, y=20i);
+///     debug!("x = {x}, y = {y}", x=10, y=20);
 /// }
 /// ```
 ///
index 71ce882e98ca99c2f5d4a602f788221aad9ae53c..ce055a84d3f2aa1421de30acae4e61b7945a8132 100644 (file)
@@ -12,7 +12,6 @@
 
 use core::prelude::*;
 use core::num::Int;
-
 use {Rng, SeedableRng, Rand};
 
 const KEY_WORDS    : uint =  8; // 8 words for the 256-bit key
@@ -28,8 +27,7 @@
 ///
 /// [1]: D. J. Bernstein, [*ChaCha, a variant of
 /// Salsa20*](http://cr.yp.to/chacha.html)
-
-#[derive(Copy)]
+#[deriving(Copy, Clone)]
 pub struct ChaChaRng {
     buffer:  [u32; STATE_WORDS], // Internal buffer of output
     state:   [u32; STATE_WORDS], // Initial state
@@ -283,5 +281,15 @@ fn test_rng_true_values() {
                         0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
                         0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
     }
+
+    #[test]
+    fn test_rng_clone() {
+        let seed : &[_] = &[0u32, ..8];
+        let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
+        let mut clone = rng.clone();
+        for _ in range(0u, 16) {
+            assert_eq!(rng.next_u64(), clone.next_u64());
+        }
+    }
 }
 
index 53ae242c5e245e1050fa85d965b04e7a2fbbdcfd..03b56963ba944e4229096bba33bdee12f39868b9 100644 (file)
@@ -179,6 +179,13 @@ macro_rules! rngstepn(
     }
 }
 
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for IsaacRng {
+    fn clone(&self) -> IsaacRng {
+        *self
+    }
+}
+
 impl Rng for IsaacRng {
     #[inline]
     fn next_u32(&mut self) -> u32 {
@@ -415,6 +422,13 @@ macro_rules! rngstepn(
     }
 }
 
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for Isaac64Rng {
+    fn clone(&self) -> Isaac64Rng {
+        *self
+    }
+}
+
 impl Rng for Isaac64Rng {
     // FIXME #7771: having next_u32 like this should be unnecessary
     #[inline]
@@ -485,6 +499,7 @@ fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
     }
 }
 
+
 #[cfg(test)]
 mod test {
     use std::prelude::v1::*;
@@ -594,4 +609,14 @@ fn test_rng_64_true_values() {
                         596345674630742204, 9947027391921273664, 11788097613744130851,
                         10391409374914919106));
     }
+
+    #[test]
+    fn test_rng_clone() {
+        let seed: &[_] = &[1, 23, 456, 7890, 12345];
+        let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
+        let mut clone = rng.clone();
+        for _ in range(0u, 16) {
+            assert_eq!(rng.next_u64(), clone.next_u64());
+        }
+    }
 }
index 18f508e816f2b772713b8ad2a8f278b4e8467373..f538e0ade05f5f5e1d32fe442c82a2389dbf7ae9 100644 (file)
@@ -269,7 +269,7 @@ fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
     /// ```
     /// use std::rand::{thread_rng, Rng};
     ///
-    /// let choices = [1i, 2, 4, 8, 16, 32];
+    /// let choices = [1, 2, 4, 8, 16, 32];
     /// let mut rng = thread_rng();
     /// println!("{}", rng.choose(&choices));
     /// # // replace with slicing syntax when it's stable!
@@ -291,7 +291,7 @@ fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
     /// use std::rand::{thread_rng, Rng};
     ///
     /// let mut rng = thread_rng();
-    /// let mut y = [1i, 2, 3];
+    /// let mut y = [1, 2, 3];
     /// rng.shuffle(&mut y);
     /// println!("{}", y.as_slice());
     /// rng.shuffle(&mut y);
@@ -385,6 +385,7 @@ pub trait SeedableRng<Seed>: Rng {
 /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
 /// Statistical Software*. Vol. 8 (Issue 14).
 #[allow(missing_copy_implementations)]
+#[deriving(Clone)]
 pub struct XorShiftRng {
     x: u32,
     y: u32,
@@ -392,17 +393,6 @@ pub struct XorShiftRng {
     w: u32,
 }
 
-impl Clone for XorShiftRng {
-    fn clone(&self) -> XorShiftRng {
-        XorShiftRng {
-            x: self.x,
-            y: self.y,
-            z: self.z,
-            w: self.w,
-        }
-    }
-}
-
 impl XorShiftRng {
     /// Creates a new XorShiftRng instance which is not seeded.
     ///
@@ -507,6 +497,7 @@ fn rand<R: Rng>(rng: &mut R) -> XorShiftRng {
 #[cfg(not(test))]
 mod std {
     pub use core::{option, fmt}; // panic!()
+    pub use core::clone; // derive Clone
     pub use core::kinds;
 }
 
index f7d5bfcd117d65a0e9f7a1218224217efa1bae9b..3acedac111d606b97aff651a95af57821f7d6257 100644 (file)
@@ -25,7 +25,7 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![allow(unknown_features)]
 #![feature(macro_rules, phase, slicing_syntax, globs)]
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, associated_types)]
 #![allow(missing_docs)]
 
 extern crate serialize;
@@ -417,6 +417,7 @@ pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
         }
     }
 
+    #[cfg(stage0)]
     impl<'doc> serialize::Decoder<Error> for Decoder<'doc> {
         fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
 
@@ -671,6 +672,263 @@ fn error(&mut self, err: &str) -> Error {
             ApplicationError(err.to_string())
         }
     }
+
+    #[cfg(not(stage0))]
+    impl<'doc> serialize::Decoder for Decoder<'doc> {
+        type Error = Error;
+        fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
+
+        fn read_u64(&mut self) -> DecodeResult<u64> { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) }
+        fn read_u32(&mut self) -> DecodeResult<u32> { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) }
+        fn read_u16(&mut self) -> DecodeResult<u16> { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) }
+        fn read_u8 (&mut self) -> DecodeResult<u8 > { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) }
+        fn read_uint(&mut self) -> DecodeResult<uint> {
+            let v = doc_as_u64(try!(self.next_doc(EsUint)));
+            if v > (::std::uint::MAX as u64) {
+                Err(IntTooBig(v as uint))
+            } else {
+                Ok(v as uint)
+            }
+        }
+
+        fn read_i64(&mut self) -> DecodeResult<i64> {
+            Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64)
+        }
+        fn read_i32(&mut self) -> DecodeResult<i32> {
+            Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32)
+        }
+        fn read_i16(&mut self) -> DecodeResult<i16> {
+            Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16)
+        }
+        fn read_i8 (&mut self) -> DecodeResult<i8> {
+            Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8)
+        }
+        fn read_int(&mut self) -> DecodeResult<int> {
+            let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64;
+            if v > (int::MAX as i64) || v < (int::MIN as i64) {
+                debug!("FIXME \\#6122: Removing this makes this function miscompile");
+                Err(IntTooBig(v as uint))
+            } else {
+                Ok(v as int)
+            }
+        }
+
+        fn read_bool(&mut self) -> DecodeResult<bool> {
+            Ok(doc_as_u8(try!(self.next_doc(EsBool))) != 0)
+        }
+
+        fn read_f64(&mut self) -> DecodeResult<f64> {
+            let bits = doc_as_u64(try!(self.next_doc(EsF64)));
+            Ok(unsafe { transmute(bits) })
+        }
+        fn read_f32(&mut self) -> DecodeResult<f32> {
+            let bits = doc_as_u32(try!(self.next_doc(EsF32)));
+            Ok(unsafe { transmute(bits) })
+        }
+        fn read_char(&mut self) -> DecodeResult<char> {
+            Ok(char::from_u32(doc_as_u32(try!(self.next_doc(EsChar)))).unwrap())
+        }
+        fn read_str(&mut self) -> DecodeResult<String> {
+            Ok(try!(self.next_doc(EsStr)).as_str())
+        }
+
+        // Compound types:
+        fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_enum({})", name);
+            try!(self._check_label(name));
+
+            let doc = try!(self.next_doc(EsEnum));
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = try!(f(self));
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            Ok(result)
+        }
+
+        fn read_enum_variant<T, F>(&mut self, _: &[&str],
+                                   mut f: F) -> DecodeResult<T>
+            where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
+        {
+            debug!("read_enum_variant()");
+            let idx = try!(self._next_uint(EsEnumVid));
+            debug!("  idx={}", idx);
+
+            let doc = try!(self.next_doc(EsEnumBody));
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = try!(f(self, idx));
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            Ok(result)
+        }
+
+        fn read_enum_variant_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_enum_variant_arg(idx={})", idx);
+            f(self)
+        }
+
+        fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
+                                          mut f: F) -> DecodeResult<T>
+            where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
+        {
+            debug!("read_enum_struct_variant()");
+            let idx = try!(self._next_uint(EsEnumVid));
+            debug!("  idx={}", idx);
+
+            let doc = try!(self.next_doc(EsEnumBody));
+
+            let (old_parent, old_pos) = (self.parent, self.pos);
+            self.parent = doc;
+            self.pos = self.parent.start;
+
+            let result = try!(f(self, idx));
+
+            self.parent = old_parent;
+            self.pos = old_pos;
+            Ok(result)
+        }
+
+        fn read_enum_struct_variant_field<T, F>(&mut self,
+                                                name: &str,
+                                                idx: uint,
+                                                f: F)
+                                                -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+                debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
+            f(self)
+        }
+
+        fn read_struct<T, F>(&mut self, name: &str, _: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_struct(name={})", name);
+            f(self)
+        }
+
+        fn read_struct_field<T, F>(&mut self, name: &str, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_struct_field(name={}, idx={})", name, idx);
+            try!(self._check_label(name));
+            f(self)
+        }
+
+        fn read_tuple<T, F>(&mut self, tuple_len: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_tuple()");
+            self.read_seq(move |d, len| {
+                if len == tuple_len {
+                    f(d)
+                } else {
+                    Err(Expected(format!("Expected tuple of length `{}`, \
+                                          found tuple of length `{}`", tuple_len, len)))
+                }
+            })
+        }
+
+        fn read_tuple_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_tuple_arg(idx={})", idx);
+            self.read_seq_elt(idx, f)
+        }
+
+        fn read_tuple_struct<T, F>(&mut self, name: &str, len: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_tuple_struct(name={})", name);
+            self.read_tuple(len, f)
+        }
+
+        fn read_tuple_struct_arg<T, F>(&mut self,
+                                       idx: uint,
+                                       f: F)
+                                       -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_tuple_struct_arg(idx={})", idx);
+            self.read_tuple_arg(idx, f)
+        }
+
+        fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
+            F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
+        {
+            debug!("read_option()");
+            self.read_enum("Option", move |this| {
+                this.read_enum_variant(&["None", "Some"], move |this, idx| {
+                    match idx {
+                        0 => f(this, false),
+                        1 => f(this, true),
+                        _ => {
+                            Err(Expected(format!("Expected None or Some")))
+                        }
+                    }
+                })
+            })
+        }
+
+        fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
+        {
+            debug!("read_seq()");
+            self.push_doc(EsVec, move |d| {
+                let len = try!(d._next_uint(EsVecLen));
+                debug!("  len={}", len);
+                f(d, len)
+            })
+        }
+
+        fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_seq_elt(idx={})", idx);
+            self.push_doc(EsVecElt, f)
+        }
+
+        fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
+        {
+            debug!("read_map()");
+            self.push_doc(EsMap, move |d| {
+                let len = try!(d._next_uint(EsMapLen));
+                debug!("  len={}", len);
+                f(d, len)
+            })
+        }
+
+        fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_map_elt_key(idx={})", idx);
+            self.push_doc(EsMapKey, f)
+        }
+
+        fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        {
+            debug!("read_map_elt_val(idx={})", idx);
+            self.push_doc(EsMapVal, f)
+        }
+
+        fn error(&mut self, err: &str) -> Error {
+            ApplicationError(err.to_string())
+        }
+    }
 }
 
 pub mod writer {
@@ -872,7 +1130,212 @@ pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
         }
     }
 
+    #[cfg(stage0)]
     impl<'a, W: Writer + Seek> serialize::Encoder<io::IoError> for Encoder<'a, W> {
+
+        fn emit_nil(&mut self) -> EncodeResult {
+            Ok(())
+        }
+
+        fn emit_uint(&mut self, v: uint) -> EncodeResult {
+            self.wr_tagged_u64(EsUint as uint, v as u64)
+        }
+        fn emit_u64(&mut self, v: u64) -> EncodeResult {
+            self.wr_tagged_u64(EsU64 as uint, v)
+        }
+        fn emit_u32(&mut self, v: u32) -> EncodeResult {
+            self.wr_tagged_u32(EsU32 as uint, v)
+        }
+        fn emit_u16(&mut self, v: u16) -> EncodeResult {
+            self.wr_tagged_u16(EsU16 as uint, v)
+        }
+        fn emit_u8(&mut self, v: u8) -> EncodeResult {
+            self.wr_tagged_u8(EsU8 as uint, v)
+        }
+
+        fn emit_int(&mut self, v: int) -> EncodeResult {
+            self.wr_tagged_i64(EsInt as uint, v as i64)
+        }
+        fn emit_i64(&mut self, v: i64) -> EncodeResult {
+            self.wr_tagged_i64(EsI64 as uint, v)
+        }
+        fn emit_i32(&mut self, v: i32) -> EncodeResult {
+            self.wr_tagged_i32(EsI32 as uint, v)
+        }
+        fn emit_i16(&mut self, v: i16) -> EncodeResult {
+            self.wr_tagged_i16(EsI16 as uint, v)
+        }
+        fn emit_i8(&mut self, v: i8) -> EncodeResult {
+            self.wr_tagged_i8(EsI8 as uint, v)
+        }
+
+        fn emit_bool(&mut self, v: bool) -> EncodeResult {
+            self.wr_tagged_u8(EsBool as uint, v as u8)
+        }
+
+        fn emit_f64(&mut self, v: f64) -> EncodeResult {
+            let bits = unsafe { mem::transmute(v) };
+            self.wr_tagged_u64(EsF64 as uint, bits)
+        }
+        fn emit_f32(&mut self, v: f32) -> EncodeResult {
+            let bits = unsafe { mem::transmute(v) };
+            self.wr_tagged_u32(EsF32 as uint, bits)
+        }
+        fn emit_char(&mut self, v: char) -> EncodeResult {
+            self.wr_tagged_u32(EsChar as uint, v as u32)
+        }
+
+        fn emit_str(&mut self, v: &str) -> EncodeResult {
+            self.wr_tagged_str(EsStr as uint, v)
+        }
+
+        fn emit_enum<F>(&mut self, name: &str, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            try!(self._emit_label(name));
+            try!(self.start_tag(EsEnum as uint));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_enum_variant<F>(&mut self,
+                                _: &str,
+                                v_id: uint,
+                                _: uint,
+                                f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            try!(self._emit_tagged_uint(EsEnumVid, v_id));
+            try!(self.start_tag(EsEnumBody as uint));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_enum_variant_arg<F>(&mut self, _: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            f(self)
+        }
+
+        fn emit_enum_struct_variant<F>(&mut self,
+                                       v_name: &str,
+                                       v_id: uint,
+                                       cnt: uint,
+                                       f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_enum_variant(v_name, v_id, cnt, f)
+        }
+
+        fn emit_enum_struct_variant_field<F>(&mut self,
+                                             _: &str,
+                                             idx: uint,
+                                             f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_enum_variant_arg(idx, f)
+        }
+
+        fn emit_struct<F>(&mut self, _: &str, _len: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            f(self)
+        }
+
+        fn emit_struct_field<F>(&mut self, name: &str, _: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            try!(self._emit_label(name));
+            f(self)
+        }
+
+        fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_seq(len, f)
+        }
+        fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_seq_elt(idx, f)
+        }
+
+        fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_seq(len, f)
+        }
+        fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_seq_elt(idx, f)
+        }
+
+        fn emit_option<F>(&mut self, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            self.emit_enum("Option", f)
+        }
+        fn emit_option_none(&mut self) -> EncodeResult {
+            self.emit_enum_variant("None", 0, 0, |_| Ok(()))
+        }
+        fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+
+            self.emit_enum_variant("Some", 1, 1, f)
+        }
+
+        fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+
+            try!(self.start_tag(EsVec as uint));
+            try!(self._emit_tagged_uint(EsVecLen, len));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_seq_elt<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+
+            try!(self.start_tag(EsVecElt as uint));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+
+            try!(self.start_tag(EsMap as uint));
+            try!(self._emit_tagged_uint(EsMapLen, len));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_map_elt_key<F>(&mut self, _idx: uint, mut f: F) -> EncodeResult where
+            F: FnMut(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+
+            try!(self.start_tag(EsMapKey as uint));
+            try!(f(self));
+            self.end_tag()
+        }
+
+        fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
+            F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult,
+        {
+            try!(self.start_tag(EsMapVal as uint));
+            try!(f(self));
+            self.end_tag()
+        }
+    }
+    #[cfg(not(stage0))]
+    impl<'a, W: Writer + Seek> serialize::Encoder for Encoder<'a, W> {
+        type Error = io::IoError;
+
         fn emit_nil(&mut self) -> EncodeResult {
             Ok(())
         }
index 8f03f8821285a47c24d951abb92d114d3d651beb..1a145746a286eba77a546a43858c7e4bff3aea48 100644 (file)
@@ -494,11 +494,7 @@ fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
         let mut n_uniq = 0i;
         ty::fold_ty(cx.tcx, ty, |t| {
             match t.sty {
-                ty::ty_uniq(_) |
-                ty::ty_closure(box ty::ClosureTy {
-                    store: ty::UniqTraitStore,
-                    ..
-                }) => {
+                ty::ty_uniq(_) => {
                     n_uniq += 1;
                 }
 
@@ -550,20 +546,20 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
 }
 
 declare_lint! {
-    RAW_POINTER_DERIVING,
+    RAW_POINTER_DERIVE,
     Warn,
     "uses of #[derive] with raw pointers are rarely correct"
 }
 
-struct RawPtrDerivingVisitor<'a, 'tcx: 'a> {
+struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
     cx: &'a Context<'a, 'tcx>
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDerivingVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
         static MSG: &'static str = "use of `#[derive]` with a raw pointer";
         if let ast::TyPtr(..) = ty.node {
-            self.cx.span_lint(RAW_POINTER_DERIVING, ty.span, MSG);
+            self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
         }
         visit::walk_ty(self, ty);
     }
@@ -572,21 +568,21 @@ fn visit_expr(&mut self, _: &ast::Expr) {}
     fn visit_block(&mut self, _: &ast::Block) {}
 }
 
-pub struct RawPointerDeriving {
+pub struct RawPointerDerive {
     checked_raw_pointers: NodeSet,
 }
 
-impl RawPointerDeriving {
-    pub fn new() -> RawPointerDeriving {
-        RawPointerDeriving {
+impl RawPointerDerive {
+    pub fn new() -> RawPointerDerive {
+        RawPointerDerive {
             checked_raw_pointers: NodeSet::new(),
         }
     }
 }
 
-impl LintPass for RawPointerDeriving {
+impl LintPass for RawPointerDerive {
     fn get_lints(&self) -> LintArray {
-        lint_array!(RAW_POINTER_DERIVING)
+        lint_array!(RAW_POINTER_DERIVE)
     }
 
     fn check_item(&mut self, cx: &Context, item: &ast::Item) {
@@ -611,7 +607,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
         if !self.checked_raw_pointers.insert(item.id) { return }
         match item.node {
             ast::ItemStruct(..) | ast::ItemEnum(..) => {
-                let mut visitor = RawPtrDerivingVisitor { cx: cx };
+                let mut visitor = RawPtrDeriveVisitor { cx: cx };
                 visit::walk_item(&mut visitor, &*item);
             }
             _ => {}
@@ -1329,8 +1325,8 @@ fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
                 let ident = path1.node;
                 if let ast::BindByValue(ast::MutMutable) = mode {
                     if !token::get_ident(ident).get().starts_with("_") {
-                        match mutables.entry(ident.name.uint()) {
-                            Vacant(entry) => { entry.set(vec![id]); },
+                        match mutables.entry(&ident.name.uint()) {
+                            Vacant(entry) => { entry.insert(vec![id]); },
                             Occupied(mut entry) => { entry.get_mut().push(id); },
                         }
                     }
@@ -1762,7 +1758,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
                     }
                 }
             }
-            ast::ItemImpl(_, _, Some(ref t), _, _) => {
+            ast::ItemImpl(_, _, _, Some(ref t), _, _) => {
                 let id = ty::trait_ref_to_def_id(cx.tcx, t);
                 self.lint(cx, id, t.path.span);
             }
index 69e5b4889c28837ab5169d956a944e0df09a3c7d..521e5e305bc77529df3d4b475e03cc93295aa485 100644 (file)
@@ -208,7 +208,7 @@ macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => (
 
         add_builtin_with_new!(sess,
                               TypeLimits,
-                              RawPointerDeriving,
+                              RawPointerDerive,
                               MissingDoc,
         );
 
@@ -247,6 +247,7 @@ macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => (
         self.register_renamed("unknown_crate_type", "unknown_crate_types");
         self.register_renamed("variant_size_difference", "variant_size_differences");
         self.register_renamed("transmute_fat_ptr", "fat_ptr_transmutes");
+        self.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
 
     }
 
index cc21243b81d8db45c00ddb877f86e2edd69967dd..ca7c65c8e2bc220223d2845e4832206e7fed0b9b 100644 (file)
@@ -259,3 +259,5 @@ pub struct LinkMeta {
 
 pub const tag_associated_type_names: uint = 0xb2;
 pub const tag_associated_type_name: uint = 0xb3;
+
+pub const tag_polarity: uint = 0xb4;
index 5dac2bafaec3d847508de229b3244ca3a169f812..b0cf322b0688ec47baa287ca59477d45f88e7306 100644 (file)
@@ -87,8 +87,8 @@ fn dump_crates(cstore: &CStore) {
 fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
     let mut map = FnvHashMap::new();
     cstore.iter_crate_data(|cnum, data| {
-        match map.entry(data.name()) {
-            Vacant(entry) => { entry.set(vec![cnum]); },
+        match map.entry(&data.name()) {
+            Vacant(entry) => { entry.insert(vec![cnum]); },
             Occupied(mut entry) => { entry.get_mut().push(cnum); },
         }
     });
index 2f4acaca4de4d3eda8f5f1223da3182d9bd89f15..ec0b80c3a5342f26b6af6563ab6a628b0f2810b1 100644 (file)
@@ -23,8 +23,8 @@
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use std::cell::RefCell;
-use std::c_vec::CVec;
 use std::rc::Rc;
+use flate::Bytes;
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token::IdentInterner;
@@ -36,7 +36,7 @@
 pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
 
 pub enum MetadataBlob {
-    MetadataVec(CVec<u8>),
+    MetadataVec(Bytes),
     MetadataArchive(loader::ArchiveMetadata),
 }
 
index 97f5228f0330b5ca98a988d15215ff433e47052d..ac8dfc1675942c37055147762cb438bb94a20568 100644 (file)
@@ -662,27 +662,27 @@ pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
     item_path(lookup_item(id, cdata.data()))
 }
 
-pub type DecodeInlinedItem<'a> = for<'tcx> |cdata: Cmd,
-                                            tcx: &ty::ctxt<'tcx>,
-                                            path: Vec<ast_map::PathElem>,
-                                            par_doc: rbml::Doc|: 'a
-                                            -> Result<&'tcx ast::InlinedItem,
-                                                      Vec<ast_map::PathElem>>;
+pub type DecodeInlinedItem<'a> =
+    Box<for<'tcx> FnMut(Cmd,
+                        &ty::ctxt<'tcx>,
+                        Vec<ast_map::PathElem>,
+                        rbml::Doc)
+                        -> Result<&'tcx ast::InlinedItem, Vec<ast_map::PathElem>> + 'a>;
 
 pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
-                                decode_inlined_item: DecodeInlinedItem)
+                                mut decode_inlined_item: DecodeInlinedItem)
                                 -> csearch::found_ast<'tcx> {
     debug!("Looking up item: {}", id);
     let item_doc = lookup_item(id, cdata.data());
     let path = item_path(item_doc).init().to_vec();
-    match decode_inlined_item(cdata, tcx, path, item_doc) {
+    match decode_inlined_item.call_mut((cdata, tcx, path, item_doc)) {
         Ok(ii) => csearch::found(ii),
         Err(path) => {
             match item_parent_item(item_doc) {
                 Some(did) => {
                     let did = translate_def_id(cdata, did);
                     let parent_item = lookup_item(did.node, cdata.data());
-                    match decode_inlined_item(cdata, tcx, path, parent_item) {
+                    match decode_inlined_item.call_mut((cdata, tcx, path, parent_item)) {
                         Ok(ii) => csearch::found_parent(did, ii),
                         Err(_) => csearch::not_found
                     }
index 75b9a18063e2821f9e37372b376ea51734973c91..14ab471a4b8314c77fd4c626f9dfbca4c44ed939 100644 (file)
@@ -59,9 +59,8 @@ pub enum InlinedItemRef<'a> {
 
 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
 
-pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
-                                  rbml_w: &mut Encoder,
-                                  ii: InlinedItemRef|: 'a;
+pub type EncodeInlinedItem<'a> =
+    Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
 
 pub struct EncodeParams<'a, 'tcx: 'a> {
     pub diag: &'a SpanHandler,
@@ -953,7 +952,7 @@ fn encode_inlined_item(ecx: &EncodeContext,
                        ii: InlinedItemRef) {
     let mut eii = ecx.encode_inlined_item.borrow_mut();
     let eii: &mut EncodeInlinedItem = &mut *eii;
-    (*eii)(ecx, rbml_w, ii)
+    eii.call_mut((ecx, rbml_w, ii))
 }
 
 const FN_FAMILY: char = 'f';
@@ -1207,7 +1206,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             None => {}
         }
       }
-      ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => {
+      ast::ItemImpl(unsafety, polarity, _, ref opt_trait, 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();
@@ -1221,6 +1220,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_name(rbml_w, item.ident.name);
         encode_attributes(rbml_w, item.attrs[]);
         encode_unsafety(rbml_w, unsafety);
+        encode_polarity(rbml_w, polarity);
         match ty.node {
             ast::TyPath(ref path, _) if path.segments.len() == 1 => {
                 let ident = path.segments.last().unwrap().identifier;
@@ -1704,6 +1704,14 @@ fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
     rbml_w.end_tag();
 }
 
+fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
+    let byte: u8 = match polarity {
+        ast::ImplPolarity::Positive => 0,
+        ast::ImplPolarity::Negative => 1,
+    };
+    rbml_w.wr_tagged_u8(tag_polarity, byte);
+}
+
 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
         // Pull the cnums and name,vers,hash out of cstore
@@ -1885,7 +1893,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
 
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
-        if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node {
+        if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
             let def_map = &self.ecx.tcx.def_map;
             let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
             let def_id = trait_def.def_id();
index 5f554eb9c1e5c0dc577490f68704a11816d3356d..7c0645b4ca204037c451ef1c62f6232a7c547360 100644 (file)
 use syntax::diagnostic::SpanHandler;
 use util::fs;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cmp;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::collections::{HashMap, HashSet};
 use std::io::fs::PathExtensions;
 use std::io;
@@ -400,10 +399,9 @@ fn find_library_crate(&mut self) -> Option<Library> {
             };
             info!("lib candidate: {}", path.display());
 
-            let slot = match candidates.entry(hash.to_string()) {
-                Occupied(entry) => entry.into_mut(),
-                Vacant(entry) => entry.set((HashSet::new(), HashSet::new())),
-            };
+            let hash_str = hash.to_string();
+            let slot = candidates.entry(&hash_str).get().unwrap_or_else(
+                |vacant_entry| vacant_entry.insert((HashSet::new(), HashSet::new())));
             let (ref mut rlibs, ref mut dylibs) = *slot;
             if rlib {
                 rlibs.insert(fs::realpath(path).unwrap());
@@ -722,9 +720,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
         }
     }
     unsafe {
-        let mb = filename.with_c_str(|buf| {
-            llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
-        });
+        let buf = CString::from_slice(filename.as_vec());
+        let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
         if mb as int == 0 {
             return Err(format!("error reading library: '{}'",
                                filename.display()))
@@ -740,8 +737,9 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
         while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
             let mut name_buf = ptr::null();
             let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
-            let name = String::from_raw_buf_len(name_buf as *const u8,
-                                                name_len as uint);
+            let name = slice::from_raw_buf(&(name_buf as *const u8),
+                                           name_len as uint).to_vec();
+            let name = String::from_utf8(name).unwrap();
             debug!("get_metadata_section: name {}", name);
             if read_meta_section_name(is_osx) == name {
                 let cbuf = llvm::LLVMGetSectionContents(si.llsi);
index 80b13aac89fc8f2feb1aaa4293d7e143323d2d0e..07dc13ff0d48f6e3b782bb1bbf858b57f935359c 100644 (file)
@@ -61,8 +61,7 @@ pub enum DefIdSource {
     UnboxedClosureSource
 }
 
-pub type conv_did<'a> =
-    |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
+// type conv_did = impl FnMut(DefIdSource, ast::DefId) -> ast::DefId;
 
 pub struct PState<'a, 'tcx: 'a> {
     data: &'a [u8],
@@ -145,70 +144,88 @@ fn data_log_string(data: &[u8], pos: uint) -> String {
     buf
 }
 
-pub fn parse_ty_closure_data<'tcx>(data: &[u8],
-                                   crate_num: ast::CrateNum,
-                                   pos: uint,
-                                   tcx: &ty::ctxt<'tcx>,
-                                   conv: conv_did)
-                                   -> ty::ClosureTy<'tcx> {
+pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
+                                      crate_num: ast::CrateNum,
+                                      pos: uint,
+                                      tcx: &ty::ctxt<'tcx>,
+                                      conv: F)
+                                      -> ty::ClosureTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_closure_ty(&mut st, conv)
 }
 
-pub fn parse_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
-                           tcx: &ty::ctxt<'tcx>, conv: conv_did) -> Ty<'tcx> {
+pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
+                              tcx: &ty::ctxt<'tcx>, conv: F) -> Ty<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     debug!("parse_ty_data {}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_ty(&mut st, conv)
 }
 
-pub fn parse_region_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
-                         conv: conv_did) -> ty::Region {
+pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
+                            conv: F) -> ty::Region where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     debug!("parse_region_data {}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_region(&mut st, conv)
 }
 
-pub fn parse_bare_fn_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
-                                   tcx: &ty::ctxt<'tcx>, conv: conv_did)
-                                   -> ty::BareFnTy<'tcx> {
+pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
+                                      tcx: &ty::ctxt<'tcx>, conv: F)
+                                      -> ty::BareFnTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_bare_fn_ty(&mut st, conv)
 }
 
-pub fn parse_trait_ref_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
-                                  tcx: &ty::ctxt<'tcx>, conv: conv_did)
-                                  -> Rc<ty::TraitRef<'tcx>> {
+pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
+                                     tcx: &ty::ctxt<'tcx>, conv: F)
+                                     -> Rc<ty::TraitRef<'tcx>> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     debug!("parse_trait_ref_data {}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_trait_ref(&mut st, conv)
 }
 
-pub fn parse_substs_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
-                               tcx: &ty::ctxt<'tcx>, conv: conv_did) -> subst::Substs<'tcx> {
+pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
+                                  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));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_substs(&mut st, conv)
 }
 
-pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
-                               pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
-                               -> ty::ParamBounds<'tcx> {
+pub fn parse_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
+                                  pos: uint, 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>(data: &[u8], crate_num: ast::CrateNum,
-                                           pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
-                                           -> ty::ExistentialBounds<'tcx> {
+pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
+                                              pos: uint, tcx: &ty::ctxt<'tcx>, conv: F)
+                                              -> ty::ExistentialBounds<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_existential_bounds(&mut st, conv)
 }
 
-pub fn parse_builtin_bounds_data(data: &[u8], crate_num: ast::CrateNum,
-                                 pos: uint, tcx: &ty::ctxt, conv: conv_did)
-                                 -> ty::BuiltinBounds {
+pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
+                                    pos: uint, tcx: &ty::ctxt, conv: F)
+                                    -> ty::BuiltinBounds where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_builtin_bounds(&mut st, conv)
 }
@@ -226,10 +243,12 @@ fn parse_size(st: &mut PState) -> Option<uint> {
     }
 }
 
-fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
+fn parse_trait_store_<F>(st: &mut PState, conv: &mut F) -> ty::TraitStore where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     match next(st) {
         '~' => ty::UniqTraitStore,
-        '&' => ty::RegionTraitStore(parse_region(st, conv), parse_mutability(st)),
+        '&' => ty::RegionTraitStore(parse_region_(st, conv), parse_mutability(st)),
         c => {
             st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'",
                                     c)[])
@@ -253,31 +272,44 @@ fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>,
     r
 }
 
-fn parse_substs<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
-                          conv: conv_did) -> subst::Substs<'tcx> {
+fn parse_substs<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                             mut conv: F) -> subst::Substs<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_substs_(st, &mut conv)
+}
+
+fn parse_substs_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                              conv: &mut F) -> subst::Substs<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let regions =
-        parse_region_substs(st, |x,y| conv(x,y));
+        parse_region_substs_(st, conv);
 
     let types =
-        parse_vec_per_param_space(st, |st| parse_ty(st, |x,y| conv(x,y)));
+        parse_vec_per_param_space(st, |st| parse_ty_(st, conv));
 
     subst::Substs { types: types,
                     regions: regions }
 }
 
-fn parse_region_substs(st: &mut PState, conv: conv_did) -> subst::RegionSubsts {
+fn parse_region_substs_<F>(st: &mut PState, conv: &mut F) -> subst::RegionSubsts where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     match next(st) {
         'e' => subst::ErasedRegions,
         'n' => {
             subst::NonerasedRegions(
                 parse_vec_per_param_space(
-                    st, |st| parse_region(st, |x,y| conv(x,y))))
+                    st, |st| parse_region_(st, conv)))
         }
         _ => panic!("parse_bound_region: bad input")
     }
 }
 
-fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
+fn parse_bound_region_<F>(st: &mut PState, conv: &mut F) -> ty::BoundRegion where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     match next(st) {
         'a' => {
             let id = parse_u32(st);
@@ -285,7 +317,7 @@ fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
             ty::BrAnon(id)
         }
         '[' => {
-            let def = parse_def(st, RegionParameter, |x,y| conv(x,y));
+            let def = parse_def_(st, RegionParameter, conv);
             let ident = token::str_to_ident(parse_str(st, ']')[]);
             ty::BrNamed(def, ident.name)
         }
@@ -299,13 +331,21 @@ fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
     }
 }
 
-fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
+fn parse_region<F>(st: &mut PState, mut conv: F) -> ty::Region where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_region_(st, &mut conv)
+}
+
+fn parse_region_<F>(st: &mut PState, conv: &mut F) -> ty::Region where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     match next(st) {
       'b' => {
         assert_eq!(next(st), '[');
         let id = ty::DebruijnIndex::new(parse_u32(st));
         assert_eq!(next(st), '|');
-        let br = parse_bound_region(st, |x,y| conv(x,y));
+        let br = parse_bound_region_(st, conv);
         assert_eq!(next(st), ']');
         ty::ReLateBound(id, br)
       }
@@ -324,7 +364,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
         assert_eq!(next(st), '[');
         let scope = parse_scope(st);
         assert_eq!(next(st), '|');
-        let br = parse_bound_region(st, |x,y| conv(x,y));
+        let br = parse_bound_region_(st, conv);
         assert_eq!(next(st), ']');
         ty::ReFree(ty::FreeRegion { scope: scope,
                                     bound_region: br})
@@ -375,14 +415,31 @@ fn parse_str(st: &mut PState, term: char) -> String {
     result
 }
 
-fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
-                             -> Rc<ty::TraitRef<'tcx>> {
-    let def = parse_def(st, NominalType, |x,y| conv(x,y));
-    let substs = st.tcx.mk_substs(parse_substs(st, |x,y| conv(x,y)));
+fn parse_trait_ref<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F)
+                                -> Rc<ty::TraitRef<'tcx>> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_trait_ref_(st, &mut conv)
+}
+
+fn parse_trait_ref_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
+                              -> Rc<ty::TraitRef<'tcx>> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let def = parse_def_(st, NominalType, conv);
+    let substs = st.tcx.mk_substs(parse_substs_(st, conv));
     Rc::new(ty::TraitRef {def_id: def, substs: substs})
 }
 
-fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
+fn parse_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F) -> Ty<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_ty_(st, &mut conv)
+}
+
+fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let tcx = st.tcx;
     match next(st) {
       'b' => return tcx.types.bool,
@@ -406,15 +463,15 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
       'c' => return tcx.types.char,
       't' => {
         assert_eq!(next(st), '[');
-        let def = parse_def(st, NominalType, |x,y| conv(x,y));
-        let substs = parse_substs(st, |x,y| conv(x,y));
+        let def = parse_def_(st, NominalType, conv);
+        let substs = parse_substs_(st, conv);
         assert_eq!(next(st), ']');
         return ty::mk_enum(tcx, def, st.tcx.mk_substs(substs));
       }
       'x' => {
         assert_eq!(next(st), '[');
-        let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)));
-        let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
+        let trait_ref = ty::Binder(parse_trait_ref_(st, conv));
+        let bounds = parse_existential_bounds_(st, conv);
         assert_eq!(next(st), ']');
         return ty::mk_trait(tcx, trait_ref, bounds);
       }
@@ -427,15 +484,15 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
         let name = token::intern(parse_str(st, ']')[]);
         return ty::mk_param(tcx, space, index, name);
       }
-      '~' => return ty::mk_uniq(tcx, parse_ty(st, |x,y| conv(x,y))),
-      '*' => return ty::mk_ptr(tcx, parse_mt(st, |x,y| conv(x,y))),
+      '~' => return ty::mk_uniq(tcx, parse_ty_(st, conv)),
+      '*' => return ty::mk_ptr(tcx, parse_mt_(st, conv)),
       '&' => {
-        let r = parse_region(st, |x,y| conv(x,y));
-        let mt = parse_mt(st, |x,y| conv(x,y));
+        let r = parse_region_(st, conv);
+        let mt = parse_mt_(st, conv);
         return ty::mk_rptr(tcx, tcx.mk_region(r), mt);
       }
       'V' => {
-        let t = parse_ty(st, |x,y| conv(x,y));
+        let t = parse_ty_(st, conv);
         let sz = parse_size(st);
         return ty::mk_vec(tcx, t, sz);
       }
@@ -445,21 +502,18 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = Vec::new();
-        while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
+        while peek(st) != ']' { params.push(parse_ty_(st, conv)); }
         st.pos = st.pos + 1u;
         return ty::mk_tup(tcx, params);
       }
-      'f' => {
-        return ty::mk_closure(tcx, parse_closure_ty(st, |x,y| conv(x,y)));
-      }
       'F' => {
-          let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
+          let def_id = parse_def_(st, NominalType, conv);
           return ty::mk_bare_fn(tcx, Some(def_id),
-                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+                                tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
       }
       'G' => {
           return ty::mk_bare_fn(tcx, None,
-                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+                                tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
       }
       '#' => {
         let pos = parse_hex(st);
@@ -478,34 +532,34 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
             pos: pos,
             .. *st
         };
-        let tt = parse_ty(&mut ps, |x,y| conv(x,y));
+        let tt = parse_ty_(&mut ps, conv);
         tcx.rcache.borrow_mut().insert(key, tt);
         return tt;
       }
       '\"' => {
-        let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
-        let inner = parse_ty(st, |x,y| conv(x,y));
+        let _ = parse_def_(st, TypeWithId, conv);
+        let inner = parse_ty_(st, conv);
         inner
       }
       'a' => {
           assert_eq!(next(st), '[');
-          let did = parse_def(st, NominalType, |x,y| conv(x,y));
-          let substs = parse_substs(st, |x,y| conv(x,y));
+          let did = parse_def_(st, NominalType, conv);
+          let substs = parse_substs_(st, conv);
           assert_eq!(next(st), ']');
           return ty::mk_struct(st.tcx, did, st.tcx.mk_substs(substs));
       }
       'k' => {
           assert_eq!(next(st), '[');
-          let did = parse_def(st, UnboxedClosureSource, |x,y| conv(x,y));
-          let region = parse_region(st, |x,y| conv(x,y));
-          let substs = parse_substs(st, |x,y| conv(x,y));
+          let did = parse_def_(st, UnboxedClosureSource, conv);
+          let region = parse_region_(st, conv);
+          let substs = parse_substs_(st, conv);
           assert_eq!(next(st), ']');
           return ty::mk_unboxed_closure(st.tcx, did,
                   st.tcx.mk_region(region), st.tcx.mk_substs(substs));
       }
       'P' => {
           assert_eq!(next(st), '[');
-          let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
+          let trait_ref = parse_trait_ref_(st, conv);
           let name = token::intern(parse_str(st, ']').as_slice());
           return ty::mk_projection(tcx, trait_ref, name);
       }
@@ -523,14 +577,17 @@ fn parse_mutability(st: &mut PState) -> ast::Mutability {
     }
 }
 
-fn parse_mt<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::mt<'tcx> {
+fn parse_mt_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::mt<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let m = parse_mutability(st);
-    ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m }
+    ty::mt { ty: parse_ty_(st, conv), mutbl: m }
 }
 
-fn parse_def(st: &mut PState, source: DefIdSource,
-             conv: conv_did) -> ast::DefId {
-    return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
+fn parse_def_<F>(st: &mut PState, source: DefIdSource, conv: &mut F) -> ast::DefId where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    return (*conv)(source, scan(st, |c| { c == '|' }, parse_def_id));
 }
 
 fn parse_uint(st: &mut PState) -> uint {
@@ -592,13 +649,22 @@ fn parse_onceness(c: char) -> ast::Onceness {
     }
 }
 
-fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
-                              conv: conv_did) -> ty::ClosureTy<'tcx> {
+fn parse_closure_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                 mut conv: F) -> ty::ClosureTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_closure_ty_(st, &mut conv)
+}
+
+fn parse_closure_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                 conv: &mut F) -> ty::ClosureTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let unsafety = parse_unsafety(next(st));
     let onceness = parse_onceness(next(st));
-    let store = parse_trait_store(st, |x,y| conv(x,y));
-    let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
-    let sig = parse_sig(st, |x,y| conv(x,y));
+    let store = parse_trait_store_(st, conv);
+    let bounds = parse_existential_bounds_(st, conv);
+    let sig = parse_sig_(st, conv);
     let abi = parse_abi_set(st);
     ty::ClosureTy {
         unsafety: unsafety,
@@ -610,11 +676,20 @@ fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
     }
 }
 
-fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
-                              conv: conv_did) -> ty::BareFnTy<'tcx> {
+fn parse_bare_fn_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                 mut conv: F) -> ty::BareFnTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_bare_fn_ty_(st, &mut conv)
+}
+
+fn parse_bare_fn_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                 conv: &mut F) -> ty::BareFnTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let unsafety = parse_unsafety(next(st));
     let abi = parse_abi_set(st);
-    let sig = parse_sig(st, |x,y| conv(x,y));
+    let sig = parse_sig_(st, conv);
     ty::BareFnTy {
         unsafety: unsafety,
         abi: abi,
@@ -622,11 +697,13 @@ fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
     }
 }
 
-fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::PolyFnSig<'tcx> {
+fn parse_sig_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::PolyFnSig<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     assert_eq!(next(st), '[');
     let mut inputs = Vec::new();
     while peek(st) != ']' {
-        inputs.push(parse_ty(st, |x,y| conv(x,y)));
+        inputs.push(parse_ty_(st, conv));
     }
     st.pos += 1u; // eat the ']'
     let variadic = match next(st) {
@@ -639,7 +716,7 @@ fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::PolyFnS
           st.pos += 1u;
           ty::FnDiverging
         }
-        _ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
+        _ => ty::FnConverging(parse_ty_(st, conv))
     };
     ty::Binder(ty::FnSig {inputs: inputs,
                         output: output,
@@ -672,66 +749,87 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
     ast::DefId { krate: crate_num, node: def_num }
 }
 
-pub fn parse_predicate_data<'tcx>(data: &[u8],
-                                  start: uint,
-                                  crate_num: ast::CrateNum,
-                                  tcx: &ty::ctxt<'tcx>,
-                                  conv: conv_did)
-                                  -> ty::Predicate<'tcx>
+pub fn parse_predicate_data<'tcx, F>(data: &[u8],
+                                     start: uint,
+                                     crate_num: ast::CrateNum,
+                                     tcx: &ty::ctxt<'tcx>,
+                                     conv: F)
+                                     -> ty::Predicate<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     let mut st = parse_state_from_data(data, crate_num, start, tcx);
     parse_predicate(&mut st, conv)
 }
 
-pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
-                                conv: conv_did)
-                                -> ty::Predicate<'tcx>
+pub fn parse_predicate<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                   mut conv: F)
+                                   -> ty::Predicate<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_predicate_(st, &mut conv)
+}
+
+fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
+                                conv: &mut F)
+                                -> ty::Predicate<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     match next(st) {
-        't' => ty::Binder(parse_trait_ref(st, conv)).as_predicate(),
-        'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
-                                              parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
-        'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
-                                                parse_region(st, |x,y| conv(x,y)))).as_predicate(),
-        'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
-                                                parse_region(st, |x,y| conv(x,y)))).as_predicate(),
-        'p' => ty::Binder(parse_projection_predicate(st, conv)).as_predicate(),
+        't' => ty::Binder(parse_trait_ref_(st, conv)).as_predicate(),
+        'e' => ty::Binder(ty::EquatePredicate(parse_ty_(st, conv),
+                                              parse_ty_(st, conv))).as_predicate(),
+        'r' => ty::Binder(ty::OutlivesPredicate(parse_region_(st, conv),
+                                                parse_region_(st, conv))).as_predicate(),
+        'o' => ty::Binder(ty::OutlivesPredicate(parse_ty_(st, conv),
+                                                parse_region_(st, conv))).as_predicate(),
+        'p' => ty::Binder(parse_projection_predicate_(st, conv)).as_predicate(),
         c => panic!("Encountered invalid character in metadata: {}", c)
     }
 }
 
-fn parse_projection_predicate<'a,'tcx>(
+fn parse_projection_predicate_<'a,'tcx, F>(
     st: &mut PState<'a, 'tcx>,
-    conv: conv_did)
-     -> ty::ProjectionPredicate<'tcx>
+    conv: &mut F,
+) -> ty::ProjectionPredicate<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     ty::ProjectionPredicate {
         projection_ty: ty::ProjectionTy {
-            trait_ref: parse_trait_ref(st, |x,y| conv(x,y)),
+            trait_ref: parse_trait_ref_(st, conv),
             item_name: token::str_to_ident(parse_str(st, '|').as_slice()).name,
         },
-        ty: parse_ty(st, |x,y| conv(x,y)),
+        ty: parse_ty_(st, conv),
     }
 }
 
-pub fn parse_type_param_def_data<'tcx>(data: &[u8], start: uint,
-                                       crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
-                                       conv: conv_did) -> ty::TypeParameterDef<'tcx>
+pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: uint,
+                                          crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
+                                          conv: F) -> ty::TypeParameterDef<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     let mut st = parse_state_from_data(data, crate_num, start, tcx);
     parse_type_param_def(&mut st, conv)
 }
 
-fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
-                                  -> ty::TypeParameterDef<'tcx> {
+fn parse_type_param_def<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F)
+                                     -> ty::TypeParameterDef<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_type_param_def_(st, &mut conv)
+}
+
+fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
+                                      -> ty::TypeParameterDef<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
     let name = parse_name(st, ':');
-    let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
+    let def_id = parse_def_(st, NominalType, conv);
     let space = parse_param_space(st);
     assert_eq!(next(st), '|');
     let index = parse_u32(st);
     assert_eq!(next(st), '|');
-    let bounds = parse_bounds(st, |x,y| conv(x,y));
-    let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
+    let bounds = parse_bounds_(st, conv);
+    let default = parse_opt(st, |st| parse_ty_(st, conv));
 
     ty::TypeParameterDef {
         name: name,
@@ -743,12 +841,21 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
     }
 }
 
-fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
-                                     conv: conv_did)
-                                     -> ty::ExistentialBounds<'tcx>
+fn parse_existential_bounds<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
+                                        mut conv: F)
+                                        -> ty::ExistentialBounds<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_existential_bounds_(st, &mut conv)
+}
+
+fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
+                                        conv: &mut F)
+                                        -> 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);
+         parse_bounds_(st, conv);
     assert_eq!(region_bounds.len(), 1);
     assert_eq!(trait_bounds.len(), 0);
     let region_bound = region_bounds.pop().unwrap();
@@ -757,7 +864,15 @@ fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
                                    projection_bounds: projection_bounds };
 }
 
-fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {
+fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    parse_builtin_bounds_(st, &mut _conv)
+}
+
+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();
 
     loop {
@@ -784,9 +899,18 @@ fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {
     }
 }
 
-fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
-                          -> ty::ParamBounds<'tcx> {
-    let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y));
+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 mut param_bounds = ty::ParamBounds {
         region_bounds: Vec::new(),
@@ -798,15 +922,15 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
         match next(st) {
             'R' => {
                 param_bounds.region_bounds.push(
-                    parse_region(st, |x, y| conv (x, y)));
+                    parse_region_(st, conv));
             }
             'I' => {
                 param_bounds.trait_bounds.push(
-                    ty::Binder(parse_trait_ref(st, |x,y| conv(x,y))));
+                    ty::Binder(parse_trait_ref_(st, conv)));
             }
             'P' => {
                 param_bounds.projection_bounds.push(
-                    ty::Binder(parse_projection_predicate(st, |x,y| conv(x,y))));
+                    ty::Binder(parse_projection_predicate_(st, conv)));
             }
             '.' => {
                 return param_bounds;
index 5f0f51ce9033d3b4f9a5ecfda313839e0dfa9423..0042209aced6ad4e17d1392c72e374e9d35f8f34 100644 (file)
@@ -119,10 +119,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
         ty::ty_str => {
             mywrite!(w, "v");
         }
-        ty::ty_closure(ref f) => {
-            mywrite!(w, "f");
-            enc_closure_ty(w, cx, &**f);
-        }
         ty::ty_bare_fn(Some(def_id), f) => {
             mywrite!(w, "F");
             mywrite!(w, "{}|", (cx.ds)(def_id));
index e4d407d66a2ee91db813b8ff572303e0bc668425..93a19a01f668fb26d65d2b8b07ba29c40dfed7fd 100644 (file)
@@ -263,18 +263,27 @@ trait def_id_encoder_helpers {
     fn emit_def_id(&mut self, did: ast::DefId);
 }
 
+#[cfg(stage0)]
 impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
     fn emit_def_id(&mut self, did: ast::DefId) {
         did.encode(self).ok().unwrap()
     }
 }
 
+#[cfg(not(stage0))]
+impl<S:serialize::Encoder> def_id_encoder_helpers for S {
+    fn emit_def_id(&mut self, did: ast::DefId) {
+        did.encode(self).ok().unwrap()
+    }
+}
+
 trait def_id_decoder_helpers {
     fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId;
     fn read_def_id_nodcx(&mut self,
                          cdata: &cstore::crate_metadata) -> ast::DefId;
 }
 
+#[cfg(stage0)]
 impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
     fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
@@ -288,6 +297,20 @@ fn read_def_id_nodcx(&mut self,
     }
 }
 
+#[cfg(not(stage0))]
+impl<D:serialize::Decoder> def_id_decoder_helpers for D {
+    fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId {
+        let did: ast::DefId = Decodable::decode(self).ok().unwrap();
+        did.tr(dcx)
+    }
+
+    fn read_def_id_nodcx(&mut self,
+                         cdata: &cstore::crate_metadata) -> ast::DefId {
+        let did: ast::DefId = Decodable::decode(self).ok().unwrap();
+        decoder::translate_def_id(cdata, did)
+    }
+}
+
 // ______________________________________________________________________
 // Encoding and decoding the AST itself
 //
@@ -1008,13 +1031,6 @@ fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
 
         self.emit_enum("AutoAdjustment", |this| {
             match *adj {
-                ty::AdjustAddEnv(def_id, store) => {
-                    this.emit_enum_variant("AdjustAddEnv", 0, 2, |this| {
-                        this.emit_enum_variant_arg(0, |this| def_id.encode(this));
-                        this.emit_enum_variant_arg(1, |this| store.encode(this))
-                    })
-                }
-
                 ty::AdjustReifyFnPointer(def_id) => {
                     this.emit_enum_variant("AdjustReifyFnPointer", 1, 2, |this| {
                         this.emit_enum_variant_arg(0, |this| def_id.encode(this))
@@ -1655,14 +1671,6 @@ fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
             let variants = ["AutoAddEnv", "AutoDerefRef"];
             this.read_enum_variant(&variants, |this, i| {
                 Ok(match i {
-                    0 => {
-                        let def_id: ast::DefId =
-                            this.read_def_id(dcx);
-                        let store: ty::TraitStore =
-                            this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
-
-                        ty::AdjustAddEnv(def_id, store.tr(dcx))
-                    }
                     1 => {
                         let def_id: ast::DefId =
                             this.read_def_id(dcx);
index ff5175ffdcfb2a3cc73021c9c835cd21db691ec8..de81f307c4d7cfb5286672806ee9f29f784e7a8c 100644 (file)
@@ -509,7 +509,7 @@ fn call<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
         let method_call = ty::MethodCall::expr(call_expr.id);
         let return_ty = ty::ty_fn_ret(match self.tcx.method_map.borrow().get(&method_call) {
             Some(method) => method.ty,
-            None => ty::expr_ty(self.tcx, func_or_rcvr)
+            None => ty::expr_ty_adjusted(self.tcx, func_or_rcvr)
         });
 
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
index 06fef66c1e0033609f053b0e8ca3b6190f3c2c9f..8a2ecbca20d55beab1226c9fa0284a1f9ad83b08 100644 (file)
@@ -60,16 +60,16 @@ fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
 
     fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
         if i == self.cfg.entry {
-            dot::LabelStr("entry".into_cow())
+            dot::LabelText::LabelStr("entry".into_cow())
         } else if i == self.cfg.exit {
-            dot::LabelStr("exit".into_cow())
+            dot::LabelText::LabelStr("exit".into_cow())
         } else if n.data.id == ast::DUMMY_NODE_ID {
-            dot::LabelStr("(dummy_node)".into_cow())
+            dot::LabelText::LabelStr("(dummy_node)".into_cow())
         } else {
             let s = self.ast_map.node_to_string(n.data.id);
             // left-aligns the lines
             let s = replace_newline_with_backslash_l(s);
-            dot::EscStr(s.into_cow())
+            dot::LabelText::EscStr(s.into_cow())
         }
     }
 
@@ -87,7 +87,7 @@ fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
             let s = replace_newline_with_backslash_l(s);
             label.push_str(format!("exiting scope_{} {}", i, s[])[]);
         }
-        dot::EscStr(label.into_cow())
+        dot::LabelText::EscStr(label.into_cow())
     }
 }
 
index 6277656e03afce8e97ec780138c507075cbe03c1..ac53bdbefcf10a4e2d63c37efa7f4a4a9ae83474 100644 (file)
@@ -14,9 +14,7 @@
 use util::ppaux;
 
 use syntax::ast;
-use syntax::ast_util;
-use syntax::visit::Visitor;
-use syntax::visit;
+use syntax::visit::{self, Visitor};
 
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
@@ -37,24 +35,39 @@ fn inside_const<F>(&mut self, f: F) where
     {
         self.with_const(true, f);
     }
-    fn outside_const<F>(&mut self, f: F) where
-        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
-    {
-        self.with_const(false, f);
-    }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
     fn visit_item(&mut self, i: &ast::Item) {
-        check_item(self, i);
+        match i.node {
+            ast::ItemStatic(_, _, ref ex) |
+            ast::ItemConst(_, ref ex) => {
+                self.inside_const(|v| v.visit_expr(&**ex));
+            }
+            ast::ItemEnum(ref enum_definition, _) => {
+                self.inside_const(|v| {
+                    for var in enum_definition.variants.iter() {
+                        if let Some(ref ex) = var.node.disr_expr {
+                            v.visit_expr(&**ex);
+                        }
+                    }
+                });
+            }
+            _ => self.with_const(false, |v| visit::walk_item(v, i))
+        }
     }
     fn visit_pat(&mut self, p: &ast::Pat) {
-        check_pat(self, p);
+        let is_const = match p.node {
+            ast::PatLit(_) | ast::PatRange(..) => true,
+            _ => false
+        };
+        self.with_const(is_const, |v| visit::walk_pat(v, p))
     }
     fn visit_expr(&mut self, ex: &ast::Expr) {
-        if check_expr(self, ex) {
-            visit::walk_expr(self, ex);
+        if self.in_const {
+            check_expr(self, ex);
         }
+        visit::walk_expr(self, ex);
     }
 }
 
@@ -64,57 +77,13 @@ pub fn check_crate(tcx: &ty::ctxt) {
     tcx.sess.abort_if_errors();
 }
 
-fn check_item(v: &mut CheckCrateVisitor, it: &ast::Item) {
-    match it.node {
-        ast::ItemStatic(_, _, ref ex) |
-        ast::ItemConst(_, ref ex) => {
-            v.inside_const(|v| v.visit_expr(&**ex));
-        }
-        ast::ItemEnum(ref enum_definition, _) => {
-            for var in (*enum_definition).variants.iter() {
-                for ex in var.node.disr_expr.iter() {
-                    v.inside_const(|v| v.visit_expr(&**ex));
-                }
-            }
-        }
-        _ => v.outside_const(|v| visit::walk_item(v, it))
-    }
-}
-
-fn check_pat(v: &mut CheckCrateVisitor, p: &ast::Pat) {
-    fn is_str(e: &ast::Expr) -> bool {
-        match e.node {
-            ast::ExprBox(_, ref expr) => {
-                match expr.node {
-                    ast::ExprLit(ref lit) => ast_util::lit_is_str(&**lit),
-                    _ => false,
-                }
-            }
-            _ => false,
-        }
-    }
-    match p.node {
-        // Let through plain ~-string literals here
-        ast::PatLit(ref a) => if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); },
-        ast::PatRange(ref a, ref b) => {
-            if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); }
-            if !is_str(&**b) { v.inside_const(|v| v.visit_expr(&**b)); }
-        }
-        _ => v.outside_const(|v| visit::walk_pat(v, p))
-    }
-}
-
-fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
-    if !v.in_const { return true }
-
+fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
     match e.node {
         ast::ExprUnary(ast::UnDeref, _) => {}
         ast::ExprUnary(ast::UnUniq, _) => {
             span_err!(v.tcx.sess, e.span, E0010,
                       "cannot do allocations in constant expressions");
-            return false;
         }
-        ast::ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {}
         ast::ExprBinary(..) | ast::ExprUnary(..) => {
             let method_call = ty::MethodCall::expr(e.id);
             if v.tcx.method_map.borrow().contains_key(&method_call) {
@@ -123,7 +92,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
                            expressions");
             }
         }
-        ast::ExprLit(_) => (),
+        ast::ExprLit(_) => {}
         ast::ExprCast(ref from, _) => {
             let toty = ty::expr_ty(v.tcx, e);
             let fromty = ty::expr_ty(v.tcx, &**from);
@@ -142,39 +111,23 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
                            expression");
             }
         }
-        ast::ExprPath(ref pth) => {
-            // NB: In the future you might wish to relax this slightly
-            // to handle on-demand instantiation of functions via
-            // foo::<bar> in a const. Currently that is only done on
-            // a path in trans::callee that only works in block contexts.
-            if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
-                span_err!(v.tcx.sess, e.span, E0013,
-                          "paths in constants may only refer to items without \
-                           type parameters");
-            }
-            match v.tcx.def_map.borrow().get(&e.id) {
-                Some(&DefStatic(..)) |
-                Some(&DefConst(..)) |
-                Some(&DefFn(..)) |
-                Some(&DefVariant(_, _, _)) |
-                Some(&DefStruct(_)) => { }
+        ast::ExprPath(_) => {
+            match v.tcx.def_map.borrow()[e.id] {
+                DefStatic(..) | DefConst(..) |
+                DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
+                DefStruct(_) | DefVariant(_, _, _) => {}
 
-                Some(&def) => {
+                def => {
                     debug!("(checking const) found bad def: {}", def);
                     span_err!(v.tcx.sess, e.span, E0014,
                               "paths in constants may only refer to constants \
                                or functions");
                 }
-                None => {
-                    v.tcx.sess.span_bug(e.span, "unbound path in const?!");
-                }
             }
         }
         ast::ExprCall(ref callee, _) => {
-            match v.tcx.def_map.borrow().get(&callee.id) {
-                Some(&DefStruct(..)) |
-                Some(&DefVariant(..)) => {}    // OK.
-
+            match v.tcx.def_map.borrow()[callee.id] {
+                DefStruct(..) | DefVariant(..) => {}    // OK.
                 _ => {
                     span_err!(v.tcx.sess, e.span, E0015,
                               "function calls in constants are limited to \
@@ -190,9 +143,9 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
                               "blocks in constants are limited to items and \
                                tail expressions");
                 match stmt.node {
-                    ast::StmtDecl(ref span, _) => {
-                        match span.node {
-                            ast::DeclLocal(_) => block_span_err(span.span),
+                    ast::StmtDecl(ref decl, _) => {
+                        match decl.node {
+                            ast::DeclLocal(_) => block_span_err(decl.span),
 
                             // Item statements are allowed
                             ast::DeclItem(_) => {}
@@ -206,10 +159,6 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
                     }
                 }
             }
-            match block.expr {
-                Some(ref expr) => { check_expr(v, &**expr); }
-                None => {}
-            }
         }
         ast::ExprVec(_) |
         ast::ExprAddrOf(ast::MutImmutable, _) |
@@ -232,11 +181,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
             }
         }
 
-        _ => {
-            span_err!(v.tcx.sess, e.span, E0019,
-                      "constant contains unimplemented expression type");
-            return false;
-        }
+        _ => span_err!(v.tcx.sess, e.span, E0019,
+                       "constant contains unimplemented expression type")
     }
-    true
 }
index a62b134c48e71d9a1547bb398adffca87641f8d2..a95523f2e06005f3f72af857d4a8bd0dc1e6e788 100644 (file)
@@ -132,7 +132,7 @@ fn variant_expr<'a>(variants: &'a [P<ast::Variant>], id: ast::NodeId)
             None => {}
         }
         let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def,
-            |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
+            box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
             csearch::found(&ast::IIItem(ref item)) => match item.node {
                 ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
                     // NOTE this doesn't do the right thing, it compares inlined
@@ -172,7 +172,7 @@ pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
             None => {}
         }
         let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
-            |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
+            box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
             csearch::found(&ast::IIItem(ref item)) => match item.node {
                 ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
@@ -311,8 +311,8 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
 
         ast::ExprCall(ref callee, ref args) => {
             let def = tcx.def_map.borrow()[callee.id].clone();
-            if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
-               entry.set(def);
+            if let Vacant(entry) = tcx.def_map.borrow_mut().entry(&expr.id) {
+               entry.insert(def);
             }
             let path = match def {
                 def::DefStruct(def_id) => def_to_path(tcx, def_id),
index 5a2085bee24c5f483997f7fa9cf105648a2dec86..2e40bdd001a1748404e5948ceb4375c1771a232b 100644 (file)
@@ -355,7 +355,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemEnum(ref enum_def, _) if allow_dead_code => {
                 self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
             }
-            ast::ItemImpl(_, _, Some(ref _trait_ref), _, ref impl_items) => {
+            ast::ItemImpl(_, _, _, Some(ref _trait_ref), _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         ast::MethodImplItem(ref method) => {
index 1075263e7512de7b34eb77aa71a339f01a24f5ef..f7eea6e5cb7c9cc45da7be1b13ae6c291afd87a2 100644 (file)
@@ -33,7 +33,6 @@ 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::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe,
         _ => false,
     }
 }
index 5b786ec99224723bb254790390f25dd904ee096b..df2a4e4c2532a988616508c89bab76516f8a1c73 100644 (file)
@@ -656,19 +656,6 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
             ty::ty_bare_fn(..) => {
                 self.consume_expr(callee);
             }
-            ty::ty_closure(ref f) => {
-                match f.onceness {
-                    ast::Many => {
-                        self.borrow_expr(callee,
-                                         ty::ReScope(call_scope),
-                                         ty::UniqueImmBorrow,
-                                         ClosureInvocation);
-                    }
-                    ast::Once => {
-                        self.consume_expr(callee);
-                    }
-                }
-            }
             ty::ty_err => { }
             _ => {
                 let overloaded_call_type =
@@ -836,7 +823,6 @@ fn walk_adjustment(&mut self, expr: &ast::Expr) {
             None => { }
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AdjustAddEnv(..) |
                     ty::AdjustReifyFnPointer(..) => {
                         // Creating a closure/fn-pointer consumes the
                         // input and stores it into the resulting
index d42817bce9302a911584a95118aaf5905862bc69..42bc70b5b561fd12b57db8ffd50ea559f078fd16 100644 (file)
@@ -80,9 +80,6 @@ pub fn simplify_type(tcx: &ty::ctxt,
         ty::ty_tup(ref tys) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::ty_closure(ref f) => {
-            Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
-        }
         ty::ty_bare_fn(_, ref f) => {
             Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
         }
index f6f62e035900e0ea9ae06a4a3fbbfa962e539a10..65de3a083d2d9154cb3268df618a033c4e4a283c 100644 (file)
@@ -71,7 +71,6 @@
 use util::ppaux;
 use util::ppaux::Repr;
 
-use syntax::abi;
 use syntax::ast;
 
 // Note: Coerce is not actually a combiner, in that it does not
@@ -160,15 +159,6 @@ pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
                 };
             }
 
-            ty::ty_closure(box ty::ClosureTy {
-                    store: ty::RegionTraitStore(..),
-                    ..
-                }) => {
-                return self.unpack_actual_value(a, |a| {
-                    self.coerce_borrowed_fn(a, b)
-                });
-            }
-
             _ => {}
         }
 
@@ -511,21 +501,6 @@ fn coerce_from_fn_item(&self,
                    a.repr(self.tcx()), b.repr(self.tcx()));
 
             match b.sty {
-                ty::ty_closure(ref f) => {
-                    if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
-                        return self.subtype(a, b);
-                    }
-
-                    let fn_ty_b = (*f).clone();
-                    let adj = ty::AdjustAddEnv(fn_def_id_a, fn_ty_b.store);
-                    let a_closure = ty::mk_closure(self.tcx(),
-                                                   ty::ClosureTy {
-                                                       sig: fn_ty_a.sig.clone(),
-                                                       .. *fn_ty_b
-                                                   });
-                    try!(self.subtype(a_closure, b));
-                    Ok(Some(adj))
-                }
                 ty::ty_bare_fn(None, _) => {
                     let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, fn_ty_a);
                     try!(self.subtype(a_fn_pointer, b));
index 29507058761154952096e908b058d2d19de6a4e2..dd711fcbf022eed6d76a7d49e45db83b026d6795 100644 (file)
@@ -644,12 +644,6 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
             Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
         }
 
-      (&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => {
-        this.closure_tys(&**a_fty, &**b_fty).and_then(|fty| {
-            Ok(ty::mk_closure(tcx, fty))
-        })
-      }
-
       (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
           let projection_ty = try!(this.projection_tys(a_data, b_data));
           Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
index 7ff585087f508eb3e12635a51f08b6f2fdc5c109..e58ff53b00cb9f91c3e644f39075e4a70a9d9166 100644 (file)
@@ -66,7 +66,8 @@
 use super::region_inference::ConcreteFailure;
 use super::region_inference::SubSupConflict;
 use super::region_inference::SupSupConflict;
-use super::region_inference::ParamBoundFailure;
+use super::region_inference::GenericBoundFailure;
+use super::region_inference::GenericKind;
 use super::region_inference::ProcessedErrors;
 use super::region_inference::SameRegions;
 
@@ -120,11 +121,11 @@ fn report_concrete_failure(&self,
                                sub: Region,
                                sup: Region);
 
-    fn report_param_bound_failure(&self,
-                                  origin: SubregionOrigin<'tcx>,
-                                  param_ty: ty::ParamTy,
-                                  sub: Region,
-                                  sups: Vec<Region>);
+    fn report_generic_bound_failure(&self,
+                                    origin: SubregionOrigin<'tcx>,
+                                    kind: GenericKind<'tcx>,
+                                    sub: Region,
+                                    sups: Vec<Region>);
 
     fn report_sub_sup_conflict(&self,
                                var_origin: RegionVariableOrigin,
@@ -175,8 +176,8 @@ fn report_region_errors(&self,
                     self.report_concrete_failure(origin, sub, sup);
                 }
 
-                ParamBoundFailure(origin, param_ty, sub, sups) => {
-                    self.report_param_bound_failure(origin, param_ty, sub, sups);
+                GenericBoundFailure(kind, param_ty, sub, sups) => {
+                    self.report_generic_bound_failure(kind, param_ty, sub, sups);
                 }
 
                 SubSupConflict(var_origin,
@@ -421,30 +422,35 @@ fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
                      found.user_string(self.tcx)))
     }
 
-    fn report_param_bound_failure(&self,
-                                  origin: SubregionOrigin<'tcx>,
-                                  param_ty: ty::ParamTy,
-                                  sub: Region,
-                                  _sups: Vec<Region>) {
-
+    fn report_generic_bound_failure(&self,
+                                    origin: SubregionOrigin<'tcx>,
+                                    bound_kind: GenericKind<'tcx>,
+                                    sub: Region,
+                                    _sups: Vec<Region>)
+    {
         // FIXME: it would be better to report the first error message
         // with the span of the parameter itself, rather than the span
         // where the error was detected. But that span is not readily
         // accessible.
 
+        let labeled_user_string = match bound_kind {
+            GenericKind::Param(ref p) =>
+                format!("the parameter type `{}`", p.user_string(self.tcx)),
+            GenericKind::Projection(ref p) =>
+                format!("the associated type `{}`", p.user_string(self.tcx)),
+        };
+
         match sub {
             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
                 // Does the required lifetime have a nice name we can print?
                 self.tcx.sess.span_err(
                     origin.span(),
-                    format!(
-                        "the parameter type `{}` may not live long enough",
-                        param_ty.user_string(self.tcx))[]);
+                    format!("{} may not live long enough", labeled_user_string)[]);
                 self.tcx.sess.span_help(
                     origin.span(),
                     format!(
                         "consider adding an explicit lifetime bound `{}: {}`...",
-                        param_ty.user_string(self.tcx),
+                        bound_kind.user_string(self.tcx),
                         sub.user_string(self.tcx))[]);
             }
 
@@ -452,14 +458,12 @@ fn report_param_bound_failure(&self,
                 // Does the required lifetime have a nice name we can print?
                 self.tcx.sess.span_err(
                     origin.span(),
-                    format!(
-                        "the parameter type `{}` may not live long enough",
-                        param_ty.user_string(self.tcx))[]);
+                    format!("{} may not live long enough", labeled_user_string)[]);
                 self.tcx.sess.span_help(
                     origin.span(),
                     format!(
                         "consider adding an explicit lifetime bound `{}: 'static`...",
-                        param_ty.user_string(self.tcx))[]);
+                        bound_kind.user_string(self.tcx))[]);
             }
 
             _ => {
@@ -467,17 +471,16 @@ fn report_param_bound_failure(&self,
                 self.tcx.sess.span_err(
                     origin.span(),
                     format!(
-                        "the parameter type `{}` may not live long enough",
-                        param_ty.user_string(self.tcx))[]);
+                        "{} may not live long enough",
+                        labeled_user_string)[]);
                 self.tcx.sess.span_help(
                     origin.span(),
                     format!(
-                        "consider adding an explicit lifetime bound to `{}`",
-                        param_ty.user_string(self.tcx))[]);
+                        "consider adding an explicit lifetime bound for `{}`",
+                        bound_kind.user_string(self.tcx))[]);
                 note_and_explain_region(
                     self.tcx,
-                    format!("the parameter type `{}` must be valid for ",
-                            param_ty.user_string(self.tcx))[],
+                    format!("{} must be valid for ", labeled_user_string)[],
                     sub,
                     "...");
             }
@@ -1712,7 +1715,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
         match tcx.map.find(parent) {
             Some(node) => match node {
                 ast_map::NodeItem(item) => match item.node {
-                    ast::ItemImpl(_, ref gen, _, _, _) => {
+                    ast::ItemImpl(_, _, ref gen, _, _, _) => {
                         taken.push_all(gen.lifetimes.as_slice());
                     }
                     _ => ()
index 0ae4a3d851e7ffaf341760b7ddc561bf0ee671b7..608ae31475327e4b3430336fef69183f1e1b1583 100644 (file)
@@ -66,13 +66,13 @@ fn freshen<F>(&mut self,
             None => { }
         }
 
-        match self.freshen_map.entry(key) {
+        match self.freshen_map.entry(&key) {
             Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
                 let index = self.freshen_count;
                 self.freshen_count += 1;
                 let t = ty::mk_infer(self.infcx.tcx, freshener(index));
-                entry.set(t);
+                entry.insert(t);
                 t
             }
         }
@@ -152,7 +152,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::ty_ptr(..) |
             ty::ty_rptr(..) |
             ty::ty_bare_fn(..) |
-            ty::ty_closure(..) |
             ty::ty_trait(..) |
             ty::ty_struct(..) |
             ty::ty_unboxed_closure(..) |
index e1401898f7a79582985ff1a1ccd667ca9785f4c2..c2db81d311483b5e72d57be2921e26f39ce176bd 100644 (file)
@@ -20,6 +20,7 @@
 pub use self::fixup_err::*;
 pub use middle::ty::IntVarValue;
 pub use self::freshen::TypeFreshener;
+pub use self::region_inference::GenericKind;
 
 use middle::subst;
 use middle::subst::Substs;
@@ -382,19 +383,6 @@ pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
     cx.region_vars.commit(snapshot);
 }
 
-pub fn verify_param_bound<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                                    origin: SubregionOrigin<'tcx>,
-                                    param_ty: ty::ParamTy,
-                                    a: ty::Region,
-                                    bs: Vec<ty::Region>) {
-    debug!("verify_param_bound({}, {} <: {})",
-           param_ty.repr(cx.tcx),
-           a.repr(cx.tcx),
-           bs.repr(cx.tcx));
-
-    cx.region_vars.verify_param_bound(origin, param_ty, a, bs);
-}
-
 pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                          a_is_expected: bool,
                          origin: TypeOrigin,
@@ -1070,6 +1058,20 @@ pub fn replace_late_bound_regions_with_fresh_var<T>(
             value,
             |br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
     }
+
+    /// See `verify_generic_bound` method in `region_inference`
+    pub fn verify_generic_bound(&self,
+                                origin: SubregionOrigin<'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));
+
+        self.region_vars.verify_generic_bound(origin, kind, a, bs);
+    }
 }
 
 impl<'tcx> TypeTrace<'tcx> {
index 2bf32e7bdaedee05b6d5f7e0a41b2c8ccfa1182b..98c69962bc288b6732ab1951c698d068fe10f5dd 100644 (file)
@@ -137,8 +137,8 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
         let mut node_ids = FnvHashMap::new();
         {
             let mut add_node = |&mut : node| {
-                if let Vacant(e) = node_ids.entry(node) {
-                    e.set(i);
+                if let Vacant(e) = node_ids.entry(&node) {
+                    e.insert(i);
                     i += 1;
                 }
             };
index f0ee63c08e8b60a86f1cd6a7c5a354d37536133f..23e96dafa611bf9074fb6116e77540cad52ce795 100644 (file)
@@ -22,7 +22,7 @@
 use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
 
 use middle::region;
-use middle::ty;
+use middle::ty::{mod, Ty};
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
 use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
 use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
@@ -30,7 +30,7 @@
 use middle::graph::{Direction, NodeIndex};
 use util::common::indenter;
 use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux::Repr;
+use util::ppaux::{Repr, UserString};
 
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering::{self, Less, Greater, Equal};
@@ -61,12 +61,18 @@ pub enum Verify<'tcx> {
     // `b` are inference variables.
     VerifyRegSubReg(SubregionOrigin<'tcx>, Region, Region),
 
-    // VerifyParamBound(T, _, R, RS): The parameter type `T` must
-    // outlive the region `R`. `T` is known to outlive `RS`. Therefore
-    // verify that `R <= RS[i]` for some `i`. Inference variables may
-    // be involved (but this verification step doesn't influence
-    // inference).
-    VerifyParamBound(ty::ParamTy, SubregionOrigin<'tcx>, Region, Vec<Region>),
+    // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
+    // associated type) must outlive the region `R`. `T` is known to
+    // outlive `RS`. Therefore verify that `R <= RS[i]` for some
+    // `i`. Inference variables may be involved (but this verification
+    // step doesn't influence inference).
+    VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec<Region>),
+}
+
+#[deriving(Clone, Show, PartialEq, Eq)]
+pub enum GenericKind<'tcx> {
+    Param(ty::ParamTy),
+    Projection(ty::ProjectionTy<'tcx>),
 }
 
 #[derive(Copy, PartialEq, Eq, Hash)]
@@ -98,12 +104,12 @@ pub enum RegionResolutionError<'tcx> {
     /// `o` requires that `a <= b`, but this does not hold
     ConcreteFailure(SubregionOrigin<'tcx>, Region, Region),
 
-    /// `ParamBoundFailure(p, s, a, bs)
+    /// `GenericBoundFailure(p, s, a, bs)
     ///
-    /// The parameter type `p` must be known to outlive the lifetime
+    /// The parameter/assocated-type `p` must be known to outlive the lifetime
     /// `a`, but it is only known to outlive `bs` (and none of the
     /// regions in `bs` outlive `a`).
-    ParamBoundFailure(SubregionOrigin<'tcx>, ty::ParamTy, Region, Vec<Region>),
+    GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec<Region>),
 
     /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
     ///
@@ -489,12 +495,13 @@ pub fn make_subregion(&self,
         }
     }
 
-    pub fn verify_param_bound(&self,
-                              origin: SubregionOrigin<'tcx>,
-                              param_ty: ty::ParamTy,
-                              sub: Region,
-                              sups: Vec<Region>) {
-        self.add_verify(VerifyParamBound(param_ty, origin, sub, sups));
+    /// See `Verify::VerifyGenericBound`
+    pub fn verify_generic_bound(&self,
+                                origin: SubregionOrigin<'tcx>,
+                                kind: GenericKind<'tcx>,
+                                sub: Region,
+                                sups: Vec<Region>) {
+        self.add_verify(VerifyGenericBound(kind, origin, sub, sups));
     }
 
     pub fn lub_regions(&self,
@@ -660,7 +667,7 @@ pub fn tainted(&self, mark: &RegionSnapshot, r0: Region) -> Vec<Region> {
                                     &mut result_set, r,
                                     a, b);
                             }
-                            VerifyParamBound(_, _, a, ref bs) => {
+                            VerifyGenericBound(_, _, a, ref bs) => {
                                 for &b in bs.iter() {
                                     consider_adding_bidirectional_edges(
                                         &mut result_set, r,
@@ -1211,7 +1218,7 @@ fn collect_concrete_region_errors(&self,
                     errors.push(ConcreteFailure((*origin).clone(), sub, sup));
                 }
 
-                VerifyParamBound(ref param_ty, ref origin, sub, ref sups) => {
+                VerifyGenericBound(ref kind, ref origin, sub, ref sups) => {
                     let sub = normalize(values, sub);
                     if sups.iter()
                            .map(|&sup| normalize(values, sup))
@@ -1223,8 +1230,8 @@ fn collect_concrete_region_errors(&self,
                     let sups = sups.iter().map(|&sup| normalize(values, sup))
                                           .collect();
                     errors.push(
-                        ParamBoundFailure(
-                            (*origin).clone(), *param_ty, sub, sups));
+                        GenericBoundFailure(
+                            (*origin).clone(), kind.clone(), sub, sups));
                 }
             }
         }
@@ -1584,8 +1591,8 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
             VerifyRegSubReg(_, ref a, ref b) => {
                 format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx))
             }
-            VerifyParamBound(_, ref p, ref a, ref bs) => {
-                format!("VerifyParamBound({}, {}, {})",
+            VerifyGenericBound(_, ref p, ref a, ref bs) => {
+                format!("VerifyGenericBound({}, {}, {})",
                         p.repr(tcx), a.repr(tcx), bs.repr(tcx))
             }
         }
@@ -1624,3 +1631,32 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
                 self.origin.repr(tcx))
     }
 }
+
+impl<'tcx> Repr<'tcx> for GenericKind<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        match *self {
+            GenericKind::Param(ref p) => p.repr(tcx),
+            GenericKind::Projection(ref p) => p.repr(tcx),
+        }
+    }
+}
+
+impl<'tcx> UserString<'tcx> for GenericKind<'tcx> {
+    fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        match *self {
+            GenericKind::Param(ref p) => p.user_string(tcx),
+            GenericKind::Projection(ref p) => p.user_string(tcx),
+        }
+    }
+}
+
+impl<'tcx> GenericKind<'tcx> {
+    pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        match *self {
+            GenericKind::Param(ref p) =>
+                p.to_ty(tcx),
+            GenericKind::Projection(ref p) =>
+                ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name),
+        }
+    }
+}
index 75d5b4fd7f932dcefec592aeb3c832b87e696357..77875139be3a3fd5f22d9436a019b44afaba3971 100644 (file)
@@ -1149,7 +1149,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
           ast::ExprCall(ref f, ref args) => {
             let diverges = !self.ir.tcx.is_method_call(expr.id) && {
-                let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, &**f));
+                let t_ret = ty::ty_fn_ret(ty::expr_ty_adjusted(self.ir.tcx, &**f));
                 t_ret == ty::FnDiverging
             };
             let succ = if diverges {
index 8325cebf1ed75e80403aeb4339244855232b3947..dd61db4270ce3499bf2642edd8779d37a38578fa 100644 (file)
@@ -197,8 +197,7 @@ pub enum deref_kind {
 // pointer adjustment).
 pub fn deref_kind(t: Ty) -> McResult<deref_kind> {
     match t.sty {
-        ty::ty_uniq(_) |
-        ty::ty_closure(box ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
+        ty::ty_uniq(_) => {
             Ok(deref_ptr(Unique))
         }
 
@@ -207,13 +206,6 @@ pub fn deref_kind(t: Ty) -> McResult<deref_kind> {
             Ok(deref_ptr(BorrowedPtr(kind, *r)))
         }
 
-        ty::ty_closure(box ty::ClosureTy {
-                store: ty::RegionTraitStore(r, _),
-                ..
-            }) => {
-            Ok(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
-        }
-
         ty::ty_ptr(ref mt) => {
             Ok(deref_ptr(UnsafePtr(mt.mutbl)))
         }
@@ -421,8 +413,8 @@ pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
 
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AdjustAddEnv(..) | ty::AdjustReifyFnPointer(..) => {
-                        debug!("cat_expr(AdjustAddEnv|AdjustReifyFnPointer): {}",
+                    ty::AdjustReifyFnPointer(..) => {
+                        debug!("cat_expr(AdjustReifyFnPointer): {}",
                                expr.repr(self.tcx()));
                         // Convert a bare fn to a closure by adding NULL env.
                         // Result is an rvalue.
@@ -559,14 +551,14 @@ pub fn cat_def(&self,
                id, expr_ty.repr(self.tcx()), def);
 
         match def {
-          def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
-          def::DefStaticMethod(..) | def::DefConst(..) => {
+          def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
+          def::DefFn(..) | def::DefStaticMethod(..) |  def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
           def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
           def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
-          def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
+          def::DefLabel(_) | def::DefSelfTy(..) |
           def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
               Ok(Rc::new(cmt_ {
                   id:id,
@@ -592,25 +584,6 @@ pub fn cat_def(&self,
           def::DefUpvar(var_id, fn_node_id, _) => {
               let ty = try!(self.node_ty(fn_node_id));
               match ty.sty {
-                  ty::ty_closure(ref closure_ty) => {
-                      // Translate old closure type info into unboxed
-                      // closure kind/capture mode
-                      let (mode, kind) = match (closure_ty.store, closure_ty.onceness) {
-                          // stack closure
-                          (ty::RegionTraitStore(..), ast::Many) => {
-                              (ast::CaptureByRef, ty::FnMutUnboxedClosureKind)
-                          }
-                          // proc or once closure
-                          (_, ast::Once) => {
-                              (ast::CaptureByValue, ty::FnOnceUnboxedClosureKind)
-                          }
-                          // There should be no such old closure type
-                          (ty::UniqTraitStore, ast::Many) => {
-                              self.tcx().sess.span_bug(span, "Impossible closure type");
-                          }
-                      };
-                      self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, false)
-                  }
                   ty::ty_unboxed_closure(closure_id, _, _) => {
                       let kind = self.typer.unboxed_closure_kind(closure_id);
                       let mode = self.typer.capture_mode(fn_node_id);
index e6665699b7b7bd7ca06a68dba0413ce469e3fba9..50e328ef0e3c35b9f4be4ec026fcc9c841ce25c1 100644 (file)
@@ -287,7 +287,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             //   undefined symbols at linkage time if this case is not handled.
             //
             // * Private trait impls for private types can be completely ignored
-            ast::ItemImpl(_, _, _, ref ty, ref impl_items) => {
+            ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
                     ast::TyPath(_, id) => {
                         match self.tcx.def_map.borrow()[id].clone() {
@@ -657,7 +657,7 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId,
                     // invoked, and the struct/enum itself is private. Crawl
                     // back up the chains to find the relevant struct/enum that
                     // was private.
-                    ast::ItemImpl(_, _, _, ref ty, _) => {
+                    ast::ItemImpl(_, _, _, _, ref ty, _) => {
                         let id = match ty.node {
                             ast::TyPath(_, id) => id,
                             _ => return Some((err_span, err_msg, None)),
@@ -750,7 +750,7 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
         debug!("privacy - path {}", self.nodestr(path_id));
         let orig_def = self.tcx.def_map.borrow()[path_id].clone();
         let ck = |&: tyname: &str| {
-            let ck_public = |def: ast::DefId| {
+            let ck_public = |&: def: ast::DefId| {
                 let name = token::get_ident(path.segments.last().unwrap().identifier);
                 let origdid = orig_def.def_id();
                 self.ensure_public(span,
@@ -1137,7 +1137,7 @@ fn check_sane_privacy(&self, item: &ast::Item) {
         match item.node {
             // implementations of traits don't need visibility qualifiers because
             // that's controlled by having the trait in scope.
-            ast::ItemImpl(_, _, Some(..), _, ref impl_items) => {
+            ast::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
                 check_inherited(item.span, item.vis,
                                 "visibility qualifiers have no effect on trait \
                                  impls");
@@ -1216,7 +1216,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
         };
         check_inherited(tcx, item.span, item.vis);
         match item.node {
-            ast::ItemImpl(_, _, _, _, ref impl_items) => {
+            ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         ast::MethodImplItem(ref m) => {
@@ -1361,7 +1361,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible.
-            ast::ItemImpl(_, ref g, ref trait_ref, ref self_, ref impl_items) => {
+            ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // impl [... for] Public<...>, but not `impl [... for]
index 4d83075480bcc0877dda9a089efeb2a46c6fa19c..5736e3072862aadc9b195f79e8829970cb9439f2 100644 (file)
@@ -55,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
     }
 
     match item.node {
-        ast::ItemImpl(_, ref generics, _, _, _) |
+        ast::ItemImpl(_, _, ref generics, _, _, _) |
         ast::ItemFn(_, _, _, ref generics, _) => {
             generics_require_inlining(generics)
         }
@@ -216,7 +216,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
                                       .map
                                       .expect_item(impl_did.node)
                                       .node {
-                                ast::ItemImpl(_, ref generics, _, _, _) => {
+                                ast::ItemImpl(_, _, ref generics, _, _, _) => {
                                     generics_require_inlining(generics)
                                 }
                                 _ => false
index 5eb033a01bd5862bd361b36b67d14201a42d38ff..68cb8ca39b492c323c833f5a1069daaa05cf05c0 100644 (file)
@@ -106,7 +106,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                 ast::ItemEnum(_, ref generics) |
                 ast::ItemStruct(_, ref generics) |
                 ast::ItemTrait(_, ref generics, _, _) |
-                ast::ItemImpl(_, ref generics, _, _, _) => {
+                ast::ItemImpl(_, _, ref generics, _, _, _) => {
                     // These kinds of items have only early bound lifetime parameters.
                     let lifetimes = &generics.lifetimes;
                     let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
@@ -136,18 +136,6 @@ fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
 
     fn visit_ty(&mut self, ty: &ast::Ty) {
         match ty.node {
-            ast::TyClosure(ref c)  => {
-                // Careful, the bounds on a closure/proc are *not* within its binder.
-                visit::walk_ty_param_bounds_helper(self, &c.bounds);
-                visit::walk_lifetime_decls_helper(self, &c.lifetimes);
-                self.with(LateScope(&c.lifetimes, self.scope), |old_scope, this| {
-                    this.check_lifetime_defs(old_scope, &c.lifetimes);
-                    for argument in c.decl.inputs.iter() {
-                        this.visit_ty(&*argument.ty)
-                    }
-                    visit::walk_fn_ret_ty(this, &c.decl.output);
-                });
-            }
             ast::TyBareFn(ref c) => {
                 visit::walk_lifetime_decls_helper(self, &c.lifetimes);
                 self.with(LateScope(&c.lifetimes, self.scope), |old_scope, this| {
index 505352fa1234462801e06c5d95abbece2acce6d7..362d5fedaa376f7463d235e7255947d0df1db1cb 100644 (file)
@@ -82,7 +82,7 @@ fn visit_item(&mut self, i: &Item) {
         // stability of the trait. This is WRONG, but expedient to get
         // libstd stabilized for the 1.0 release.
         let use_parent = match i.node {
-            ast::ItemImpl(_, _, Some(_), _, _) => false,
+            ast::ItemImpl(_, _, _, Some(_), _, _) => false,
             _ => true,
         };
 
index e6805cddae05aab1c9a26432c422ada8424a194d..55abe895183f1ba69b195846fca35bea20f51850 100644 (file)
@@ -118,7 +118,6 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::ty_float(..) |
         ty::ty_str(..) |
         ty::ty_bare_fn(..) |
-        ty::ty_closure(..) |
         ty::ty_vec(..) |
         ty::ty_ptr(..) |
         ty::ty_rptr(..) |
index 8bb7012fb075cbaed45fd423712f064e5de2dbdd..c2327adece8e04dc274e6df1ad68fbfe6a6b2469 100644 (file)
@@ -437,8 +437,9 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("register_region_obligation({})",
            region_obligation.repr(tcx));
 
-    match region_obligations.entry(region_obligation.cause.body_id) {
-        Vacant(entry) => { entry.set(vec![region_obligation]); },
+    let body_id = region_obligation.cause.body_id;
+    match region_obligations.entry(&body_id) {
+        Vacant(entry) => { entry.insert(vec![region_obligation]); },
         Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
     }
 
index d5b41d238062890f21d32306e03e2036b4868d8d..65f7ad296db519855ac5cd625d79f7b11c972db7 100644 (file)
@@ -643,11 +643,12 @@ fn confirm_candidate<'cx,'tcx>(
             match impl_ty {
                 Some(ty) => (ty, impl_vtable.nested.to_vec()),
                 None => {
-                    selcx.tcx().sess.span_bug(
-                        obligation.cause.span,
-                        format!("impl `{}` did not contain projection for `{}`",
-                                impl_vtable.repr(selcx.tcx()),
-                                obligation.repr(selcx.tcx())).as_slice());
+                    // 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!())
                 }
             }
         }
index f499cf61301aa9be5d96fc5570e7434aff99b44e..2393b7d733d0000ae9c1e001a801eaf0fc67f1fb 100644 (file)
@@ -1273,62 +1273,6 @@ fn builtin_bound(&mut self,
                 }
             }
 
-            ty::ty_closure(ref c) => {
-                match c.store {
-                    ty::UniqTraitStore => {
-                        // proc: Equivalent to `Box<FnOnce>`
-                        match bound {
-                            ty::BoundCopy => {
-                                Err(Unimplemented)
-                            }
-
-                            ty::BoundSized => {
-                                Ok(If(Vec::new()))
-                            }
-
-                            ty::BoundSync |
-                            ty::BoundSend => {
-                                if c.bounds.builtin_bounds.contains(&bound) {
-                                    Ok(If(Vec::new()))
-                                } else {
-                                    Err(Unimplemented)
-                                }
-                            }
-                        }
-                    }
-                    ty::RegionTraitStore(_, mutbl) => {
-                        // ||: Equivalent to `&FnMut` or `&mut FnMut` or something like that.
-                        match bound {
-                            ty::BoundCopy => {
-                                match mutbl {
-                                    ast::MutMutable => {
-                                        // &mut T is affine
-                                        Err(Unimplemented)
-                                    }
-                                    ast::MutImmutable => {
-                                        // &T is copyable, no matter what T is
-                                        Ok(If(Vec::new()))
-                                    }
-                                }
-                            }
-
-                            ty::BoundSized => {
-                                Ok(If(Vec::new()))
-                            }
-
-                            ty::BoundSync |
-                            ty::BoundSend => {
-                                if c.bounds.builtin_bounds.contains(&bound) {
-                                    Ok(If(Vec::new()))
-                                } else {
-                                    Err(Unimplemented)
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
             ty::ty_trait(ref data) => {
                 match bound {
                     ty::BoundSized => {
index d168e84a01ccdb514bdf310f2f4b06c8c99559fe..291bb4c982058df82cb96ae044c97de0b73d20ae 100644 (file)
@@ -78,7 +78,6 @@
 use std::rc::Rc;
 use collections::enum_set::{EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
@@ -294,7 +293,6 @@ pub enum Variance {
 
 #[derive(Clone, Show)]
 pub enum AutoAdjustment<'tcx> {
-    AdjustAddEnv(ast::DefId, ty::TraitStore),
     AdjustReifyFnPointer(ast::DefId), // go from a fn-item type to a fn-pointer type
     AdjustDerefRef(AutoDerefRef<'tcx>)
 }
@@ -917,7 +915,7 @@ 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_closure, ty_trait,
+            ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
             ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
@@ -1354,7 +1352,6 @@ pub enum sty<'tcx> {
     // fn item. Otherwise, if None(_), it a fn pointer type.
     ty_bare_fn(Option<DefId>, &'tcx BareFnTy<'tcx>),
 
-    ty_closure(Box<ClosureTy<'tcx>>),
     ty_trait(Box<TyTrait<'tcx>>),
     ty_struct(DefId, &'tcx Substs<'tcx>),
 
@@ -1779,6 +1776,10 @@ pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
         !self.regions.is_empty_in(space)
     }
 
+    pub fn is_empty(&self) -> bool {
+        self.types.is_empty() && self.regions.is_empty()
+    }
+
     pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
                      -> GenericBounds<'tcx> {
         GenericBounds {
@@ -2595,14 +2596,6 @@ fn add_sty(&mut self, st: &sty) {
             &ty_bare_fn(_, ref f) => {
                 self.add_fn_sig(&f.sig);
             }
-
-            &ty_closure(ref f) => {
-                if let RegionTraitStore(r, _) = f.store {
-                    self.add_region(r);
-                }
-                self.add_fn_sig(&f.sig);
-                self.add_bounds(&f.bounds);
-            }
         }
     }
 
@@ -2749,10 +2742,6 @@ pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
     mk_tup(cx, Vec::new())
 }
 
-pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_closure(box fty))
-}
-
 pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
                         opt_def_id: Option<ast::DefId>,
                         fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
@@ -3029,7 +3018,7 @@ pub fn type_is_vec(ty: Ty) -> bool {
 
 pub fn type_is_structural(ty: Ty) -> bool {
     match ty.sty {
-      ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
+      ty_struct(..) | ty_tup(_) | ty_enum(..) |
       ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
       _ => type_is_slice(ty) | type_is_trait(ty)
     }
@@ -3346,10 +3335,6 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 TC::None
             }
 
-            ty_closure(ref c) => {
-                closure_contents(&**c) | TC::ReachesFfiUnsafe
-            }
-
             ty_uniq(typ) => {
                 TC::ReachesFfiUnsafe | match typ.sty {
                     ty_str => TC::OwnsOwned,
@@ -3520,23 +3505,6 @@ fn borrowed_contents(region: ty::Region,
         b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
     }
 
-    fn closure_contents(cty: &ClosureTy) -> TypeContents {
-        // Closure contents are just like trait contents, but with potentially
-        // even more stuff.
-        let st = object_contents(&cty.bounds);
-
-        let st = match cty.store {
-            UniqTraitStore => {
-                st.owned_pointer()
-            }
-            RegionTraitStore(r, mutbl) => {
-                st.reference(borrowed_contents(r, mutbl))
-            }
-        };
-
-        st
-    }
-
     fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
         // These are the type contents of the (opaque) interior. We
         // make no assumptions (other than that it cannot have an
@@ -3650,7 +3618,6 @@ fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
             ty_float(_) |
             ty_str |
             ty_bare_fn(..) |
-            ty_closure(_) |
             ty_param(_) |
             ty_projection(_) |
             ty_vec(_, None) => {
@@ -4154,7 +4121,6 @@ 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,
-        ty_closure(ref f) => f.sig.0.variadic,
         ref s => {
             panic!("fn_is_variadic() called on non-fn type: {}", s)
         }
@@ -4164,7 +4130,6 @@ 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,
-        ty_closure(ref f) => &f.sig,
         ref s => {
             panic!("ty_fn_sig() called on non-fn type: {}", s)
         }
@@ -4175,7 +4140,6 @@ pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
 pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
     match fty.sty {
         ty_bare_fn(_, ref f) => f.abi,
-        ty_closure(ref f) => f.abi,
         _ => panic!("ty_fn_abi() called on non-fn type"),
     }
 }
@@ -4187,7 +4151,6 @@ pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> &'tcx [Ty<'tcx>] {
 
 pub fn ty_closure_store(fty: Ty) -> TraitStore {
     match fty.sty {
-        ty_closure(ref f) => f.store,
         ty_unboxed_closure(..) => {
             // Close enough for the purposes of all the callers of this
             // function (which is soon to be deprecated anyhow).
@@ -4202,7 +4165,6 @@ pub fn ty_closure_store(fty: Ty) -> TraitStore {
 pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
     match fty.sty {
         ty_bare_fn(_, ref f) => f.sig.0.output,
-        ty_closure(ref f) => f.sig.0.output,
         ref s => {
             panic!("ty_fn_ret() called on non-fn type: {}", s)
         }
@@ -4212,7 +4174,6 @@ pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
 pub fn is_fn_ty(fty: Ty) -> bool {
     match fty.sty {
         ty_bare_fn(..) => true,
-        ty_closure(_) => true,
         _ => false
     }
 }
@@ -4336,33 +4297,6 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
     return match adjustment {
         Some(adjustment) => {
             match *adjustment {
-                AdjustAddEnv(_, store) => {
-                    match unadjusted_ty.sty {
-                        ty::ty_bare_fn(Some(_), ref b) => {
-                            let bounds = ty::ExistentialBounds {
-                                region_bound: ReStatic,
-                                builtin_bounds: all_builtin_bounds(),
-                                projection_bounds: vec!(),
-                            };
-
-                            ty::mk_closure(
-                                cx,
-                                ty::ClosureTy {unsafety: b.unsafety,
-                                               onceness: ast::Many,
-                                               store: store,
-                                               bounds: bounds,
-                                               sig: b.sig.clone(),
-                                               abi: b.abi})
-                        }
-                        ref b => {
-                            cx.sess.bug(
-                                format!("add_env adjustment on non-fn-item: \
-                                         {}",
-                                        b).as_slice());
-                        }
-                    }
-                }
-
                 AdjustReifyFnPointer(_) => {
                     match unadjusted_ty.sty {
                         ty::ty_bare_fn(Some(_), b) => {
@@ -4732,7 +4666,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         ty_rptr(_, _) => "&-ptr".to_string(),
         ty_bare_fn(Some(_), _) => format!("fn item"),
         ty_bare_fn(None, _) => "fn pointer".to_string(),
-        ty_closure(_) => "fn".to_string(),
         ty_trait(ref inner) => {
             format!("trait {}", item_path_str(cx, inner.principal_def_id()))
         }
@@ -5128,7 +5061,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
             match cx.map.find(id.node) {
                 Some(ast_map::NodeItem(item)) => {
                     match item.node {
-                        ast::ItemImpl(_, _, ref opt_trait, _, _) => {
+                        ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
                             match opt_trait {
                                 &Some(ref t) => {
                                     let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
@@ -5651,10 +5584,8 @@ pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
         node_id_to_type(tcx, id.node)
     } else {
         let mut tcache = tcx.tcache.borrow_mut();
-        let pty = match tcache.entry(id) {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
-        };
+        let pty = tcache.entry(&id).get().unwrap_or_else(
+            |vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id)));
         pty.ty
     };
     ty.subst(tcx, substs)
@@ -6329,24 +6260,6 @@ fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, state: &mut sip::SipS
                     fn_sig(state, &b.sig);
                     return false;
                 }
-                ty_closure(ref c) => {
-                    byte!(15);
-                    hash!(c.unsafety);
-                    hash!(c.onceness);
-                    hash!(c.bounds);
-                    match c.store {
-                        UniqTraitStore => byte!(0),
-                        RegionTraitStore(r, m) => {
-                            byte!(1);
-                            region(state, r);
-                            assert_eq!(m, ast::MutMutable);
-                        }
-                    }
-
-                    fn_sig(state, &c.sig);
-
-                    return false;
-                }
                 ty_trait(ref data) => {
                     byte!(17);
                     did(state, data.principal_def_id());
@@ -6669,12 +6582,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
             ty_struct(_, substs) => {
                 accum_substs(accumulator, substs);
             }
-            ty_closure(ref closure_ty) => {
-                match closure_ty.store {
-                    RegionTraitStore(region, _) => accumulator.push(region),
-                    UniqTraitStore => {}
-                }
-            }
             ty_unboxed_closure(_, region, substs) => {
                 accumulator.push(*region);
                 accum_substs(accumulator, substs);
@@ -6744,7 +6651,6 @@ pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
 impl<'tcx> AutoAdjustment<'tcx> {
     pub fn is_identity(&self) -> bool {
         match *self {
-            AdjustAddEnv(..) => false,
             AdjustReifyFnPointer(..) => false,
             AdjustDerefRef(ref r) => r.is_identity(),
         }
@@ -6841,10 +6747,8 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
         debug!("region={}", region.repr(tcx));
         match region {
             ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
-                * match map.entry(br) {
-                    Vacant(entry) => entry.set(mapf(br, debruijn)),
-                    Occupied(entry) => entry.into_mut(),
-                }
+                * map.entry(&br).get().unwrap_or_else(
+                      |vacant_entry| vacant_entry.insert(mapf(br, debruijn)))
             }
             _ => {
                 region
@@ -6870,11 +6774,8 @@ pub fn shifted(&self, amount: u32) -> DebruijnIndex {
 impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         match *self {
-            AdjustAddEnv(def_id, ref trait_store) => {
-                format!("AdjustAddEnv({},{})", def_id.repr(tcx), trait_store)
-            }
             AdjustReifyFnPointer(def_id) => {
-                format!("AdjustAddEnv({})", def_id.repr(tcx))
+                format!("AdjustReifyFnPointer({})", def_id.repr(tcx))
             }
             AdjustDerefRef(ref data) => {
                 data.repr(tcx)
index 9a66b98ee5841918d35c091111febeafdf91ed09..1bc0d70945899eacea45d77c05ff91fc5103546c 100644 (file)
@@ -70,6 +70,13 @@ fn enter_region_binder(&mut self) { }
     /// track the Debruijn index nesting level.
     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>
+    {
+        // FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`.
+        super_fold_binder(self, t)
+    }
+
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         super_fold_ty(self, t)
     }
@@ -183,12 +190,9 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
     }
 }
 
-impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
+impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
-        folder.enter_region_binder();
-        let result = ty::Binder(self.0.fold_with(folder));
-        folder.exit_region_binder();
-        result
+        folder.fold_binder(self)
     }
 }
 
@@ -556,6 +560,17 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpv
 //
 // They should invoke `foo.fold_with()` to do recursive folding.
 
+pub fn super_fold_binder<'tcx, T, U>(this: &mut T,
+                                     binder: &ty::Binder<U>)
+                                     -> ty::Binder<U>
+    where T : TypeFolder<'tcx>, U : TypeFoldable<'tcx>
+{
+    this.enter_region_binder();
+    let result = ty::Binder(binder.0.fold_with(this));
+    this.exit_region_binder();
+    result
+}
+
 pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
                                                 ty: Ty<'tcx>)
                                                 -> Ty<'tcx> {
@@ -589,9 +604,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             let bfn = f.fold_with(this);
             ty::ty_bare_fn(opt_def_id, this.tcx().mk_bare_fn(bfn))
         }
-        ty::ty_closure(ref f) => {
-            ty::ty_closure(f.fold_with(this))
-        }
         ty::ty_rptr(r, ref tm) => {
             let r = r.fold_with(this);
             ty::ty_rptr(this.tcx().mk_region(r), tm.fold_with(this))
index 6070a4208f663709a3d0d3ae03eafea13cd1edea..4953e9a2ce1d16eee8b4003fdd388945c84078fa 100644 (file)
@@ -51,9 +51,6 @@ fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) {
             ty::ty_bare_fn(_, ref ft) => {
                 self.push_sig_subtypes(&ft.sig);
             }
-            ty::ty_closure(ref ft) => {
-                self.push_sig_subtypes(&ft.sig);
-            }
         }
     }
 
index 1480ff016b53ddbed73e5bead8c540f6fa8eec9d..138f648049c73f748e6937474f7e94ff38054148 100644 (file)
@@ -105,6 +105,7 @@ pub struct Options {
     pub prints: Vec<PrintRequest>,
     pub cg: CodegenOptions,
     pub color: ColorConfig,
+    pub show_span: Option<String>,
     pub externs: HashMap<String, Vec<String>>,
     pub crate_name: Option<String>,
     /// An optional name to use as the crate for std during std injection,
@@ -211,6 +212,7 @@ pub fn basic_options() -> Options {
         prints: Vec::new(),
         cg: basic_codegen_options(),
         color: Auto,
+        show_span: None,
         externs: HashMap::new(),
         crate_name: None,
         alt_std_name: None,
@@ -259,7 +261,6 @@ macro_rules! debugging_opts {
         BORROWCK_STATS,
         NO_LANDING_PADS,
         DEBUG_LLVM,
-        SHOW_SPAN,
         COUNT_TYPE_SIZES,
         META_STATS,
         GC,
@@ -299,7 +300,6 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
      ("no-landing-pads", "omit landing pads for unwinding",
       NO_LANDING_PADS),
      ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
-     ("show-span", "show spans for compiler debugging", SHOW_SPAN),
      ("count-type-sizes", "count the sizes of aggregate types",
       COUNT_TYPE_SIZES),
      ("meta-stats", "gather metadata statistics", META_STATS),
@@ -754,7 +754,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                  "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
         opt::multi("", "print", "Comma separated list of compiler information to \
                                print on stdout",
-                 "[crate-name|output-file-names|sysroot]"),
+                 "[crate-name|file-names|sysroot]"),
         opt::flag("g",  "",  "Equivalent to -C debuginfo=2"),
         opt::flag("O", "", "Equivalent to -C opt-level=2"),
         opt::opt("o", "", "Write output to <filename>", "FILENAME"),
@@ -823,6 +823,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                       `flowgraph=<nodeid>` (graphviz formatted flowgraph for node), or
                       `everybody_loops` (all function bodies replaced with `loop {}`).",
                      "TYPE"),
+        opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"),
         opt::flagopt("", "dep-info",
                  "Output dependency info to <filename> after compiling, \
                   in a format suitable for use by Makefiles", "FILENAME"),
@@ -1114,8 +1115,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
             None => early_error("--extern value must be of the format `foo=bar`"),
         };
 
-        match externs.entry(name.to_string()) {
-            Vacant(entry) => { entry.set(vec![location.to_string()]); },
+        match externs.entry(&name.to_string()) {
+            Vacant(entry) => { entry.insert(vec![location.to_string()]); },
             Occupied(mut entry) => { entry.get_mut().push(location.to_string()); },
         }
     }
@@ -1143,6 +1144,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         prints: prints,
         cg: cg,
         color: color,
+        show_span: None,
         externs: externs,
         crate_name: crate_name,
         alt_std_name: None,
index 770e8d73ec7614f70ceb16982a5bdd7f9838f72a..abb780615ae7b8170f6f8801dd660e3368417683 100644 (file)
@@ -201,8 +201,8 @@ pub fn lto(&self) -> bool {
     pub fn no_landing_pads(&self) -> bool {
         self.debugging_opt(config::NO_LANDING_PADS)
     }
-    pub fn show_span(&self) -> bool {
-        self.debugging_opt(config::SHOW_SPAN)
+    pub fn unstable_options(&self) -> bool {
+        self.debugging_opt(config::UNSTABLE_OPTIONS)
     }
     pub fn print_enum_sizes(&self) -> bool {
         self.debugging_opt(config::PRINT_ENUM_SIZES)
index 9639af5ca1cd53ec49789ac81ed9f31d5fd64d6e..e6ee16d1789c00fbd401f20ab5fd472b52e34e5c 100644 (file)
@@ -18,7 +18,7 @@
 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, ty_closure};
+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, ty_open};
 use middle::ty::{ty_unboxed_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
@@ -417,9 +417,6 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
                 strs => format!("({})", strs.connect(", "))
             }
         }
-        ty_closure(ref f) => {
-            closure_to_string(cx, &**f)
-        }
         ty_bare_fn(opt_def_id, ref f) => {
             bare_fn_to_string(cx, opt_def_id, f.unsafety, f.abi, None, &f.sig)
         }
index 75545634b40cf689a72597e9d339ba37e6bdadf0..e1f0c9ec26677abef3eb817672c78b396bfc8686 100644 (file)
@@ -662,13 +662,6 @@ fn move_suggestion<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
                                     default_msgs: (&'static str, &'static str))
                                     -> (&'static str, &'static str) {
             match ty.sty {
-                ty::ty_closure(box ty::ClosureTy {
-                    store: ty::RegionTraitStore(..),
-                    ..
-                }) => {
-                    ("a non-copyable stack closure",
-                     "capture it in a new closure, e.g. `|x| f(x)`, to override")
-                }
                 _ => {
                     if ty::type_moves_by_default(param_env, span, ty) {
                         ("non-copyable",
index 388cbf2f18b7ca142f01cb482cd8d80ae28827d5..f2c35851d0d7c6484429951d9b799a0a78fff425 100644 (file)
@@ -137,8 +137,8 @@ fn node_label(&'a self, n: &Node<'a>) -> dot::LabelText<'a> {
         let suffix = self.dataflow_for(dataflow::Exit, n);
         let inner_label = self.inner.node_label(n);
         inner_label
-            .prefix_line(dot::LabelStr(prefix.into_cow()))
-            .suffix_line(dot::LabelStr(suffix.into_cow()))
+            .prefix_line(dot::LabelText::LabelStr(prefix.into_cow()))
+            .suffix_line(dot::LabelText::LabelStr(suffix.into_cow()))
     }
     fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) }
 }
index 1455aa3c99bb3680403e7a33897672319d1187cf..f5c29a6b30b3069f7fe9f02859cc033d44ddf451 100644 (file)
@@ -146,8 +146,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
         println!("{}", json::as_json(&krate));
     }
 
-    if sess.show_span() {
-        syntax::show_span::run(sess.diagnostic(), &krate);
+    if let Some(ref s) = sess.opts.show_span {
+        syntax::show_span::run(sess.diagnostic(), s.as_slice(), &krate);
     }
 
     krate
@@ -572,7 +572,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool {
         debug!("invoked with --parse-only, returning early from compile_input");
         return true;
     }
-    if sess.show_span() {
+    if sess.opts.show_span.is_some() {
         return true;
     }
     return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
@@ -638,7 +638,7 @@ fn write_out_deps(sess: &Session,
         _ => return,
     };
 
-    let result = (|| -> io::IoResult<()> {
+    let result = (|&:| -> io::IoResult<()> {
         // Build a list of files used to compile the output and
         // write Makefile-compatible dependency rules
         let files: Vec<String> = sess.codemap().files.borrow()
index 9a993de098ea427176b28289d478006dcae3839c..2e8cde658904cc3304c08207c88871537cf98e0d 100644 (file)
@@ -54,7 +54,6 @@
 use rustc::metadata;
 use rustc::DIAGNOSTICS;
 
-use std::any::AnyRefExt;
 use std::cmp::Ordering::Equal;
 use std::io;
 use std::iter::repeat;
@@ -135,7 +134,7 @@ fn run_compiler(args: &[String]) {
         _ => early_error("multiple input filenames provided")
     };
 
-    let sess = build_session(sopts, input_file_path, descriptions);
+    let mut sess = build_session(sopts, input_file_path, descriptions);
     let cfg = config::build_configuration(&sess);
     if print_crate_info(&sess, Some(&input), &odir, &ofile) {
         return
@@ -146,7 +145,7 @@ fn run_compiler(args: &[String]) {
         pretty::parse_pretty(&sess, a.as_slice(), false)
     });
     let pretty = if pretty.is_none() &&
-        sess.debugging_opt(config::UNSTABLE_OPTIONS) {
+        sess.unstable_options() {
             matches.opt_str("xpretty").map(|a| {
                 // extended with unstable pretty-print variants
                 pretty::parse_pretty(&sess, a.as_slice(), true)
@@ -163,6 +162,10 @@ fn run_compiler(args: &[String]) {
         None => {/* continue */ }
     }
 
+    if sess.unstable_options() {
+        sess.opts.show_span = matches.opt_str("show-span");
+    }
+
     let r = matches.opt_strs("Z");
     if r.contains(&("ls".to_string())) {
         match input {
index ab41ade576a5898c4dd3f3dda73a54ff672974d4..b1e65dce6045a592200f44e9d29cd5f760e09447 100644 (file)
@@ -277,26 +277,6 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
         ty::mk_tup(self.infcx.tcx, vec![ty1, ty2])
     }
 
-    pub fn t_closure(&self,
-                     input_tys: &[Ty<'tcx>],
-                     output_ty: Ty<'tcx>,
-                     region_bound: ty::Region)
-                     -> Ty<'tcx>
-    {
-        ty::mk_closure(self.infcx.tcx, ty::ClosureTy {
-            unsafety: ast::Unsafety::Normal,
-            onceness: ast::Many,
-            store: ty::RegionTraitStore(region_bound, ast::MutMutable),
-            bounds: ty::region_existential_bound(region_bound),
-            sig: ty::Binder(ty::FnSig {
-                inputs: input_tys.to_vec(),
-                output: ty::FnConverging(output_ty),
-                variadic: false,
-            }),
-            abi: abi::Rust,
-        })
-    }
-
     pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
         ty::mk_param(self.infcx.tcx, space, index, token::intern(name[]))
@@ -780,19 +760,6 @@ fn escaping() {
         assert!(!ty::type_has_escaping_regions(t_param));
         let t_fn = env.t_fn(&[t_param], env.t_nil());
         assert!(!ty::type_has_escaping_regions(t_fn));
-
-        // t_fn = |&int|+'a
-        let t_fn = env.t_closure(&[t_rptr_bound1], env.t_nil(), env.re_free(0, 1));
-        assert!(!ty::type_has_escaping_regions(t_fn));
-
-        // t_fn = |&int|+'a (where &int has depth 2)
-        let t_fn = env.t_closure(&[t_rptr_bound2], env.t_nil(), env.re_free(0, 1));
-        assert!(ty::type_has_escaping_regions(t_fn));
-
-        // t_fn = |&int|+&int
-        let t_fn = env.t_closure(&[t_rptr_bound1], env.t_nil(),
-                                 env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1)));
-        assert!(ty::type_has_escaping_regions(t_fn));
     })
 }
 
index 53992d4567a34915148e2c9e87957e05cbc81517..d3555e4c0436354055399d04ab1cbb2f58995c97 100644 (file)
@@ -13,7 +13,7 @@
 use libc;
 use ArchiveRef;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::mem;
 use std::raw;
 
@@ -30,9 +30,8 @@ impl ArchiveRO {
     /// raised.
     pub fn open(dst: &Path) -> Option<ArchiveRO> {
         unsafe {
-            let ar = dst.with_c_str(|dst| {
-                ::LLVMRustOpenArchive(dst)
-            });
+            let s = CString::from_slice(dst.as_vec());
+            let ar = ::LLVMRustOpenArchive(s.as_ptr());
             if ar.is_null() {
                 None
             } else {
@@ -45,9 +44,9 @@ pub fn open(dst: &Path) -> Option<ArchiveRO> {
     pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
         unsafe {
             let mut size = 0 as libc::size_t;
-            let ptr = file.with_c_str(|file| {
-                ::LLVMRustArchiveReadSection(self.ptr, file, &mut size)
-            });
+            let file = CString::from_slice(file.as_bytes());
+            let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
+                                                   &mut size);
             if ptr.is_null() {
                 None
             } else {
index 2ec5f37634afb35474c708bae64d1e8e9538d023..854ac5ff5c01cafedf48cc71c1cb8ad6f35d996e 100644 (file)
@@ -47,7 +47,7 @@
 pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::RefCell;
 use std::{raw, mem};
 use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
@@ -2114,10 +2114,9 @@ fn drop(&mut self) {
 }
 
 pub fn mk_target_data(string_rep: &str) -> TargetData {
+    let string_rep = CString::from_slice(string_rep.as_bytes());
     TargetData {
-        lltd: string_rep.with_c_str(|buf| {
-            unsafe { LLVMCreateTargetData(buf) }
-        })
+        lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
     }
 }
 
index d7c1a4fe17b2fa200509dad0332536fcde2eb1fd..10788f9f7cb83e67c296651d0273dc7c22af7161 100644 (file)
@@ -386,7 +386,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 parent.clone()
             }
 
-            ItemImpl(_, _, None, ref ty, ref impl_items) => {
+            ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
                 // If this implements an anonymous trait, then add all the
                 // methods within to a new module, if the type was defined
                 // within this module.
@@ -527,7 +527,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 parent.clone()
             }
 
-            ItemImpl(_, _, Some(_), _, _) => parent.clone(),
+            ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
 
             ItemTrait(_, _, _, ref items) => {
                 let name_bindings =
index 3be7aa294f17a759ae795ec02a5d0e630747382c..a2c86c3cdb7563a71a0e0905cd469c141ef67596 100644 (file)
@@ -71,7 +71,7 @@
 use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit};
 use syntax::ast::{RegionTyParamBound, StructField};
 use syntax::ast::{TraitRef, TraitTyParamBound};
-use syntax::ast::{Ty, TyBool, TyChar, TyClosure, TyF32};
+use syntax::ast::{Ty, TyBool, TyChar, TyF32};
 use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
 use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath};
 use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
@@ -972,7 +972,6 @@ fn new(session: &'a Session,
         }
     }
 
-
     // Import resolution
     //
     // This is a fixed-point algorithm. We resolve imports until our efforts
@@ -1688,15 +1687,11 @@ fn merge_import_resolution(&mut self,
         let is_public = import_directive.is_public;
 
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        let dest_import_resolution = match import_resolutions.entry(name) {
-            Occupied(entry) => {
-                entry.into_mut()
-            }
-            Vacant(entry) => {
+        let dest_import_resolution = import_resolutions.entry(&name).get().unwrap_or_else(
+            |vacant_entry| {
                 // Create a new import resolution from this child.
-                entry.set(ImportResolution::new(id, is_public))
-            }
-        };
+                vacant_entry.insert(ImportResolution::new(id, is_public))
+            });
 
         debug!("(resolving glob import) writing resolution `{}` in `{}` \
                to `{}`",
@@ -2630,16 +2625,16 @@ fn upvarify(&self,
                             def = DefUpvar(node_id, function_id, last_proc_body_id);
 
                             let mut seen = self.freevars_seen.borrow_mut();
-                            let seen = match seen.entry(function_id) {
+                            let seen = match seen.entry(&function_id) {
                                 Occupied(v) => v.into_mut(),
-                                Vacant(v) => v.set(NodeSet::new()),
+                                Vacant(v) => v.insert(NodeSet::new()),
                             };
                             if seen.contains(&node_id) {
                                 continue;
                             }
-                            match self.freevars.borrow_mut().entry(function_id) {
+                            match self.freevars.borrow_mut().entry(&function_id) {
                                 Occupied(v) => v.into_mut(),
-                                Vacant(v) => v.set(vec![]),
+                                Vacant(v) => v.insert(vec![]),
                             }.push(Freevar { def: prev_def, span: span });
                             seen.insert(node_id);
                         }
@@ -2841,7 +2836,7 @@ fn resolve_item(&mut self, item: &Item) {
                 });
             }
 
-            ItemImpl(_,
+            ItemImpl(_, _,
                      ref generics,
                      ref implemented_traits,
                      ref self_type,
@@ -3611,14 +3606,6 @@ fn resolve_type(&mut self, ty: &Ty) {
                 self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
             }
 
-            TyClosure(ref c) => {
-                self.resolve_type_parameter_bounds(
-                    ty.id,
-                    &c.bounds,
-                    TraitBoundingTypeParameter);
-                visit::walk_ty(self, ty);
-            }
-
             TyPolyTraitRef(ref bounds) => {
                 self.resolve_type_parameter_bounds(
                     ty.id,
@@ -4722,7 +4709,7 @@ fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
                 "Import should only be used for `use` directives");
         self.last_private.insert(node_id, lp);
 
-        match self.def_map.borrow_mut().entry(node_id) {
+        match self.def_map.borrow_mut().entry(&node_id) {
             // Resolve appears to "resolve" the same ID multiple
             // times, so here is a sanity check it at least comes to
             // the same conclusion! - nmatsakis
@@ -4734,7 +4721,7 @@ fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
                                  *entry.get(),
                                  def)[]);
             },
-            Vacant(entry) => { entry.set(def); },
+            Vacant(entry) => { entry.insert(def); },
         }
     }
 
index c6488ec6638a3efe83d1a199c0d87277c592d5c0..f3e90c43a8414961bcdb979fb15f9dbada402d85 100644 (file)
@@ -20,7 +20,7 @@
 use libc;
 use flate;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::iter;
 use std::mem;
 use std::num::Int;
@@ -139,9 +139,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     }
 
     // Internalize everything but the reachable symbols of the current module
-    let cstrs: Vec<::std::c_str::CString> =
-        reachable.iter().map(|s| s.to_c_str()).collect();
-    let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
+    let cstrs: Vec<CString> = reachable.iter().map(|s| {
+        CString::from_slice(s.as_bytes())
+    }).collect();
+    let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
     let ptr = arr.as_ptr();
     unsafe {
         llvm::LLVMRustRunRestrictionPass(llmod,
@@ -164,7 +165,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     unsafe {
         let pm = llvm::LLVMCreatePassManager();
         llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
-        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+        llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
         let builder = llvm::LLVMPassManagerBuilderCreate();
         llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
@@ -172,7 +173,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
             /* RunInliner = */ True);
         llvm::LLVMPassManagerBuilderDispose(builder);
 
-        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+        llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
         time(sess.time_passes(), "LTO passes", (), |()|
              llvm::LLVMRunPassManager(pm, llmod));
index 33011d9e35c106b959033561f4c63b88e7fed919..089d7f737d3cf4703376bc9c4901c4d322fe38ea 100644 (file)
@@ -22,7 +22,7 @@
 use syntax::diagnostic;
 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
 
-use std::c_str::{ToCStr, CString};
+use std::ffi::{mod, CString};
 use std::io::Command;
 use std::io::fs;
 use std::iter::Unfold;
@@ -32,7 +32,7 @@
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::channel;
 use std::thread;
-use libc::{c_uint, c_int, c_void};
+use libc::{mod, c_uint, c_int, c_void};
 
 #[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
 pub enum OutputType {
@@ -49,8 +49,9 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
         if cstr == ptr::null() {
             handler.fatal(msg[]);
         } else {
-            let err = CString::new(cstr, true);
-            let err = String::from_utf8_lossy(err.as_bytes());
+            let err = ffi::c_str_to_bytes(&cstr);
+            let err = String::from_utf8_lossy(err.as_slice()).to_string();
+            libc::free(cstr as *mut _);
             handler.fatal(format!("{}: {}",
                                   msg[],
                                   err[])[]);
@@ -66,13 +67,12 @@ pub fn write_output_file(
         output: &Path,
         file_type: llvm::FileType) {
     unsafe {
-        output.with_c_str(|output| {
-            let result = llvm::LLVMRustWriteOutputFile(
-                    target, pm, m, output, file_type);
-            if !result {
-                llvm_err(handler, "could not write output".to_string());
-            }
-        })
+        let output = CString::from_slice(output.as_vec());
+        let result = llvm::LLVMRustWriteOutputFile(
+                target, pm, m, output.as_ptr(), file_type);
+        if !result {
+            llvm_err(handler, "could not write output".to_string());
+        }
     }
 }
 
@@ -221,28 +221,25 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let triple = sess.target.target.llvm_target[];
 
     let tm = unsafe {
-        triple.with_c_str(|t| {
-            let cpu = match sess.opts.cg.target_cpu {
-                Some(ref s) => s[],
-                None => sess.target.target.options.cpu[]
-            };
-            cpu.with_c_str(|cpu| {
-                target_feature(sess).with_c_str(|features| {
-                    llvm::LLVMRustCreateTargetMachine(
-                        t, cpu, features,
-                        code_model,
-                        reloc_model,
-                        opt_level,
-                        true /* EnableSegstk */,
-                        use_softfp,
-                        no_fp_elim,
-                        !any_library && reloc_model == llvm::RelocPIC,
-                        ffunction_sections,
-                        fdata_sections,
-                    )
-                })
-            })
-        })
+        let triple = CString::from_slice(triple.as_bytes());
+        let cpu = match sess.opts.cg.target_cpu {
+            Some(ref s) => s.as_slice(),
+            None => sess.target.target.options.cpu.as_slice()
+        };
+        let cpu = CString::from_slice(cpu.as_bytes());
+        let features = CString::from_slice(target_feature(sess).as_bytes());
+        llvm::LLVMRustCreateTargetMachine(
+            triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
+            code_model,
+            reloc_model,
+            opt_level,
+            true /* EnableSegstk */,
+            use_softfp,
+            no_fp_elim,
+            !any_library && reloc_model == llvm::RelocPIC,
+            ffunction_sections,
+            fdata_sections,
+        )
     };
 
     if tm.is_null() {
@@ -371,8 +368,9 @@ struct HandlerFreeVars<'a> {
 
     match llvm::diagnostic::Diagnostic::unpack(info) {
         llvm::diagnostic::Optimization(opt) => {
-            let pass_name = CString::new(opt.pass_name, false);
-            let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
+            let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+                                .ok()
+                                .expect("got a non-UTF8 pass name from LLVM");
             let enabled = match cgcx.remark {
                 AllPasses => true,
                 SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
@@ -416,9 +414,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
     if config.emit_no_opt_bc {
         let ext = format!("{}.no-opt.bc", name_extra);
-        output_names.with_extension(ext[]).with_c_str(|buf| {
-            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-        })
+        let out = output_names.with_extension(ext.as_slice());
+        let out = CString::from_slice(out.as_vec());
+        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
     }
 
     match config.opt_level {
@@ -433,7 +431,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             // If we're verifying or linting, add them to the function pass
             // manager.
             let addpass = |&: pass: &str| {
-                pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
+                let pass = CString::from_slice(pass.as_bytes());
+                llvm::LLVMRustAddPass(fpm, pass.as_ptr())
             };
             if !config.no_verify { assert!(addpass("verify")); }
 
@@ -445,12 +444,11 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             }
 
             for pass in config.passes.iter() {
-                pass.with_c_str(|s| {
-                    if !llvm::LLVMRustAddPass(mpm, s) {
-                        cgcx.handler.warn(format!("unknown pass {}, ignoring",
-                                                  *pass)[]);
-                    }
-                })
+                let pass = CString::from_slice(pass.as_bytes());
+                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
+                    cgcx.handler.warn(format!("unknown pass {}, ignoring",
+                                              pass).as_slice());
+                }
             }
 
             // Finally, run the actual optimization passes
@@ -470,9 +468,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
                     if config.emit_lto_bc {
                         let name = format!("{}.lto.bc", name_extra);
-                        output_names.with_extension(name[]).with_c_str(|buf| {
-                            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-                        })
+                        let out = output_names.with_extension(name.as_slice());
+                        let out = CString::from_slice(out.as_vec());
+                        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
                     }
                 },
                 _ => {},
@@ -504,18 +502,18 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
 
     if config.emit_bc {
         let ext = format!("{}.bc", name_extra);
-        output_names.with_extension(ext[]).with_c_str(|buf| {
-            llvm::LLVMWriteBitcodeToFile(llmod, buf);
-        })
+        let out = output_names.with_extension(ext.as_slice());
+        let out = CString::from_slice(out.as_vec());
+        llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
     }
 
     time(config.time_passes, "codegen passes", (), |()| {
         if config.emit_ir {
             let ext = format!("{}.ll", name_extra);
-            output_names.with_extension(ext[]).with_c_str(|output| {
-                with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    llvm::LLVMRustPrintModule(cpm, llmod, output);
-                })
+            let out = output_names.with_extension(ext.as_slice());
+            let out = CString::from_slice(out.as_vec());
+            with_codegen(tm, llmod, config.no_builtins, |cpm| {
+                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
             })
         }
 
@@ -995,7 +993,7 @@ unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_args = Vec::new();
     {
         let mut add = |&mut : arg: &str| {
-            let s = arg.to_c_str();
+            let s = CString::from_slice(arg.as_bytes());
             llvm_args.push(s.as_ptr());
             llvm_c_strs.push(s);
         };
@@ -1083,7 +1081,7 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
 
     match opt {
         llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
-            "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
+            llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
         }
         _ => {}
     };
index 55bdff819101182f7145c6b24b2f4ecc801e68f4..8e6276b61f949eecfe4afdae958965bcfc5d63e7 100644 (file)
@@ -283,7 +283,7 @@ fn process_method(&mut self, method: &ast::Method) {
                 NodeItem(item) => {
                     scope_id = item.id;
                     match item.node {
-                        ast::ItemImpl(_, _, _, ref ty, _) => {
+                        ast::ItemImpl(_, _, _, _, ref ty, _) => {
                             let mut result = String::from_str("<");
                             result.push_str(ty_to_string(&**ty)[]);
 
@@ -1040,7 +1040,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                 self.process_const(item, &**typ, &**expr),
             ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            ast::ItemImpl(_,
+            ast::ItemImpl(_, _,
                           ref ty_params,
                           ref trait_ref,
                           ref typ,
index 223df5d3a57855dc6e366e875515e4b442b452a7..01b47b728b6ba7410f71e9723ae463c3024579d6 100644 (file)
@@ -355,12 +355,6 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
         // Functions are just pointers
         ty::ty_bare_fn(..) => Some(path),
 
-        // Closures are a pair of pointers: the code and environment
-        ty::ty_closure(..) => {
-            path.push(FAT_PTR_ADDR);
-            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() => {
             let nonzero_fields = ty::lookup_struct_fields(tcx, did);
index 5597e112f76d1727f05d08a1febd1a599d1bb023..f18d483f70328bd3389cdc527f445b729c6247ff 100644 (file)
@@ -20,9 +20,8 @@
 use trans::type_of;
 use trans::type_::Type;
 
-use std::c_str::ToCStr;
-use std::string::String;
 use syntax::ast;
+use std::ffi::CString;
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
@@ -121,18 +120,16 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         ast::AsmIntel => llvm::AD_Intel
     };
 
-    let r = ia.asm.get().with_c_str(|a| {
-        constraints.with_c_str(|c| {
-            InlineAsmCall(bcx,
-                          a,
-                          c,
-                          inputs[],
+    let asm = CString::from_slice(ia.asm.get().as_bytes());
+    let constraints = CString::from_slice(constraints.as_bytes());
+    let r = InlineAsmCall(bcx,
+                          asm.as_ptr(),
+                          constraints.as_ptr(),
+                          inputs.as_slice(),
                           output_type,
                           ia.volatile,
                           ia.alignstack,
-                          dialect)
-        })
-    });
+                          dialect);
 
     // Again, based on how many outputs we have
     if num_outputs == 1 {
index 58cb2ebd2566c6990e92f66456cea71e30575d2d..7031710c679add12782d359e1f07ee807e7a98ac 100644 (file)
 
 use arena::TypedArena;
 use libc::{c_uint, uint64_t};
-use std::c_str::ToCStr;
+use std::ffi::{mod, CString};
 use std::cell::{Cell, RefCell};
 use std::collections::HashSet;
 use std::mem;
 use std::rc::Rc;
+use std::str;
 use std::{i8, i16, i32, i64};
 use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
 use syntax::ast_util::local_def;
@@ -187,11 +188,10 @@ fn drop(&mut self) {
 pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
                ty: Type, output: ty::FnOutput) -> ValueRef {
 
-    let llfn: ValueRef = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf, ty.to_ref())
-        }
-    });
+    let buf = CString::from_slice(name.as_bytes());
+    let llfn: ValueRef = unsafe {
+        llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
+    };
 
     // diverging functions may unwind, but can never return normally
     if output == ty::FnDiverging {
@@ -287,9 +287,6 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ty::ty_bare_fn(_, ref f) => {
             (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, None)
         }
-        ty::ty_closure(ref f) => {
-            (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, Some(Type::i8p(ccx)))
-        }
         ty::ty_unboxed_closure(closure_did, _, substs) => {
             let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
             let function_type = typer.unboxed_closure_type(closure_did, substs);
@@ -334,9 +331,8 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
         None => ()
     }
     unsafe {
-        let c = name.with_c_str(|buf| {
-            llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf)
-        });
+        let buf = CString::from_slice(name.as_bytes());
+        let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
         // Thread-local statics in some other crate need to *always* be linked
         // against in a thread-local fashion, so we need to be sure to apply the
         // thread-local attribute locally if it was present remotely. If we
@@ -475,15 +471,17 @@ pub fn set_always_inline(f: ValueRef) {
 }
 
 pub fn set_split_stack(f: ValueRef) {
-    "split-stack".with_c_str(|buf| {
-        unsafe { llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
-    })
+    unsafe {
+        llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+                                        "split-stack\0".as_ptr() as *const _);
+    }
 }
 
 pub fn unset_split_stack(f: ValueRef) {
-    "split-stack".with_c_str(|buf| {
-        unsafe { llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
-    })
+    unsafe {
+        llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+                                           "split-stack\0".as_ptr() as *const _);
+    }
 }
 
 // Double-check that we never ask LLVM to declare the same symbol twice. It
@@ -511,7 +509,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Since we're in trans we don't care for any region parameters
         let substs = subst::Substs::erased(substs.types.clone());
 
-        let (val, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
+        let (val, _, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
 
         val
     } else if did.krate == ast::LOCAL_CRATE {
@@ -537,11 +535,8 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 // Structural comparison: a rather involved form of glue.
 pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
     if cx.sess().opts.cg.save_temps {
-        s.with_c_str(|buf| {
-            unsafe {
-                llvm::LLVMSetValueName(v, buf)
-            }
-        })
+        let buf = CString::from_slice(s.as_bytes());
+        unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) }
     }
 }
 
@@ -669,30 +664,31 @@ pub fn compare_simd_types<'blk, 'tcx>(
     }
 }
 
-pub type val_and_ty_fn<'a, 'blk, 'tcx> =
-    |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'blk, 'tcx>;
-
 // Iterates through the elements of a structural type.
-pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
-                                          av: ValueRef,
-                                          t: Ty<'tcx>,
-                                          f: val_and_ty_fn<'a, 'blk, 'tcx>)
-                                          -> Block<'blk, 'tcx> {
+pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
+                                         av: ValueRef,
+                                         t: Ty<'tcx>,
+                                         mut f: F)
+                                         -> Block<'blk, 'tcx> where
+    F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
+{
     let _icx = push_ctxt("iter_structural_ty");
 
-    fn iter_variant<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
-                                    repr: &adt::Repr<'tcx>,
-                                    av: ValueRef,
-                                    variant: &ty::VariantInfo<'tcx>,
-                                    substs: &subst::Substs<'tcx>,
-                                    f: val_and_ty_fn<'a, 'blk, 'tcx>)
-                                    -> Block<'blk, 'tcx> {
+    fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
+                                   repr: &adt::Repr<'tcx>,
+                                   av: ValueRef,
+                                   variant: &ty::VariantInfo<'tcx>,
+                                   substs: &subst::Substs<'tcx>,
+                                   f: &mut F)
+                                   -> Block<'blk, 'tcx> where
+        F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
+    {
         let _icx = push_ctxt("iter_variant");
         let tcx = cx.tcx();
         let mut cx = cx;
 
         for (i, &arg) in variant.args.iter().enumerate() {
-            cx = f(cx,
+            cx = (*f)(cx,
                    adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
                    arg.subst(tcx, substs));
         }
@@ -764,7 +760,7 @@ fn iter_variant<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
           match adt::trans_switch(cx, &*repr, av) {
               (_match::Single, None) => {
                   cx = iter_variant(cx, &*repr, av, &*(*variants)[0],
-                                    substs, f);
+                                    substs, &mut f);
               }
               (_match::Switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, cx.tcx().types.int);
@@ -793,7 +789,7 @@ fn iter_variant<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                        data_ptr,
                                        &**variant,
                                        substs,
-                                       |x,y,z| f(x,y,z));
+                                       &mut f);
                       Br(variant_cx, next_cx.llbb);
                   }
                   cx = next_cx;
@@ -951,9 +947,6 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ty::ty_closure(_) => {
-            get_extern_rust_fn(ccx, t, name[], did)
-        }
         _ => {
             get_extern_const(ccx, did, t)
         }
@@ -2317,7 +2310,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         let mut v = TransItemVisitor{ ccx: ccx };
         v.visit_block(&**body);
       }
-      ast::ItemImpl(_, ref generics, _, _, ref impl_items) => {
+      ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
         meth::trans_impl(ccx,
                          item.ident,
                          impl_items[],
@@ -2437,7 +2430,6 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
     use middle::ty::{BrAnon, ReLateBound};
 
     let (fn_sig, abi, has_env) = match fn_ty.sty {
-        ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
         ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false),
         ty::ty_unboxed_closure(closure_did, _, substs) => {
             let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
@@ -2645,11 +2637,10 @@ fn create_entry_fn(ccx: &CrateContext,
             unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
         }
 
-        let llbb = "top".with_c_str(|buf| {
-            unsafe {
-                llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, buf)
-            }
-        });
+        let llbb = unsafe {
+            llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn,
+                                                "top\0".as_ptr() as *const _)
+        };
         let bld = ccx.raw_builder();
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
@@ -2670,9 +2661,9 @@ fn create_entry_fn(ccx: &CrateContext,
                 };
 
                 let args = {
-                    let opaque_rust_main = "rust_main".with_c_str(|buf| {
-                        llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf)
-                    });
+                    let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
+                        rust_main, Type::i8p(ccx).to_ref(),
+                        "rust_main\0".as_ptr() as *const _);
 
                     vec!(
                         opaque_rust_main,
@@ -2779,9 +2770,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                 format!("Illegal null byte in export_name \
                                          value: `{}`", sym)[]);
                         }
-                        let g = sym.with_c_str(|buf| {
-                            llvm::LLVMAddGlobal(ccx.llmod(), llty, buf)
-                        });
+                        let buf = CString::from_slice(sym.as_bytes());
+                        let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
+                                                    buf.as_ptr());
 
                         if attr::contains_name(i.attrs[],
                                                "thread_local") {
@@ -2823,9 +2814,8 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                                  sect.get())[]);
                     }
                     unsafe {
-                        sect.get().with_c_str(|buf| {
-                            llvm::LLVMSetSection(v, buf);
-                        })
+                        let buf = CString::from_slice(sect.get().as_bytes());
+                        llvm::LLVMSetSection(v, buf.as_ptr());
                     }
                 },
                 None => ()
@@ -2978,7 +2968,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
     }
 
     let encode_inlined_item: encoder::EncodeInlinedItem =
-        |ecx, rbml_w, ii| astencode::encode_inlined_item(ecx, rbml_w, ii);
+        box |ecx, rbml_w, ii| astencode::encode_inlined_item(ecx, rbml_w, ii);
 
     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
     let metadata = encoder::encode_metadata(encode_parms, krate);
@@ -2992,17 +2982,16 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
     let name = format!("rust_metadata_{}_{}",
                        cx.link_meta().crate_name,
                        cx.link_meta().crate_hash);
-    let llglobal = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf)
-        }
-    });
+    let buf = CString::from_vec(name.into_bytes());
+    let llglobal = unsafe {
+        llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
+                            buf.as_ptr())
+    };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
         let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
-        name.with_c_str(|buf| {
-            llvm::LLVMSetSection(llglobal, buf)
-        });
+        let name = CString::from_slice(name.as_bytes());
+        llvm::LLVMSetSection(llglobal, name.as_ptr())
     }
     return metadata;
 }
@@ -3010,8 +2999,6 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
 /// Find any symbols that are defined in one compilation unit, but not declared
 /// in any other compilation unit.  Give these symbols internal linkage.
 fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
-    use std::c_str::CString;
-
     unsafe {
         let mut declared = HashSet::new();
 
@@ -3041,7 +3028,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
                     continue
                 }
 
-                let name = CString::new(llvm::LLVMGetValueName(val), false);
+                let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+                               .to_vec();
                 declared.insert(name);
             }
         }
@@ -3057,9 +3045,10 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
                     continue
                 }
 
-                let name = CString::new(llvm::LLVMGetValueName(val), false);
+                let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+                               .to_vec();
                 if !declared.contains(&name) &&
-                   !reachable.contains(name.as_str().unwrap()) {
+                   !reachable.contains(str::from_utf8(name.as_slice()).unwrap()) {
                     llvm::SetLinkage(val, llvm::InternalLinkage);
                 }
             }
index 97f0b92a290f839ab9871f6819dce94038bef53f..e09d36ddae923188be8407e9942c2aac077713ec 100644 (file)
@@ -20,7 +20,8 @@
 use trans::type_::Type;
 use util::nodemap::FnvHashMap;
 use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+
+use std::ffi::CString;
 use syntax::codemap::Span;
 
 pub struct Builder<'a, 'tcx: 'a> {
@@ -429,9 +430,9 @@ pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
             if name.is_empty() {
                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
             } else {
-                name.with_c_str(|c| {
-                    llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
-                })
+                let name = CString::from_slice(name.as_bytes());
+                llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+                                      name.as_ptr())
             }
         }
     }
@@ -774,12 +775,12 @@ pub fn add_comment(&self, text: &str) {
             let comment_text = format!("{} {}", "#",
                                        sanitized.replace("\n", "\n\t# "));
             self.count_insn("inlineasm");
-            let asm = comment_text.with_c_str(|c| {
-                unsafe {
-                    llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
-                                             c, noname(), False, False)
-                }
-            });
+            let comment_text = CString::from_vec(comment_text.into_bytes());
+            let asm = unsafe {
+                llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+                                         comment_text.as_ptr(), noname(), False,
+                                         False)
+            };
             self.call(asm, &[], None);
         }
     }
@@ -926,9 +927,8 @@ pub fn trap(&self) {
             let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
             let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
             let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
-            let t: ValueRef = "llvm.trap".with_c_str(|buf| {
-                llvm::LLVMGetNamedFunction(m, buf)
-            });
+            let p = "llvm.trap\0".as_ptr();
+            let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
             assert!((t as int != 0));
             let args: &[ValueRef] = &[];
             self.count_insn("trap");
index f001786bec4e96be9d8a0454d0fd2dbb51047d1e..65e6d7e1924b6050f8625c466203fb433a523c5e 100644 (file)
@@ -19,7 +19,7 @@
 pub use self::CallArgs::*;
 
 use arena::TypedArena;
-use back::{abi,link};
+use back::link;
 use session;
 use llvm::{ValueRef};
 use llvm::get_param;
@@ -38,6 +38,7 @@
 use trans::closure;
 use trans::common;
 use trans::common::*;
+use trans::consts;
 use trans::datum::*;
 use trans::expr;
 use trans::glue;
@@ -65,8 +66,6 @@ pub struct MethodData {
 }
 
 pub enum CalleeData<'tcx> {
-    Closure(Datum<'tcx, Lvalue>),
-
     // Constructor for enum variant/tuple-like-struct
     // i.e. Some, Ok
     NamedTupleConstructor(subst::Substs<'tcx>, ty::Disr),
@@ -101,7 +100,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
 
     fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                                 -> Callee<'blk, 'tcx> {
-        let DatumBlock {mut bcx, datum} = expr::trans(bcx, expr);
+        let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr);
         match datum.ty.sty {
             ty::ty_bare_fn(..) => {
                 let llval = datum.to_llscalarish(bcx);
@@ -110,14 +109,6 @@ fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                     data: Fn(llval),
                 };
             }
-            ty::ty_closure(..) => {
-                let datum = unpack_datum!(
-                    bcx, datum.to_lvalue_datum(bcx, "callee", expr.id));
-                return Callee {
-                    bcx: bcx,
-                    data: Closure(datum),
-                };
-            }
             _ => {
                 bcx.tcx().sess.span_bug(
                     expr.span,
@@ -152,7 +143,8 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     _ => false
                 }
             } => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(substs, 0)
@@ -162,23 +154,28 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
                 _ => false
             } => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
                 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
             }
             def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
             def::DefStaticMethod(did, def::FromImpl(_)) => {
-                fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id)))
+                fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs).val)
             }
             def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
             def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
-                fn_callee(bcx, meth::trans_static_method_callee(bcx, meth_did,
+                fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
+                                                                meth_did,
                                                                 trait_did,
-                                                                ref_expr.id))
+                                                                ref_expr.id,
+                                                                bcx.fcx.param_substs).val)
             }
             def::DefVariant(tid, vid, _) => {
                 let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
 
                 // Nullary variants are not callable
                 assert!(vinfo.args.len() > 0u);
@@ -189,7 +186,8 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
             def::DefStruct(_) => {
-                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
+                                            bcx.fcx.param_substs);
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(substs, 0)
@@ -217,15 +215,19 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 /// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function
 /// pointer. This may require monomorphization or inlining.
-pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
+pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                              def_id: ast::DefId,
+                              node: ExprOrMethodCall,
+                              param_substs: &subst::Substs<'tcx>)
+                              -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_fn_ref");
 
-    let substs = node_id_substs(bcx, node);
+    let substs = node_id_substs(ccx, node, param_substs);
     debug!("trans_fn_ref(def_id={}, node={}, substs={})",
-           def_id.repr(bcx.tcx()),
+           def_id.repr(ccx.tcx()),
            node,
-           substs.repr(bcx.tcx()));
-    trans_fn_ref_with_substs(bcx, def_id, node, substs)
+           substs.repr(ccx.tcx()));
+    trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs)
 }
 
 fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -235,10 +237,11 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                   -> Callee<'blk, 'tcx> {
     Callee {
         bcx: bcx,
-        data: Fn(trans_fn_ref_with_substs(bcx,
+        data: Fn(trans_fn_ref_with_substs(bcx.ccx(),
                                           def_id,
                                           ExprId(ref_id),
-                                          substs)),
+                                          bcx.fcx.param_substs,
+                                          substs).val),
     }
 }
 
@@ -364,28 +367,30 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 ///
 /// # Parameters
 ///
-/// - `bcx`: the current block where the reference to the fn occurs
+/// - `ccx`: the crate context
 /// - `def_id`: def id of the fn or method item being referenced
 /// - `node`: node id of the reference to the fn/method, if applicable.
 ///   This parameter may be zero; but, if so, the resulting value may not
 ///   have the right type, so it must be cast before being used.
+/// - `param_substs`: if the `node` is in a polymorphic function, these
+///   are the substitutions required to monomorphize its type
 /// - `substs`: values for each of the fn/method's parameters
-pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
-    bcx: Block<'blk, 'tcx>,      //
-    def_id: ast::DefId,          // def id of fn
-    node: ExprOrMethodCall,      // node id of use of fn; may be zero if N/A
-    substs: subst::Substs<'tcx>) // vtables for the call
-    -> ValueRef
+pub fn trans_fn_ref_with_substs<'a, 'tcx>(
+    ccx: &CrateContext<'a, 'tcx>,
+    def_id: ast::DefId,
+    node: ExprOrMethodCall,
+    param_substs: &subst::Substs<'tcx>,
+    substs: subst::Substs<'tcx>)
+    -> Datum<'tcx, Rvalue>
 {
     let _icx = push_ctxt("trans_fn_ref_with_substs");
-    let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
+    let tcx = ccx.tcx();
 
-    debug!("trans_fn_ref_with_substs(bcx={}, def_id={}, node={}, \
-            substs={})",
-           bcx.to_str(),
+    debug!("trans_fn_ref_with_substs(def_id={}, node={}, \
+            param_substs={}, substs={})",
            def_id.repr(tcx),
            node,
+           param_substs.repr(tcx),
            substs.repr(tcx));
 
     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
@@ -443,15 +448,15 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
                     (true, source_id, new_substs)
                 }
                 ty::TypeTraitItem(_) => {
-                    bcx.tcx().sess.bug("trans_fn_ref_with_vtables() tried \
-                                        to translate an associated type?!")
+                    tcx.sess.bug("trans_fn_ref_with_vtables() tried \
+                                  to translate an associated type?!")
                 }
             }
         }
     };
 
     // If this is an unboxed closure, redirect to it.
-    match closure::get_or_create_declaration_if_unboxed_closure(bcx,
+    match closure::get_or_create_declaration_if_unboxed_closure(ccx,
                                                                 def_id,
                                                                 &substs) {
         None => {}
@@ -494,24 +499,27 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
             MethodCallKey(_) => None,
         };
 
-        let (val, must_cast) =
+        let (val, fn_ty, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs, opt_ref_id);
-        let mut val = val;
         if must_cast && node != ExprId(0) {
             // Monotype of the REFERENCE to the function (type params
             // are subst'd)
             let ref_ty = match node {
-                ExprId(id) => node_id_type(bcx, id),
+                ExprId(id) => ty::node_id_to_type(tcx, id),
                 MethodCallKey(method_call) => {
-                    let t = (*bcx.tcx().method_map.borrow())[method_call].ty;
-                    monomorphize_type(bcx, t)
+                    (*tcx.method_map.borrow())[method_call].ty
                 }
             };
-
-            val = PointerCast(
-                bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
+            let ref_ty = monomorphize::apply_param_substs(tcx,
+                                                          param_substs,
+                                                          &ref_ty);
+            let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to();
+            if llptrty != val_ty(val) {
+                let val = consts::ptrcast(val, llptrty);
+                return Datum::new(val, ref_ty, Rvalue::new(ByValue));
+            }
         }
-        return val;
+        return Datum::new(val, fn_ty, Rvalue::new(ByValue));
     }
 
     // Type scheme of the function item (may have type params)
@@ -556,12 +564,12 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
     let llptrty = llty.ptr_to();
     if val_ty(val) != llptrty {
         debug!("trans_fn_ref_with_vtables(): casting pointer!");
-        val = BitCast(bcx, val, llptrty);
+        val = consts::ptrcast(val, llptrty);
     } else {
         debug!("trans_fn_ref_with_vtables(): not casting pointer!");
     }
 
-    val
+    Datum::new(val, fn_type, Rvalue::new(ByValue))
 }
 
 // ______________________________________________________________________
@@ -576,7 +584,7 @@ pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_call");
     trans_call_inner(in_cx,
                      Some(common::expr_info(call_ex)),
-                     expr_ty(in_cx, f),
+                     expr_ty_adjusted(in_cx, f),
                      |cx, _| trans(cx, f),
                      args,
                      Some(dest)).bcx
@@ -661,7 +669,6 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
     let (abi, ret_ty) = match callee_ty.sty {
         ty::ty_bare_fn(_, ref f) => (f.abi, f.sig.0.output),
-        ty::ty_closure(ref f) => (f.abi, f.sig.0.output),
         _ => panic!("expected bare rust fn or closure in trans_call_inner")
     };
 
@@ -672,16 +679,6 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         TraitItem(d) => {
             (d.llfn, None, Some(d.llself))
         }
-        Closure(d) => {
-            // Closures are represented as (llfn, llclosure) pair:
-            // load the requisite values out.
-            let pair = d.to_llref();
-            let llfn = GEPi(bcx, pair, &[0u, abi::FAT_PTR_ADDR]);
-            let llfn = Load(bcx, llfn);
-            let llenv = GEPi(bcx, pair, &[0u, abi::FAT_PTR_EXTRA]);
-            let llenv = Load(bcx, llenv);
-            (llfn, Some(llenv), None)
-        }
         Intrinsic(node, substs) => {
             assert!(abi == synabi::RustIntrinsic);
             assert!(dest.is_some());
index 59ba56bbbc857cd5871e20ab57e459db285368c9..79a5898e3d33ea2db7e3aaefd46ac2eee6b0b2e6 100644 (file)
@@ -726,7 +726,10 @@ fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef {
         // specify any of the types for the function, we just make it a symbol
         // that LLVM can later use.
         let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() {
-            Some(def_id) => callee::trans_fn_ref(pad_bcx, def_id, ExprId(0)),
+            Some(def_id) => {
+                callee::trans_fn_ref(pad_bcx.ccx(), def_id, ExprId(0),
+                                     pad_bcx.fcx.param_substs).val
+            }
             None => {
                 let mut personality = self.ccx.eh_personality().borrow_mut();
                 match *personality {
index cb5302f7234f91a7932461f41ebd74272fc1dd19..6f2def16e7674f867c14e673cc2cb0fdc40269cf 100644 (file)
@@ -19,7 +19,8 @@
 use trans::build::*;
 use trans::cleanup::{CleanupMethods, ScopeId};
 use trans::common::*;
-use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
+use trans::datum::{Datum, Lvalue, rvalue_scratch_datum};
+use trans::datum::{Rvalue, ByValue};
 use trans::debuginfo;
 use trans::expr;
 use trans::monomorphize::{self, MonoId};
 use middle::ty::{self, Ty, UnboxedClosureTyper};
 use middle::subst::{Substs};
 use session::config::FullDebugInfo;
-use util::ppaux::Repr;
 use util::ppaux::ty_to_string;
 
-use arena::TypedArena;
 use syntax::ast;
 use syntax::ast_util;
 
@@ -453,22 +452,21 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 /// Returns the LLVM function declaration for an unboxed closure, creating it
 /// if necessary. If the ID does not correspond to a closure ID, returns None.
-pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                                                closure_id: ast::DefId,
-                                                                substs: &Substs<'tcx>)
-                                                                -> Option<ValueRef> {
-    let ccx = bcx.ccx();
+pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                                              closure_id: ast::DefId,
+                                                              substs: &Substs<'tcx>)
+                                                              -> Option<Datum<'tcx, Rvalue>> {
     if !ccx.tcx().unboxed_closures.borrow().contains_key(&closure_id) {
         // Not an unboxed closure.
         return None
     }
 
-    let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
-    let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
+    let function_type = ty::node_id_to_type(ccx.tcx(), closure_id.node);
+    let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);
 
     // Normalize type so differences in regions and typedefs don't cause
     // duplicate declarations
-    let function_type = ty::normalize_ty(bcx.tcx(), function_type);
+    let function_type = ty::normalize_ty(ccx.tcx(), function_type);
     let params = match function_type.sty {
         ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
         _ => unreachable!()
@@ -479,10 +477,10 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
     };
 
     match ccx.unboxed_closure_vals().borrow().get(&mono_id) {
-        Some(llfn) => {
+        Some(&llfn) => {
             debug!("get_or_create_declaration_if_unboxed_closure(): found \
                     closure");
-            return Some(*llfn)
+            return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
         }
         None => {}
     }
@@ -502,7 +500,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
            ccx.tn().type_to_string(val_ty(llfn)));
     ccx.unboxed_closure_vals().borrow_mut().insert(mono_id, llfn);
 
-    Some(llfn)
+    Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
 }
 
 pub fn trans_unboxed_closure<'blk, 'tcx>(
@@ -519,7 +517,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
 
     let closure_id = ast_util::local_def(id);
     let llfn = get_or_create_declaration_if_unboxed_closure(
-        bcx,
+        bcx.ccx(),
         closure_id,
         bcx.fcx.param_substs).unwrap();
 
@@ -530,7 +528,6 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
     // of the closure expression.
     let typer = NormalizingUnboxedClosureTyper::new(bcx.tcx());
     let function_type = typer.unboxed_closure_type(closure_id, bcx.fcx.param_substs);
-    let function_type = ty::mk_closure(bcx.tcx(), function_type);
 
     let freevars: Vec<ty::Freevar> =
         ty::with_freevars(bcx.tcx(), id, |fv| fv.iter().map(|&fv| fv).collect());
@@ -539,12 +536,12 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
     trans_closure(bcx.ccx(),
                   decl,
                   body,
-                  llfn,
+                  llfn.val,
                   bcx.fcx.param_substs,
                   id,
                   &[],
-                  ty::ty_fn_ret(function_type),
-                  ty::ty_fn_abi(function_type),
+                  function_type.sig.0.output,
+                  function_type.abi,
                   ClosureEnv::new(freevars[],
                                   UnboxedClosure(freevar_mode)));
 
@@ -582,98 +579,3 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
 
     bcx
 }
-
-pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                         closure_ty: Ty<'tcx>,
-                                         def_id: ast::DefId,
-                                         fn_ptr: ValueRef,
-                                         is_local: bool) -> ValueRef {
-
-    match ccx.closure_bare_wrapper_cache().borrow().get(&fn_ptr) {
-        Some(&llval) => return llval,
-        None => {}
-    }
-
-    let tcx = ccx.tcx();
-
-    debug!("get_wrapper_for_bare_fn(closure_ty={})", closure_ty.repr(tcx));
-
-    let f = match closure_ty.sty {
-        ty::ty_closure(ref f) => f,
-        _ => {
-            ccx.sess().bug(format!("get_wrapper_for_bare_fn: \
-                                    expected a closure ty, got {}",
-                                    closure_ty.repr(tcx))[]);
-        }
-    };
-
-    let name = ty::with_path(tcx, def_id, |path| {
-        mangle_internal_name_by_path_and_seq(path, "as_closure")
-    });
-    let llfn = if is_local {
-        decl_internal_rust_fn(ccx, closure_ty, name[])
-    } else {
-        decl_rust_fn(ccx, closure_ty, name[])
-    };
-
-    ccx.closure_bare_wrapper_cache().borrow_mut().insert(fn_ptr, llfn);
-
-    // This is only used by statics inlined from a different crate.
-    if !is_local {
-        // Don't regenerate the wrapper, just reuse the original one.
-        return llfn;
-    }
-
-    let _icx = push_ctxt("closure::get_wrapper_for_bare_fn");
-
-    let arena = TypedArena::new();
-    let empty_param_substs = Substs::trans_empty();
-    let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, true, f.sig.0.output,
-                          &empty_param_substs, None, &arena);
-    let bcx = init_function(&fcx, true, f.sig.0.output);
-
-    let args = create_datums_for_fn_args(&fcx,
-                                         ty::ty_fn_args(closure_ty)
-                                            []);
-    let mut llargs = Vec::new();
-    match fcx.llretslotptr.get() {
-        Some(llretptr) => {
-            assert!(!fcx.needs_ret_allocas);
-            llargs.push(llretptr);
-        }
-        None => {}
-    }
-    llargs.extend(args.iter().map(|arg| arg.val));
-
-    let retval = Call(bcx, fn_ptr, llargs.as_slice(), None);
-    match f.sig.0.output {
-        ty::FnConverging(output_type) => {
-            if return_type_is_void(ccx, output_type) || fcx.llretslotptr.get().is_some() {
-                RetVoid(bcx);
-            } else {
-                Ret(bcx, retval);
-            }
-        }
-        ty::FnDiverging => {
-            RetVoid(bcx);
-        }
-    }
-
-    // HACK(eddyb) finish_fn cannot be used here, we returned directly.
-    debuginfo::clear_source_location(&fcx);
-    fcx.cleanup();
-
-    llfn
-}
-
-pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                             closure_ty: Ty<'tcx>,
-                                             def_id: ast::DefId,
-                                             fn_ptr: ValueRef)
-                                             -> DatumBlock<'blk, 'tcx, Expr>  {
-    let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
-    let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def_id, fn_ptr, true);
-    fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx())));
-
-    DatumBlock::new(bcx, scratch.to_expr_datum())
-}
index 87a1862186a4d1d7814d0df3840ca46a1cf4cfd6..094f98e988aad202fda3fc3e9535f62c1a3cdcaa 100644 (file)
@@ -28,6 +28,7 @@
 use trans::base;
 use trans::build;
 use trans::cleanup;
+use trans::consts;
 use trans::datum;
 use trans::debuginfo;
 use trans::machine;
@@ -43,7 +44,7 @@
 
 use arena::TypedArena;
 use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
 use std::vec::Vec;
 use syntax::ast::Ident;
@@ -400,9 +401,8 @@ pub fn get_llreturn(&self) -> BasicBlockRef {
         if self.llreturn.get().is_none() {
 
             self.llreturn.set(Some(unsafe {
-                "return".with_c_str(|buf| {
-                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf)
-                })
+                llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
+                                                    "return\0".as_ptr() as *const _)
             }))
         }
 
@@ -428,11 +428,10 @@ pub fn new_block(&'a self,
                      opt_node_id: Option<ast::NodeId>)
                      -> Block<'a, 'tcx> {
         unsafe {
-            let llbb = name.with_c_str(|buf| {
-                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
-                                                        self.llfn,
-                                                        buf)
-                });
+            let name = CString::from_slice(name.as_bytes());
+            let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
+                                                           self.llfn,
+                                                           name.as_ptr());
             BlockS::new(llbb, is_lpad, opt_node_id, self)
         }
     }
@@ -707,7 +706,8 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
 
 pub fn C_floating(s: &str, t: Type) -> ValueRef {
     unsafe {
-        s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
+        let s = CString::from_slice(s.as_bytes());
+        llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
     }
 }
 
@@ -788,9 +788,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
                                                 !null_terminated as Bool);
 
         let gsym = token::gensym("str");
-        let g = format!("str{}", gsym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf)
-        });
+        let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
+        let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
         llvm::LLVMSetInitializer(g, sc);
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::SetLinkage(g, llvm::InternalLinkage);
@@ -803,12 +802,9 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
-    unsafe {
-        let len = s.get().len();
-        let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
-                                            Type::i8p(cx).to_ref());
-        C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
-    }
+    let len = s.get().len();
+    let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx));
+    C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
 }
 
 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
@@ -817,14 +813,15 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
         let lldata = C_bytes(cx, data);
 
         let gsym = token::gensym("binary");
-        let g = format!("binary{}", gsym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf)
-        });
+        let name = format!("binary{}", gsym.uint());
+        let name = CString::from_vec(name.into_bytes());
+        let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
+                                    name.as_ptr());
         llvm::LLVMSetInitializer(g, lldata);
         llvm::LLVMSetGlobalConstant(g, True);
         llvm::SetLinkage(g, llvm::InternalLinkage);
 
-        let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+        let cs = consts::ptrcast(g, Type::i8p(cx));
         C_struct(cx, &[cs, C_uint(cx, len)], false)
     }
 }
@@ -1095,11 +1092,11 @@ pub enum ExprOrMethodCall {
     MethodCallKey(ty::MethodCall)
 }
 
-pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                  node: ExprOrMethodCall)
-                                  -> subst::Substs<'tcx>
-{
-    let tcx = bcx.tcx();
+pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                node: ExprOrMethodCall,
+                                param_substs: &subst::Substs<'tcx>)
+                                -> subst::Substs<'tcx> {
+    let tcx = ccx.tcx();
 
     let substs = match node {
         ExprId(id) => {
@@ -1111,15 +1108,13 @@ pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     if substs.types.any(|t| ty::type_needs_infer(*t)) {
-        bcx.sess().bug(
-            format!("type parameters for node {} include inference types: \
-                     {}",
-                    node,
-                    substs.repr(bcx.tcx()))[]);
+        tcx.sess.bug(format!("type parameters for node {} include inference types: {}",
+                             node, substs.repr(tcx))[]);
     }
 
-    let substs = substs.erase_regions();
-    bcx.monomorphize(&substs)
+    monomorphize::apply_param_substs(tcx,
+                                     param_substs,
+                                     &substs.erase_regions())
 }
 
 pub fn langcall(bcx: Block,
index 4f8554195e56954ec0fd2d30b6ba0a8b0e108ad4..a3861e71d83de56c614d8c676c5a203167d1065e 100644 (file)
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True, False};
 use llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
            RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
-use metadata::csearch;
 use middle::{const_eval, def};
-use trans::{adt, closure, consts, debuginfo, expr, inline, machine};
+use trans::{adt, consts, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
 use trans::common::*;
 use trans::type_::Type;
 use trans::type_of;
+use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use util::ppaux::{Repr, ty_to_string};
 
-use std::c_str::ToCStr;
 use std::iter::repeat;
 use libc::c_uint;
 use syntax::{ast, ast_util};
@@ -79,11 +78,9 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
     }
 }
 
-pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef {
+pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
     unsafe {
-        let b = llvm::LLVMConstPointerCast(a, t.ptr_to().to_ref());
-        assert!(cx.const_globals().borrow_mut().insert(b as int, a).is_none());
-        b
+        llvm::LLVMConstPointerCast(val, ty.to_ref())
     }
 }
 
@@ -105,9 +102,8 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr,
 
 pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef {
     unsafe {
-        let gv = "const".with_c_str(|name| {
-            llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), name)
-        });
+        let gv = llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(),
+                                     "const\0".as_ptr() as *const _);
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetGlobalConstant(gv,
                                     if mutbl == ast::MutImmutable {True} else {False});
@@ -191,20 +187,6 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
         None => { }
         Some(adj) => {
             match adj {
-                ty::AdjustAddEnv(def_id, ty::RegionTraitStore(ty::ReStatic, _)) => {
-                    let wrapper = closure::get_wrapper_for_bare_fn(cx,
-                                                                   ety_adjusted,
-                                                                   def_id,
-                                                                   llconst,
-                                                                   true);
-                    llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false)
-                }
-                ty::AdjustAddEnv(_, store) => {
-                    cx.sess()
-                      .span_bug(e.span,
-                                format!("unexpected static function: {}",
-                                        store)[])
-                }
                 ty::AdjustReifyFnPointer(_def_id) => {
                     // FIXME(#19925) once fn item types are
                     // zero-sized, we'll need to do something here
@@ -258,7 +240,9 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
                                     match ty.sty {
                                         ty::ty_vec(unit_ty, Some(len)) => {
                                             let llunitty = type_of::type_of(cx, unit_ty);
-                                            let llptr = const_ptrcast(cx, llconst, llunitty);
+                                            let llptr = ptrcast(llconst, llunitty.ptr_to());
+                                            assert!(cx.const_globals().borrow_mut()
+                                                      .insert(llptr as int, llconst).is_none());
                                             assert_eq!(abi::FAT_PTR_ADDR, 0);
                                             assert_eq!(abi::FAT_PTR_EXTRA, 1);
                                             llconst = C_struct(cx, &[
@@ -523,7 +507,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 }
               }
               (expr::cast_pointer, expr::cast_pointer) => {
-                llvm::LLVMConstPointerCast(v, llty.to_ref())
+                ptrcast(v, llty)
               }
               (expr::cast_integral, expr::cast_pointer) => {
                 llvm::LLVMConstIntToPtr(v, llty.to_ref())
@@ -616,36 +600,38 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 C_array(llunitty, vs[])
             }
           }
-          ast::ExprPath(ref pth) => {
-            // Assert that there are no type parameters in this path.
-            assert!(pth.segments.iter().all(|seg| !seg.parameters.has_types()));
-
-            let opt_def = cx.tcx().def_map.borrow().get(&e.id).cloned();
-            match opt_def {
-                Some(def::DefFn(def_id, _)) => {
-                    if !ast_util::is_local(def_id) {
-                        let ty = csearch::get_type(cx.tcx(), def_id).ty;
-                        base::trans_external_path(cx, def_id, ty)
-                    } else {
-                        assert!(ast_util::is_local(def_id));
-                        base::get_item_val(cx, def_id.node)
-                    }
+          ast::ExprPath(_) => {
+            let def = cx.tcx().def_map.borrow()[e.id];
+            match def {
+                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
+                    expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
                 }
-                Some(def::DefConst(def_id)) => {
+                def::DefConst(def_id) => {
                     get_const_val(cx, def_id)
                 }
-                Some(def::DefVariant(enum_did, variant_did, _)) => {
-                    let ety = ty::expr_ty(cx.tcx(), e);
-                    let repr = adt::represent_type(cx, ety);
+                def::DefVariant(enum_did, variant_did, _) => {
                     let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                          enum_did,
                                                          variant_did);
-                    adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
+                    if vinfo.args.len() > 0 {
+                        // N-ary variant.
+                        expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
+                    } else {
+                        // Nullary variant.
+                        let ety = ty::expr_ty(cx.tcx(), e);
+                        let repr = adt::represent_type(cx, ety);
+                        adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
+                    }
                 }
-                Some(def::DefStruct(_)) => {
+                def::DefStruct(_) => {
                     let ety = ty::expr_ty(cx.tcx(), e);
-                    let llty = type_of::type_of(cx, ety);
-                    C_null(llty)
+                    if let ty::ty_bare_fn(..) = ety.sty {
+                        // Tuple struct.
+                        expr::trans_def_fn_unadjusted(cx, e, def, &Substs::trans_empty()).val
+                    } else {
+                        // Unit struct.
+                        C_null(type_of::type_of(cx, ety))
+                    }
                 }
                 _ => {
                     cx.sess().span_bug(e.span, "expected a const, fn, struct, \
index e5a0e2e9234d5ed1b022736dabc0f7e57abe243e..f974a6faf4c19d8e6feb31b7e4cda3417e86a312 100644 (file)
@@ -29,8 +29,8 @@
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
 
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
-use std::c_str::ToCStr;
 use std::ptr;
 use std::rc::Rc;
 use syntax::ast;
@@ -221,21 +221,16 @@ fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> {
 
 unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
     let llcx = llvm::LLVMContextCreate();
-    let llmod = mod_name.with_c_str(|buf| {
-        llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
-    });
-    sess.target
-        .target
-        .data_layout
-        .with_c_str(|buf| {
-        llvm::LLVMSetDataLayout(llmod, buf);
-    });
-    sess.target
-        .target
-        .llvm_target
-        .with_c_str(|buf| {
-        llvm::LLVMRustSetNormalizedTarget(llmod, buf);
-    });
+    let mod_name = CString::from_slice(mod_name.as_bytes());
+    let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
+
+    let data_layout = sess.target.target.data_layout.as_slice();
+    let data_layout = CString::from_slice(data_layout.as_bytes());
+    llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
+
+    let llvm_target = sess.target.target.llvm_target.as_slice();
+    let llvm_target = CString::from_slice(llvm_target.as_bytes());
+    llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
     (llcx, llmod)
 }
 
index 916fcbfe13ef77df022583d3acf82788b4ee20ee..f6c09629f316a57eeb4003ebab2fc164b0e08b53 100644 (file)
 use util::ppaux;
 
 use libc::c_uint;
-use std::c_str::{CString, ToCStr};
+use std::ffi::CString;
 use std::cell::{Cell, RefCell};
 use std::ptr;
 use std::rc::{Rc, Weak};
@@ -465,11 +465,6 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                     }
                 }
             },
-            ty::ty_closure(box ref closure_ty) => {
-                self.get_unique_type_id_of_closure_type(cx,
-                                                        closure_ty.clone(),
-                                                        &mut unique_type_id);
-            },
             ty::ty_unboxed_closure(def_id, _, substs) => {
                 let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
                 let closure_ty = typer.unboxed_closure_type(def_id, substs);
@@ -760,14 +755,15 @@ pub fn finalize(cx: &CrateContext) {
         // for OS X to understand. For more info see #11352
         // This can be overridden using --llvm-opts -dwarf-version,N.
         if cx.sess().target.target.options.is_like_osx {
-            "Dwarf Version".with_c_str(
-                |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2));
+            llvm::LLVMRustAddModuleFlag(cx.llmod(),
+                                        "Dwarf Version\0".as_ptr() as *const _,
+                                        2)
         }
 
         // Prevent bitcode readers from deleting the debug info.
-        "Debug Info Version".with_c_str(
-            |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s,
-                                            llvm::LLVMRustDebugMetadataVersion));
+        let ptr = "Debug Info Version\0".as_ptr();
+        llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+                                    llvm::LLVMRustDebugMetadataVersion);
     };
 }
 
@@ -829,22 +825,20 @@ pub fn create_global_var_metadata(cx: &CrateContext,
         namespace_node.mangled_name_of_contained_item(var_name[]);
     let var_scope = namespace_node.scope;
 
-    var_name.with_c_str(|var_name| {
-        linkage_name.with_c_str(|linkage_name| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
-                                                        var_scope,
-                                                        var_name,
-                                                        linkage_name,
-                                                        file_metadata,
-                                                        line_number,
-                                                        type_metadata,
-                                                        is_local_to_unit,
-                                                        global,
-                                                        ptr::null_mut());
-            }
-        })
-    });
+    let var_name = CString::from_slice(var_name.as_bytes());
+    let linkage_name = CString::from_slice(linkage_name.as_bytes());
+    unsafe {
+        llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
+                                                var_scope,
+                                                var_name.as_ptr(),
+                                                linkage_name.as_ptr(),
+                                                file_metadata,
+                                                line_number,
+                                                type_metadata,
+                                                is_local_to_unit,
+                                                global,
+                                                ptr::null_mut());
+    }
 }
 
 /// Creates debug information for the given local variable.
@@ -1388,28 +1382,26 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
 
-    let fn_metadata = function_name.with_c_str(|function_name| {
-                          linkage_name.with_c_str(|linkage_name| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateFunction(
-                    DIB(cx),
-                    containing_scope,
-                    function_name,
-                    linkage_name,
-                    file_metadata,
-                    loc.line as c_uint,
-                    function_type_metadata,
-                    is_local_to_unit,
-                    true,
-                    scope_line as c_uint,
-                    FlagPrototyped as c_uint,
-                    cx.sess().opts.optimize != config::No,
-                    llfn,
-                    template_parameters,
-                    ptr::null_mut())
-            }
-        })
-    });
+    let function_name = CString::from_slice(function_name.as_bytes());
+    let linkage_name = CString::from_slice(linkage_name.as_bytes());
+    let fn_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFunction(
+            DIB(cx),
+            containing_scope,
+            function_name.as_ptr(),
+            linkage_name.as_ptr(),
+            file_metadata,
+            loc.line as c_uint,
+            function_type_metadata,
+            is_local_to_unit,
+            true,
+            scope_line as c_uint,
+            FlagPrototyped as c_uint,
+            cx.sess().opts.optimize != config::No,
+            llfn,
+            template_parameters,
+            ptr::null_mut())
+    };
 
     let scope_map = create_scope_map(cx,
                                      fn_decl.inputs.as_slice(),
@@ -1514,19 +1506,18 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
                 let ident = special_idents::type_self;
 
-                let param_metadata = token::get_ident(ident).get()
-                                                            .with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                            DIB(cx),
-                            file_metadata,
-                            name,
-                            actual_self_type_metadata,
-                            ptr::null_mut(),
-                            0,
-                            0)
-                    }
-                });
+                let ident = token::get_ident(ident);
+                let name = CString::from_slice(ident.get().as_bytes());
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_self_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
 
                 template_params.push(param_metadata);
             }
@@ -1549,19 +1540,18 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Again, only create type information if full debuginfo is enabled
             if cx.sess().opts.debuginfo == FullDebugInfo {
                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
-                let param_metadata = token::get_ident(ident).get()
-                                                            .with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                            DIB(cx),
-                            file_metadata,
-                            name,
-                            actual_type_metadata,
-                            ptr::null_mut(),
-                            0,
-                            0)
-                    }
-                });
+                let ident = token::get_ident(ident);
+                let name = CString::from_slice(ident.get().as_bytes());
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
                 template_params.push(param_metadata);
             }
         }
@@ -1606,19 +1596,19 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
             } else {
                 match abs_path.path_relative_from(work_dir) {
                     Some(ref p) if p.is_relative() => {
-                            // prepend "./" if necessary
-                            let dotdot = b"..";
-                            let prefix = [dotdot[0], ::std::path::SEP_BYTE];
-                            let mut path_bytes = p.as_vec().to_vec();
-
-                            if path_bytes.slice_to(2) != prefix &&
-                               path_bytes.slice_to(2) != dotdot {
-                                path_bytes.insert(0, prefix[0]);
-                                path_bytes.insert(1, prefix[1]);
-                            }
-
-                            path_bytes.to_c_str()
+                        // prepend "./" if necessary
+                        let dotdot = b"..";
+                        let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE];
+                        let mut path_bytes = p.as_vec().to_vec();
+
+                        if path_bytes.slice_to(2) != prefix &&
+                           path_bytes.slice_to(2) != dotdot {
+                            path_bytes.insert(0, prefix[0]);
+                            path_bytes.insert(1, prefix[1]);
                         }
+
+                        CString::from_vec(path_bytes)
+                    }
                     _ => fallback_path(cx)
                 }
             }
@@ -1630,29 +1620,25 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
                            (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
 
     let compile_unit_name = compile_unit_name.as_ptr();
-    return work_dir.as_vec().with_c_str(|work_dir| {
-        producer.with_c_str(|producer| {
-            "".with_c_str(|flags| {
-                "".with_c_str(|split_name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateCompileUnit(
-                            debug_context(cx).builder,
-                            DW_LANG_RUST,
-                            compile_unit_name,
-                            work_dir,
-                            producer,
-                            cx.sess().opts.optimize != config::No,
-                            flags,
-                            0,
-                            split_name)
-                    }
-                })
-            })
-        })
-    });
+    let work_dir = CString::from_slice(work_dir.as_vec());
+    let producer = CString::from_slice(producer.as_bytes());
+    let flags = "\0";
+    let split_name = "\0";
+    return unsafe {
+        llvm::LLVMDIBuilderCreateCompileUnit(
+            debug_context(cx).builder,
+            DW_LANG_RUST,
+            compile_unit_name,
+            work_dir.as_ptr(),
+            producer.as_ptr(),
+            cx.sess().opts.optimize != config::No,
+            flags.as_ptr() as *const _,
+            0,
+            split_name.as_ptr() as *const _)
+    };
 
     fn fallback_path(cx: &CrateContext) -> CString {
-        cx.link_meta().crate_name.to_c_str()
+        CString::from_slice(cx.link_meta().crate_name.as_bytes())
     }
 }
 
@@ -1678,42 +1664,41 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         CapturedVariable => (0, DW_TAG_auto_variable)
     };
 
-    let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
-        match variable_access {
-            DirectVariable { alloca } => (
-                alloca,
-                unsafe {
-                    llvm::LLVMDIBuilderCreateLocalVariable(
-                        DIB(cx),
-                        dwarf_tag,
-                        scope_metadata,
-                        name,
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        cx.sess().opts.optimize != config::No,
-                        0,
-                        argument_index)
-                }
-            ),
-            IndirectVariable { alloca, address_operations } => (
-                alloca,
-                unsafe {
-                    llvm::LLVMDIBuilderCreateComplexVariable(
-                        DIB(cx),
-                        dwarf_tag,
-                        scope_metadata,
-                        name,
-                        file_metadata,
-                        loc.line as c_uint,
-                        type_metadata,
-                        address_operations.as_ptr(),
-                        address_operations.len() as c_uint,
-                        argument_index)
-                }
-            )
-        }
-    });
+    let name = CString::from_slice(name.get().as_bytes());
+    let (var_alloca, var_metadata) = match variable_access {
+        DirectVariable { alloca } => (
+            alloca,
+            unsafe {
+                llvm::LLVMDIBuilderCreateLocalVariable(
+                    DIB(cx),
+                    dwarf_tag,
+                    scope_metadata,
+                    name.as_ptr(),
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    cx.sess().opts.optimize != config::No,
+                    0,
+                    argument_index)
+            }
+        ),
+        IndirectVariable { alloca, address_operations } => (
+            alloca,
+            unsafe {
+                llvm::LLVMDIBuilderCreateComplexVariable(
+                    DIB(cx),
+                    dwarf_tag,
+                    scope_metadata,
+                    name.as_ptr(),
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    address_operations.as_ptr(),
+                    address_operations.len() as c_uint,
+                    argument_index)
+            }
+        )
+    };
 
     set_debug_location(cx, DebugLocation::new(scope_metadata,
                                               loc.line,
@@ -1758,14 +1743,12 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
             full_path
         };
 
-    let file_metadata =
-        file_name.with_c_str(|file_name| {
-            work_dir.with_c_str(|work_dir| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
-                }
-            })
-        });
+    let file_name = CString::from_slice(file_name.as_bytes());
+    let work_dir = CString::from_slice(work_dir.as_bytes());
+    let file_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+                                      work_dir.as_ptr())
+    };
 
     let mut created_files = debug_context(cx).created_files.borrow_mut();
     created_files.insert(full_path.to_string(), file_metadata);
@@ -1793,16 +1776,14 @@ fn scope_metadata(fcx: &FunctionContext,
 }
 
 fn diverging_type_metadata(cx: &CrateContext) -> DIType {
-    "!".with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreateBasicType(
-                DIB(cx),
-                name,
-                bytes_to_bits(0),
-                bytes_to_bits(0),
-                DW_ATE_unsigned)
-        }
-    })
+    unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            "!\0".as_ptr() as *const _,
+            bytes_to_bits(0),
+            bytes_to_bits(0),
+            DW_ATE_unsigned)
+    }
 }
 
 fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -1838,16 +1819,15 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let llvm_type = type_of::type_of(cx, t);
     let (size, align) = size_and_align_of(cx, llvm_type);
-    let ty_metadata = name.with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreateBasicType(
-                DIB(cx),
-                name,
-                bytes_to_bits(size),
-                bytes_to_bits(align),
-                encoding)
-        }
-    });
+    let name = CString::from_slice(name.as_bytes());
+    let ty_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr(),
+            bytes_to_bits(size),
+            bytes_to_bits(align),
+            encoding)
+    };
 
     return ty_metadata;
 }
@@ -1859,16 +1839,15 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
     let name = compute_debuginfo_type_name(cx, pointer_type, false);
-    let ptr_metadata = name.with_c_str(|name| {
-        unsafe {
-            llvm::LLVMDIBuilderCreatePointerType(
-                DIB(cx),
-                pointee_type_metadata,
-                bytes_to_bits(pointer_size),
-                bytes_to_bits(pointer_align),
-                name)
-        }
-    });
+    let name = CString::from_slice(name.as_bytes());
+    let ptr_metadata = unsafe {
+        llvm::LLVMDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee_type_metadata,
+            bytes_to_bits(pointer_size),
+            bytes_to_bits(pointer_align),
+            name.as_ptr())
+    };
     return ptr_metadata;
 }
 
@@ -2478,14 +2457,14 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let enumerators_metadata: Vec<DIDescriptor> = variants
         .iter()
         .map(|v| {
-            token::get_name(v.name).get().with_c_str(|name| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateEnumerator(
-                        DIB(cx),
-                        name,
-                        v.disr_val as u64)
-                }
-            })
+            let token = token::get_name(v.name);
+            let name = CString::from_slice(token.get().as_bytes());
+            unsafe {
+                llvm::LLVMDIBuilderCreateEnumerator(
+                    DIB(cx),
+                    name.as_ptr(),
+                    v.disr_val as u64)
+            }
         })
         .collect();
 
@@ -2509,20 +2488,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                   codemap::DUMMY_SP);
                 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
 
-                let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
-                    unsafe {
-                        llvm::LLVMDIBuilderCreateEnumerationType(
-                            DIB(cx),
-                            containing_scope,
-                            name,
-                            UNKNOWN_FILE_METADATA,
-                            UNKNOWN_LINE_NUMBER,
-                            bytes_to_bits(discriminant_size),
-                            bytes_to_bits(discriminant_align),
-                            create_DIArray(DIB(cx), enumerators_metadata[]),
-                            discriminant_base_type_metadata)
-                    }
-                });
+                let name = CString::from_slice(discriminant_name.get().as_bytes());
+                let discriminant_type_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateEnumerationType(
+                        DIB(cx),
+                        containing_scope,
+                        name.as_ptr(),
+                        UNKNOWN_FILE_METADATA,
+                        UNKNOWN_LINE_NUMBER,
+                        bytes_to_bits(discriminant_size),
+                        bytes_to_bits(discriminant_align),
+                        create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
+                        discriminant_base_type_metadata)
+                };
 
                 debug_context(cx).created_enum_disr_types
                                  .borrow_mut()
@@ -2553,24 +2531,22 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                              .borrow()
                              .get_unique_type_id_as_string(unique_type_id);
 
-    let enum_metadata = enum_name.with_c_str(|enum_name| {
-        unique_type_id_str.with_c_str(|unique_type_id_str| {
-            unsafe {
-                llvm::LLVMDIBuilderCreateUnionType(
-                DIB(cx),
-                containing_scope,
-                enum_name,
-                UNKNOWN_FILE_METADATA,
-                UNKNOWN_LINE_NUMBER,
-                bytes_to_bits(enum_type_size),
-                bytes_to_bits(enum_type_align),
-                0, // Flags
-                ptr::null_mut(),
-                0, // RuntimeLang
-                unique_type_id_str)
-            }
-        })
-    });
+    let enum_name = CString::from_slice(enum_name.as_bytes());
+    let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+    let enum_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateUnionType(
+        DIB(cx),
+        containing_scope,
+        enum_name.as_ptr(),
+        UNKNOWN_FILE_METADATA,
+        UNKNOWN_LINE_NUMBER,
+        bytes_to_bits(enum_type_size),
+        bytes_to_bits(enum_type_align),
+        0, // Flags
+        ptr::null_mut(),
+        0, // RuntimeLang
+        unique_type_id_str.as_ptr())
+    };
 
     return create_and_register_recursive_type_forward_declaration(
         cx,
@@ -2681,21 +2657,20 @@ fn set_members_of_composite_type(cx: &CrateContext,
                 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
             };
 
-            member_description.name.with_c_str(|member_name| {
-                unsafe {
-                    llvm::LLVMDIBuilderCreateMemberType(
-                        DIB(cx),
-                        composite_type_metadata,
-                        member_name,
-                        UNKNOWN_FILE_METADATA,
-                        UNKNOWN_LINE_NUMBER,
-                        bytes_to_bits(member_size),
-                        bytes_to_bits(member_align),
-                        bytes_to_bits(member_offset),
-                        member_description.flags,
-                        member_description.type_metadata)
-                }
-            })
+            let member_name = CString::from_slice(member_description.name.as_bytes());
+            unsafe {
+                llvm::LLVMDIBuilderCreateMemberType(
+                    DIB(cx),
+                    composite_type_metadata,
+                    member_name.as_ptr(),
+                    UNKNOWN_FILE_METADATA,
+                    UNKNOWN_LINE_NUMBER,
+                    bytes_to_bits(member_size),
+                    bytes_to_bits(member_align),
+                    bytes_to_bits(member_offset),
+                    member_description.flags,
+                    member_description.type_metadata)
+            }
         })
         .collect();
 
@@ -2719,30 +2694,28 @@ fn create_struct_stub(cx: &CrateContext,
     let unique_type_id_str = debug_context(cx).type_map
                                               .borrow()
                                               .get_unique_type_id_as_string(unique_type_id);
+    let name = CString::from_slice(struct_type_name.as_bytes());
+    let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
     let metadata_stub = unsafe {
-        struct_type_name.with_c_str(|name| {
-            unique_type_id_str.with_c_str(|unique_type_id| {
-                // LLVMDIBuilderCreateStructType() wants an empty array. A null
-                // pointer will lead to hard to trace and debug LLVM assertions
-                // later on in llvm/lib/IR/Value.cpp.
-                let empty_array = create_DIArray(DIB(cx), &[]);
-
-                llvm::LLVMDIBuilderCreateStructType(
-                    DIB(cx),
-                    containing_scope,
-                    name,
-                    UNKNOWN_FILE_METADATA,
-                    UNKNOWN_LINE_NUMBER,
-                    bytes_to_bits(struct_size),
-                    bytes_to_bits(struct_align),
-                    0,
-                    ptr::null_mut(),
-                    empty_array,
-                    0,
-                    ptr::null_mut(),
-                    unique_type_id)
-            })
-        })
+        // LLVMDIBuilderCreateStructType() wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in llvm/lib/IR/Value.cpp.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+
+        llvm::LLVMDIBuilderCreateStructType(
+            DIB(cx),
+            containing_scope,
+            name.as_ptr(),
+            UNKNOWN_FILE_METADATA,
+            UNKNOWN_LINE_NUMBER,
+            bytes_to_bits(struct_size),
+            bytes_to_bits(struct_align),
+            0,
+            ptr::null_mut(),
+            empty_array,
+            0,
+            ptr::null_mut(),
+            unique_type_id.as_ptr())
     };
 
     return metadata_stub;
@@ -3017,9 +2990,6 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_bare_fn(_, ref barefnty) => {
             subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
         }
-        ty::ty_closure(ref closurety) => {
-            subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
-        }
         ty::ty_unboxed_closure(def_id, _, substs) => {
             let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
             let sig = typer.unboxed_closure_type(def_id, substs).sig;
@@ -3870,66 +3840,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         },
-        ty::ty_closure(box ty::ClosureTy { unsafety,
-                                           onceness,
-                                           store,
-                                           ref sig,
-                                           .. // omitting bounds ...
-                                           }) => {
-            if unsafety == ast::Unsafety::Unsafe {
-                output.push_str("unsafe ");
-            }
-
-            if onceness == ast::Once {
-                output.push_str("once ");
-            }
-
-            let param_list_closing_char;
-            match store {
-                ty::UniqTraitStore => {
-                    output.push_str("proc(");
-                    param_list_closing_char = ')';
-                }
-                ty::RegionTraitStore(_, ast::MutMutable) => {
-                    output.push_str("&mut|");
-                    param_list_closing_char = '|';
-                }
-                ty::RegionTraitStore(_, ast::MutImmutable) => {
-                    output.push_str("&|");
-                    param_list_closing_char = '|';
-                }
-            };
-
-            if sig.0.inputs.len() > 0 {
-                for &parameter_type in sig.0.inputs.iter() {
-                    push_debuginfo_type_name(cx, parameter_type, true, output);
-                    output.push_str(", ");
-                }
-                output.pop();
-                output.pop();
-            }
-
-            if sig.0.variadic {
-                if sig.0.inputs.len() > 0 {
-                    output.push_str(", ...");
-                } else {
-                    output.push_str("...");
-                }
-            }
-
-            output.push(param_list_closing_char);
-
-            match sig.0.output {
-                ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
-                ty::FnConverging(result_type) => {
-                    output.push_str(" -> ");
-                    push_debuginfo_type_name(cx, result_type, true, output);
-                }
-                ty::FnDiverging => {
-                    output.push_str(" -> !");
-                }
-            }
-        },
         ty::ty_unboxed_closure(..) => {
             output.push_str("closure");
         }
@@ -4079,18 +3989,18 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
                         None => ptr::null_mut()
                     };
                     let namespace_name = token::get_name(name);
-                    let scope = namespace_name.get().with_c_str(|namespace_name| {
-                        unsafe {
-                            llvm::LLVMDIBuilderCreateNameSpace(
-                                DIB(cx),
-                                parent_scope,
-                                namespace_name,
-                                // cannot reconstruct file ...
-                                ptr::null_mut(),
-                                // ... or line information, but that's not so important.
-                                0)
-                        }
-                    });
+                    let namespace_name = CString::from_slice(namespace_name
+                                                                .get().as_bytes());
+                    let scope = unsafe {
+                        llvm::LLVMDIBuilderCreateNameSpace(
+                            DIB(cx),
+                            parent_scope,
+                            namespace_name.as_ptr(),
+                            // cannot reconstruct file ...
+                            ptr::null_mut(),
+                            // ... or line information, but that's not so important.
+                            0)
+                    };
 
                     let node = Rc::new(NamespaceTreeNode {
                         name: name,
@@ -4128,7 +4038,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
 pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
     if needs_gdb_debug_scripts_section(ccx) {
-        let empty = b"".to_c_str();
+        let empty = CString::from_slice(b"");
         let gdb_debug_scripts_section_global =
             get_or_insert_gdb_debug_scripts_section_global(ccx);
         unsafe {
@@ -4145,14 +4055,15 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
 /// section.
 fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
                                                   -> llvm::ValueRef {
-    let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str();
+    let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
 
     let section_var = unsafe {
-        llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr())
+        llvm::LLVMGetNamedGlobal(ccx.llmod(),
+                                 section_var_name.as_ptr() as *const _)
     };
 
     if section_var == ptr::null_mut() {
-        let section_name = b".debug_gdb_scripts".to_c_str();
+        let section_name = b".debug_gdb_scripts\0";
         let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
 
         unsafe {
@@ -4160,8 +4071,9 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
                                         section_contents.len() as u64);
             let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
                                                   llvm_type.to_ref(),
-                                                  section_var_name.as_ptr());
-            llvm::LLVMSetSection(section_var, section_name.as_ptr());
+                                                  section_var_name.as_ptr()
+                                                    as *const _);
+            llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
             llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
index c525e6fcfe36ac0fe39225d89ea9188e906e6c2b..9221ae09df98aa7ad3f5ec174cc86ae605911785 100644 (file)
@@ -54,7 +54,7 @@
 use trans::tvec;
 use trans::type_of;
 use middle::ty::{struct_fields, tup_fields};
-use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustAddEnv, AutoUnsafe};
+use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AutoUnsafe};
 use middle::ty::{AutoPtr};
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
@@ -179,9 +179,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            datum.to_string(bcx.ccx()),
            adjustment.repr(bcx.tcx()));
     match adjustment {
-        AdjustAddEnv(def_id, _) => {
-            datum = unpack_datum!(bcx, add_env(bcx, def_id, expr, datum));
-        }
         AdjustReifyFnPointer(_def_id) => {
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
@@ -476,22 +473,6 @@ fn unsize_unique_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
         DatumBlock::new(bcx, scratch.to_expr_datum())
     }
-
-    fn add_env<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                           def_id: ast::DefId,
-                           expr: &ast::Expr,
-                           datum: Datum<'tcx, Expr>)
-                           -> DatumBlock<'blk, 'tcx, Expr> {
-        // This is not the most efficient thing possible; since closures
-        // are two words it'd be better if this were compiled in
-        // 'dest' mode, but I can't find a nice way to structure the
-        // code and keep it DRY that accommodates that use case at the
-        // moment.
-
-        let closure_ty = expr_ty_adjusted(bcx, expr);
-        let fn_ptr = datum.to_llscalarish(bcx);
-        closure::make_closure_from_bare_fn(bcx, closure_ty, def_id, fn_ptr)
-    }
 }
 
 /// Translates an expression in "lvalue" mode -- meaning that it returns a reference to the memory
@@ -853,7 +834,9 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match def {
         def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
         def::DefStruct(_) | def::DefVariant(..) => {
-            trans_def_fn_unadjusted(bcx, ref_expr, def)
+            let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
+                                                bcx.fcx.param_substs);
+            DatumBlock::new(bcx, datum.to_expr_datum())
         }
         def::DefStatic(did, _) => {
             // There are two things that may happen here:
@@ -1250,7 +1233,9 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let variant_info = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
             if variant_info.args.len() > 0u {
                 // N-ary variant.
-                let llfn = callee::trans_fn_ref(bcx, vid, ExprId(ref_expr.id));
+                let llfn = callee::trans_fn_ref(bcx.ccx(), vid,
+                                                ExprId(ref_expr.id),
+                                                bcx.fcx.param_substs).val;
                 Store(bcx, llfn, lldest);
                 return bcx;
             } else {
@@ -1281,34 +1266,33 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       ref_expr: &ast::Expr,
-                                       def: def::Def)
-                                       -> DatumBlock<'blk, 'tcx, Expr> {
+pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                         ref_expr: &ast::Expr,
+                                         def: def::Def,
+                                         param_substs: &subst::Substs<'tcx>)
+                                         -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
-    let llfn = match def {
+    match def {
         def::DefFn(did, _) |
         def::DefStruct(did) | def::DefVariant(_, did, _) |
         def::DefStaticMethod(did, def::FromImpl(_)) |
         def::DefMethod(did, _, def::FromImpl(_)) => {
-            callee::trans_fn_ref(bcx, did, ExprId(ref_expr.id))
+            callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
         def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) |
         def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => {
-            meth::trans_static_method_callee(bcx, impl_did,
-                                             trait_did, ref_expr.id)
+            meth::trans_static_method_callee(ccx, impl_did,
+                                             trait_did, ref_expr.id,
+                                             param_substs)
         }
         _ => {
-            bcx.tcx().sess.span_bug(ref_expr.span, format!(
+            ccx.tcx().sess.span_bug(ref_expr.span, format!(
                     "trans_def_fn_unadjusted invoked on: {} for {}",
                     def,
-                    ref_expr.repr(bcx.tcx()))[]);
+                    ref_expr.repr(ccx.tcx()))[]);
         }
-    };
-
-    let fn_ty = expr_ty(bcx, ref_expr);
-    DatumBlock::new(bcx, Datum::new(llfn, fn_ty, RvalueExpr(Rvalue::new(ByValue))))
+    }
 }
 
 /// Translates a reference to a local variable or argument. This always results in an lvalue datum.
index a4cfec791d8172e5fa32385e83eac4fa7f98cdd3..1c9be6ae4a8ba5e357566cf1ff2d65834ac56020 100644 (file)
 use trans::type_of::*;
 use trans::type_of;
 use middle::ty::{self, Ty};
-use middle::subst::{Substs};
+use middle::subst::Substs;
+
+use std::ffi::CString;
 use std::cmp;
-use std::c_str::ToCStr;
 use libc::c_uint;
 use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
 use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
@@ -132,9 +133,9 @@ pub fn register_static(ccx: &CrateContext,
             };
             unsafe {
                 // Declare a symbol `foo` with the desired linkage.
-                let g1 = ident.get().with_c_str(|buf| {
-                    llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
-                });
+                let buf = CString::from_slice(ident.get().as_bytes());
+                let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
+                                             buf.as_ptr());
                 llvm::SetLinkage(g1, linkage);
 
                 // Declare an internal global `extern_with_linkage_foo` which
@@ -145,9 +146,9 @@ pub fn register_static(ccx: &CrateContext,
                 // zero.
                 let mut real_name = "_rust_extern_with_linkage_".to_string();
                 real_name.push_str(ident.get());
-                let g2 = real_name.with_c_str(|buf| {
-                    llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
-                });
+                let real_name = CString::from_vec(real_name.into_bytes());
+                let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
+                                             real_name.as_ptr());
                 llvm::SetLinkage(g2, llvm::InternalLinkage);
                 llvm::LLVMSetInitializer(g2, g1);
                 g2
@@ -155,9 +156,8 @@ pub fn register_static(ccx: &CrateContext,
         }
         None => unsafe {
             // Generate an external declaration.
-            ident.get().with_c_str(|buf| {
-                llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
-            })
+            let buf = CString::from_slice(ident.get().as_bytes());
+            llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
         }
     }
 }
@@ -606,9 +606,9 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         //         return r;
         //     }
 
-        let the_block =
-            "the block".with_c_str(
-                |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s));
+        let ptr = "the block\0".as_ptr();
+        let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn,
+                                                            ptr as *const _);
 
         let builder = ccx.builder();
         builder.position_at_end(the_block);
index 0ff53a1af7118190f82f8f630224815677a14ec5..2fd9031fdfe4cc7f6e74fc1d70c40da040c26ad0 100644 (file)
@@ -26,6 +26,7 @@
 use trans::callee;
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
+use trans::consts;
 use trans::common::*;
 use trans::datum;
 use trans::debuginfo;
@@ -39,8 +40,8 @@
 use util::ppaux;
 
 use arena::TypedArena;
-use std::c_str::ToCStr;
 use libc::c_uint;
+use std::ffi::CString;
 use syntax::ast;
 use syntax::parse::token;
 
@@ -440,18 +441,6 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                                                          v0,
                                                          t,
                                                          |bb, vv, tt| drop_ty(bb, vv, tt, None)),
-        ty::ty_closure(ref f) if f.store == ty::UniqTraitStore => {
-            let box_cell_v = GEPi(bcx, v0, &[0u, abi::FAT_PTR_EXTRA]);
-            let env = Load(bcx, box_cell_v);
-            let env_ptr_ty = Type::at_box(bcx.ccx(), Type::i8(bcx.ccx())).ptr_to();
-            let env = PointerCast(bcx, env, env_ptr_ty);
-            with_cond(bcx, IsNotNull(bcx, env), |bcx| {
-                let dtor_ptr = GEPi(bcx, env, &[0u, abi::BOX_FIELD_DROP_GLUE]);
-                let dtor = Load(bcx, dtor_ptr);
-                Call(bcx, dtor, &[PointerCast(bcx, box_cell_v, Type::i8p(bcx.ccx()))], None);
-                bcx
-            })
-        }
         ty::ty_trait(..) => {
             // No need to do a null check here (as opposed to the Box<trait case
             // above), because this happens for a trait field in an unsized
@@ -497,11 +486,11 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
     debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
-    let gvar = name.with_c_str(|buf| {
-        unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), buf)
-        }
-    });
+    let buf = CString::from_slice(name.as_bytes());
+    let gvar = unsafe {
+        llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
+                            buf.as_ptr())
+    };
     note_unique_llvm_symbol(ccx, name);
 
     let ty_name = token::intern_and_get_ident(
@@ -530,13 +519,14 @@ fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
     return (fn_nm, llfn);
 }
 
-fn make_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                               t: Ty<'tcx>,
-                               llfn: ValueRef,
-                               helper: for<'blk> |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|
-                                                  -> Block<'blk, 'tcx>,
-                               name: &str)
-                               -> ValueRef {
+fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>,
+                                  t: Ty<'tcx>,
+                                  llfn: ValueRef,
+                                  helper: F,
+                                  name: &str)
+                                  -> ValueRef where
+    F: for<'blk> FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
+{
     let _icx = push_ctxt("make_generic_glue");
     let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t));
     let _s = StatRecorder::new(ccx, glue_name);
@@ -577,9 +567,7 @@ pub fn emit_tydescs(ccx: &CrateContext) {
         // before being put into the tydesc because we only have a singleton
         // tydesc type. Then we'll recast each function to its real type when
         // calling it.
-        let drop_glue = unsafe {
-            llvm::LLVMConstPointerCast(get_drop_glue(ccx, ti.ty), glue_fn_ty.to_ref())
-        };
+        let drop_glue = consts::ptrcast(get_drop_glue(ccx, ti.ty), glue_fn_ty);
         ccx.stats().n_real_glues.set(ccx.stats().n_real_glues.get() + 1);
 
         let tydesc = C_named_struct(ccx.tydesc_type(),
index bde9051ec74d6a65c5a95aaa07f81445a688fc87..dd1cfc5ad6d823db5c4643adefed5e512d990712 100644 (file)
@@ -40,7 +40,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
     let csearch_result =
         csearch::maybe_get_item_ast(
             ccx.tcx(), fn_id,
-            |a,b,c,d| astencode::decode_inlined_item(a, b, c, d));
+            box |a,b,c,d| astencode::decode_inlined_item(a, b, c, d));
 
     let inline_def = match csearch_result {
         csearch::not_found => {
index ca17f3558aef29a53fe6c8c7469663c4618ee28d..f6d69959dadf9ecec5607e0b0a17cdb6f03a7240 100644 (file)
@@ -34,7 +34,7 @@
 use middle::ty::MethodCall;
 use util::ppaux::Repr;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::rc::Rc;
 use syntax::abi::{Rust, RustCall};
 use syntax::parse::token;
@@ -122,9 +122,10 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ty::MethodStaticUnboxedClosure(did) => {
             Callee {
                 bcx: bcx,
-                data: Fn(callee::trans_fn_ref(bcx,
+                data: Fn(callee::trans_fn_ref(bcx.ccx(),
                                               did,
-                                              MethodCallKey(method_call))),
+                                              MethodCallKey(method_call),
+                                              bcx.fcx.param_substs).val),
             }
         }
 
@@ -166,30 +167,31 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-pub fn trans_static_method_callee(bcx: Block,
-                                  method_id: ast::DefId,
-                                  trait_id: ast::DefId,
-                                  expr_id: ast::NodeId)
-                                  -> ValueRef
+pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                            method_id: ast::DefId,
+                                            trait_id: ast::DefId,
+                                            expr_id: ast::NodeId,
+                                            param_substs: &subst::Substs<'tcx>)
+                                            -> Datum<'tcx, Rvalue>
 {
     let _icx = push_ctxt("meth::trans_static_method_callee");
-    let ccx = bcx.ccx();
+    let tcx = ccx.tcx();
 
     debug!("trans_static_method_callee(method_id={}, trait_id={}, \
             expr_id={})",
            method_id,
-           ty::item_path_str(bcx.tcx(), trait_id),
+           ty::item_path_str(tcx, trait_id),
            expr_id);
 
     let mname = if method_id.krate == ast::LOCAL_CRATE {
-        match bcx.tcx().map.get(method_id.node) {
+        match tcx.map.get(method_id.node) {
             ast_map::NodeTraitItem(method) => {
                 let ident = match *method {
                     ast::RequiredMethod(ref m) => m.ident,
                     ast::ProvidedMethod(ref m) => m.pe_ident(),
                     ast::TypeTraitItem(_) => {
-                        bcx.tcx().sess.bug("trans_static_method_callee() on \
-                                            an associated type?!")
+                        tcx.sess.bug("trans_static_method_callee() on \
+                                      an associated type?!")
                     }
                 };
                 ident.name
@@ -197,7 +199,7 @@ pub fn trans_static_method_callee(bcx: Block,
             _ => panic!("callee is not a trait method")
         }
     } else {
-        csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
+        csearch::get_item_path(tcx, method_id).last().unwrap().name()
     };
     debug!("trans_static_method_callee: method_id={}, expr_id={}, \
             name={}", method_id, expr_id, token::get_name(mname));
@@ -205,7 +207,7 @@ pub fn trans_static_method_callee(bcx: Block,
     // Find the substitutions for the fn itself. This includes
     // type parameters that belong to the trait but also some that
     // belong to the method:
-    let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
+    let rcvr_substs = node_id_substs(ccx, ExprId(expr_id), param_substs);
     let subst::SeparateVecsPerParamSpace {
         types: rcvr_type,
         selfs: rcvr_self,
@@ -238,11 +240,11 @@ pub fn trans_static_method_callee(bcx: Block,
         Substs::erased(VecPerParamSpace::new(rcvr_type,
                                              rcvr_self,
                                              Vec::new()));
-    let trait_substs = bcx.tcx().mk_substs(trait_substs);
-    debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
+    let trait_substs = tcx.mk_substs(trait_substs);
+    debug!("trait_substs={}", trait_substs.repr(tcx));
     let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: trait_id,
                                                       substs: trait_substs }));
-    let vtbl = fulfill_obligation(bcx.ccx(),
+    let vtbl = fulfill_obligation(ccx,
                                   DUMMY_SP,
                                   trait_ref);
 
@@ -282,17 +284,13 @@ pub fn trans_static_method_callee(bcx: Block,
                                                      rcvr_method));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
-            let llfn = trans_fn_ref_with_substs(bcx, mth_id, ExprId(expr_id),
-                                                callee_substs);
-
-            let callee_ty = node_id_type(bcx, expr_id);
-            let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
-            PointerCast(bcx, llfn, llty)
+            trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id),
+                                     param_substs,
+                                     callee_substs)
         }
         _ => {
-            bcx.tcx().sess.bug(
-                format!("static call to invalid vtable: {}",
-                        vtbl.repr(bcx.tcx()))[]);
+            tcx.sess.bug(format!("static call to invalid vtable: {}",
+                                 vtbl.repr(tcx))[]);
         }
     }
 }
@@ -346,20 +344,22 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     bcx, MethodCallKey(method_call), vtable_impl.substs);
 
             // translate the function
-            let llfn = trans_fn_ref_with_substs(bcx,
+            let llfn = trans_fn_ref_with_substs(bcx.ccx(),
                                                 mth_id,
                                                 MethodCallKey(method_call),
-                                                callee_substs);
+                                                bcx.fcx.param_substs,
+                                                callee_substs).val;
 
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableUnboxedClosure(closure_def_id, substs) => {
             // The substitutions should have no type parameters remaining
             // after passing through fulfill_obligation
-            let llfn = trans_fn_ref_with_substs(bcx,
+            let llfn = trans_fn_ref_with_substs(bcx.ccx(),
                                                 closure_def_id,
                                                 MethodCallKey(method_call),
-                                                substs);
+                                                bcx.fcx.param_substs,
+                                                substs).val;
 
             Callee {
                 bcx: bcx,
@@ -400,7 +400,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 {
     let ccx = bcx.ccx();
 
-    let node_substs = node_id_substs(bcx, node);
+    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()));
@@ -599,8 +599,27 @@ pub fn trans_object_shim<'a, 'tcx>(
            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 fty.sig.0.inputs[1].sty {
+                    ty::ty_tup(ref tys) => tys.as_slice(),
+                    _ => {
+                        bcx.sess().bug(
+                            format!("rust-call expects a tuple not {}",
+                                    fty.sig.0.inputs[1].repr(tcx)).as_slice());
+                    }
+                }
+            }
+            _ => {
+                // skip the self parameter:
+                fty.sig.0.inputs.slice_from(1)
+            }
+        };
+
     let llargs: Vec<_> =
-        fty.sig.0.inputs[1..].iter()
+        input_tys.iter()
         .enumerate()
         .map(|(i, _)| {
             let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
@@ -609,6 +628,7 @@ pub fn trans_object_shim<'a, 'tcx>(
             llarg
         })
         .collect();
+
     assert!(!fcx.needs_ret_allocas);
 
     let dest =
@@ -684,10 +704,11 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             traits::VtableUnboxedClosure(closure_def_id, substs) => {
                 let llfn = trans_fn_ref_with_substs(
-                    bcx,
+                    bcx.ccx(),
                     closure_def_id,
                     ExprId(0),
-                    substs.clone());
+                    bcx.fcx.param_substs,
+                    substs.clone()).val;
 
                 (vec!(llfn)).into_iter()
             }
@@ -741,9 +762,9 @@ pub fn make_vtable<I: Iterator<Item=ValueRef>>(ccx: &CrateContext,
     unsafe {
         let tbl = C_struct(ccx, components[], false);
         let sym = token::gensym("vtable");
-        let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| {
-            llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf)
-        });
+        let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes());
+        let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(),
+                                          buf.as_ptr());
         llvm::LLVMSetInitializer(vt_gvar, tbl);
         llvm::LLVMSetGlobalConstant(vt_gvar, llvm::True);
         llvm::SetLinkage(vt_gvar, llvm::InternalLinkage);
@@ -788,10 +809,11 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     Some(C_null(Type::nil(ccx).ptr_to())).into_iter()
                 } else {
                     let fn_ref = trans_fn_ref_with_substs(
-                        bcx,
+                        ccx,
                         m_id,
                         ExprId(0),
-                        substs.clone());
+                        bcx.fcx.param_substs,
+                        substs.clone()).val;
 
                     // currently, at least, by-value self is not object safe
                     assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
index 51a6bc3bfd5dedd3773c8e6c19c10217bce4812e..e6db462a342da21d05c3c731077441b1da369b2f 100644 (file)
@@ -38,7 +38,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 fn_id: ast::DefId,
                                 psubsts: &subst::Substs<'tcx>,
                                 ref_id: Option<ast::NodeId>)
-    -> (ValueRef, bool) {
+    -> (ValueRef, Ty<'tcx>, bool) {
     debug!("monomorphic_fn(\
             fn_id={}, \
             real_substs={}, \
@@ -58,11 +58,14 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         params: psubsts.types.clone()
     };
 
+    let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
+    let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
+
     match ccx.monomorphized().borrow().get(&hash_id) {
         Some(&val) => {
             debug!("leaving monomorphic fn {}",
             ty::item_path_str(ccx.tcx(), fn_id));
-            return (val, false);
+            return (val, mono_ty, false);
         }
         None => ()
     }
@@ -75,8 +78,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            psubsts.repr(ccx.tcx()),
            hash_id);
 
-    let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
-    let llitem_ty = tpt.ty;
 
     let map_node = session::expect(
         ccx.sess(),
@@ -91,13 +92,12 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     if let ast_map::NodeForeignItem(_) = map_node {
         if ccx.tcx().map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic {
             // Foreign externs don't have to be monomorphized.
-            return (get_item_val(ccx, fn_id.node), true);
+            return (get_item_val(ccx, fn_id.node), mono_ty, true);
         }
     }
 
-    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
+    debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
 
-    let mono_ty = llitem_ty.subst(ccx.tcx(), psubsts);
     debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
 
     let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);
@@ -283,7 +283,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     ccx.monomorphizing().borrow_mut().insert(fn_id, depth);
 
     debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
-    (lldecl, true)
+    (lldecl, mono_ty, true)
 }
 
 #[derive(PartialEq, Eq, Hash, Show)]
index f8d0d4f5c7bf00903c8f28fe780a3efb0608ab23..e3288466aa79c6c617890e58d86360dc15303dc3 100644 (file)
@@ -19,6 +19,7 @@
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
 use trans::common::*;
+use trans::consts;
 use trans::datum::*;
 use trans::expr::{Dest, Ignore, SaveIn};
 use trans::expr;
@@ -213,15 +214,13 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match dest {
         Ignore => bcx,
         SaveIn(lldest) => {
-            unsafe {
-                let bytes = str_lit.get().len();
-                let llbytes = C_uint(bcx.ccx(), bytes);
-                let llcstr = C_cstr(bcx.ccx(), str_lit, false);
-                let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p(bcx.ccx()).to_ref());
-                Store(bcx, llcstr, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_ADDR]));
-                Store(bcx, llbytes, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_EXTRA]));
-                bcx
-            }
+            let bytes = str_lit.get().len();
+            let llbytes = C_uint(bcx.ccx(), bytes);
+            let llcstr = C_cstr(bcx.ccx(), str_lit, false);
+            let llcstr = consts::ptrcast(llcstr, Type::i8p(bcx.ccx()));
+            Store(bcx, llcstr, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_ADDR]));
+            Store(bcx, llbytes, GEPi(bcx, lldest, &[0u, abi::FAT_PTR_EXTRA]));
+            bcx
         }
     }
 }
@@ -417,15 +416,14 @@ pub fn get_base_and_len(bcx: Block,
     }
 }
 
-pub type iter_vec_block<'a, 'blk, 'tcx> =
-    |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'blk, 'tcx>;
-
-pub fn iter_vec_loop<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                                      data_ptr: ValueRef,
                                      vt: &VecTypes<'tcx>,
                                      count: ValueRef,
-                                     f: iter_vec_block<'a, 'blk, 'tcx>)
-                                     -> Block<'blk, 'tcx> {
+                                     f: F)
+                                     -> Block<'blk, 'tcx> where
+    F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
+{
     let _icx = push_ctxt("tvec::iter_vec_loop");
     let fcx = bcx.fcx;
 
@@ -476,12 +474,14 @@ pub fn iter_vec_loop<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     next_bcx
 }
 
-pub fn iter_vec_raw<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    data_ptr: ValueRef,
-                                    unit_ty: Ty<'tcx>,
-                                    len: ValueRef,
-                                    f: iter_vec_block<'a, 'blk, 'tcx>)
-                                    -> Block<'blk, 'tcx> {
+pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
+                                   data_ptr: ValueRef,
+                                   unit_ty: Ty<'tcx>,
+                                   len: ValueRef,
+                                   f: F)
+                                   -> Block<'blk, 'tcx> where
+    F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
+{
     let _icx = push_ctxt("tvec::iter_vec_raw");
     let fcx = bcx.fcx;
 
index 5b76f5bb8270e77b12f76f81cf664a3cb8aec423..3785c2fb9bc54e5b633e3dd36099266ed2840dec 100644 (file)
@@ -19,7 +19,7 @@
 
 use syntax::ast;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::mem;
 use std::cell::RefCell;
 use std::iter::repeat;
@@ -157,7 +157,8 @@ pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
     }
 
     pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
-        ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s)))
+        let name = CString::from_slice(name.as_bytes());
+        ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
     }
 
     pub fn empty_struct(ccx: &CrateContext) -> Type {
index fbbf2ac80d51e278fca7df3504fe0d16417188f6..3e499ea8498fbad9355e18cf6204370fb9db8573 100644 (file)
@@ -143,13 +143,6 @@ 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_closure(ref f) => {
-            type_of_rust_fn(cx,
-                            Some(Type::i8p(cx)),
-                            f.sig.0.inputs.as_slice(),
-                            f.sig.0.output,
-                            f.abi)
-        }
         ty::ty_bare_fn(_, ref f) => {
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
@@ -207,7 +200,6 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
         }
 
         ty::ty_bare_fn(..) => Type::i8p(cx),
-        ty::ty_closure(..) => Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false),
 
         ty::ty_vec(ty, Some(size)) => {
             let llty = sizing_type_of(cx, ty);
@@ -369,10 +361,6 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
       ty::ty_bare_fn(..) => {
           type_of_fn_from_ty(cx, t).ptr_to()
       }
-      ty::ty_closure(_) => {
-          let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
-          Type::struct_(cx, &[fn_ty, Type::i8p(cx)], false)
-      }
       ty::ty_tup(ref tys) if tys.is_empty() => Type::nil(cx),
       ty::ty_tup(..) => {
           let repr = adt::represent_type(cx, t);
index 1d62733875e0047da75a52697bbd8b4107d09f89..bde834c2ff899d4c4cf15f2f473049e11fc4faac 100644 (file)
@@ -53,7 +53,8 @@
 use middle::resolve_lifetime as rl;
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::subst::{VecPerParamSpace};
-use middle::ty::{self, RegionEscape, Ty};
+use middle::traits;
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
              ShiftedRscope, BindingRscope};
 use TypeAndSubsts;
@@ -70,7 +71,9 @@
 
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
+
     fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>;
+
     fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
 
     /// Return an (optional) substitution to convert bound type parameters that
@@ -162,9 +165,9 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
     r
 }
 
-pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
-    this: &AC,
-    rscope: &RS,
+pub fn opt_ast_region_to_region<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     default_span: Span,
     opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
 {
@@ -241,13 +244,12 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 
 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
 /// returns an appropriate set of substitutions for this particular reference to `I`.
-fn ast_path_substs_for_ty<'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+fn ast_path_substs_for_ty<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     decl_generics: &ty::Generics<'tcx>,
     path: &ast::Path)
     -> Substs<'tcx>
-    where AC: AstConv<'tcx>, RS: RegionScope
 {
     let tcx = this.tcx();
 
@@ -285,16 +287,15 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
                                regions)
 }
 
-fn create_substs_for_ast_path<'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+fn create_substs_for_ast_path<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     span: Span,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types: Vec<Ty<'tcx>>,
     regions: Vec<ty::Region>)
- -> Substs<'tcx>
-    where AC: AstConv<'tcx>, RS: RegionScope
+    -> Substs<'tcx>
 {
     let tcx = this.tcx();
 
@@ -408,13 +409,12 @@ struct ConvertedBinding<'tcx> {
     span: Span,
 }
 
-fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
-                                                    rscope: &RS,
-                                                    data: &ast::AngleBracketedParameterData)
-                                                    -> (Vec<ty::Region>,
-                                                        Vec<Ty<'tcx>>,
-                                                        Vec<ConvertedBinding<'tcx>>)
-    where AC: AstConv<'tcx>, RS: RegionScope
+fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
+                                            rscope: &RegionScope,
+                                            data: &ast::AngleBracketedParameterData)
+                                            -> (Vec<ty::Region>,
+                                                Vec<Ty<'tcx>>,
+                                                Vec<ConvertedBinding<'tcx>>)
 {
     let regions: Vec<_> =
         data.lifetimes.iter()
@@ -468,12 +468,11 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
     (implied_output_region, lifetimes_for_params)
 }
 
-fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
-                                             implied_output_region: Option<ty::Region>,
-                                             param_lifetimes: Vec<(String, uint)>,
-                                             ty: &ast::Ty)
-                                             -> Ty<'tcx>
-    where AC: AstConv<'tcx>
+fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
+                                          implied_output_region: Option<ty::Region>,
+                                          param_lifetimes: Vec<(String, uint)>,
+                                          ty: &ast::Ty)
+                                          -> Ty<'tcx>
 {
     match implied_output_region {
         Some(implied_output_region) => {
@@ -490,10 +489,9 @@ fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
     }
 }
 
-fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
-                                             data: &ast::ParenthesizedParameterData)
-                                             -> Vec<Ty<'tcx>>
-    where AC: AstConv<'tcx>
+fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
+                                          data: &ast::ParenthesizedParameterData)
+                                          -> Vec<Ty<'tcx>>
 {
     let binding_rscope = BindingRscope::new();
     let inputs = data.inputs.iter()
@@ -517,14 +515,13 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
     vec![input_ty, output]
 }
 
-pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+pub fn instantiate_poly_trait_ref<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     ast_trait_ref: &ast::PolyTraitRef,
     self_ty: Option<Ty<'tcx>>,
     poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
-    where AC: AstConv<'tcx>, RS: RegionScope
 {
     let mut projections = Vec::new();
 
@@ -545,14 +542,13 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
 ///
 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
 /// are disallowed. Otherwise, they are pushed onto the vector given.
-pub fn instantiate_trait_ref<'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+pub fn instantiate_trait_ref<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     ast_trait_ref: &ast::TraitRef,
     self_ty: Option<Ty<'tcx>>,
     projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
-    where AC: AstConv<'tcx>, RS: RegionScope
 {
     match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
         def::DefTrait(trait_def_id) => {
@@ -573,15 +569,14 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(
     }
 }
 
-fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+fn ast_path_to_trait_ref<'a,'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
     path: &ast::Path,
     mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
-    where AC: AstConv<'tcx>, RS: RegionScope
 {
     debug!("ast_path_to_trait_ref {}", path);
     let trait_def = this.get_trait_def(trait_def_id);
@@ -632,7 +627,8 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
         }
         Some(ref mut v) => {
             for binding in assoc_bindings.iter() {
-                match ast_type_binding_to_projection_predicate(this, trait_ref.clone(), binding) {
+                match ast_type_binding_to_projection_predicate(this, trait_ref.clone(),
+                                                               self_ty, binding) {
                     Ok(pp) => { v.push(pp); }
                     Err(ErrorReported) => { }
                 }
@@ -643,13 +639,15 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
     trait_ref
 }
 
-pub fn ast_type_binding_to_projection_predicate<'tcx,AC>(
-    this: &AC,
-    trait_ref: Rc<ty::TraitRef<'tcx>>,
+fn ast_type_binding_to_projection_predicate<'tcx>(
+    this: &AstConv<'tcx>,
+    mut trait_ref: Rc<ty::TraitRef<'tcx>>,
+    self_ty: Option<Ty<'tcx>>,
     binding: &ConvertedBinding<'tcx>)
     -> Result<ty::ProjectionPredicate<'tcx>, ErrorReported>
-    where AC : AstConv<'tcx>
 {
+    let tcx = this.tcx();
+
     // Given something like `U : SomeTrait<T=X>`, we want to produce a
     // predicate like `<U as SomeTrait>::T = X`. This is somewhat
     // subtle in the event that `T` is defined in a supertrait of
@@ -666,29 +664,93 @@ pub fn ast_type_binding_to_projection_predicate<'tcx,AC>(
     //
     // We want to produce `<B as SuperTrait<int>>::T == foo`.
 
-    // FIXME(#19541): supertrait upcasting not actually impl'd :)
+    // Simple case: X is defined in the current trait.
+    if trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
+        return Ok(ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                trait_ref: trait_ref,
+                item_name: binding.item_name,
+            },
+            ty: binding.ty,
+        });
+    }
 
-    if !trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
-        this.tcx().sess.span_err(
+    // Otherwise, we have to walk through the supertraits to find
+    // those that do.  This is complicated by the fact that, for an
+    // object type, the `Self` type is not present in the
+    // substitutions (after all, it's being constructed right now),
+    // but the `supertraits` iterator really wants one. To handle
+    // this, we currently insert a dummy type and then remove it
+    // later. Yuck.
+
+    let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0));
+    if self_ty.is_none() { // if converting for an object type
+        let mut dummy_substs = trait_ref.substs.clone();
+        assert!(dummy_substs.self_ty().is_none());
+        dummy_substs.types.push(SelfSpace, dummy_self_ty);
+        trait_ref = Rc::new(ty::TraitRef::new(trait_ref.def_id,
+                                              tcx.mk_substs(dummy_substs)));
+    }
+
+    let mut candidates: Vec<ty::PolyTraitRef> =
+        traits::supertraits(tcx, trait_ref.to_poly_trait_ref())
+        .filter(|r| trait_defines_associated_type_named(this, r.def_id(), binding.item_name))
+        .collect();
+
+    // If converting for an object type, then remove the dummy-ty from `Self` now.
+    // Yuckety yuck.
+    if self_ty.is_none() {
+        for candidate in candidates.iter_mut() {
+            let mut dummy_substs = candidate.0.substs.clone();
+            assert!(dummy_substs.self_ty() == Some(dummy_self_ty));
+            dummy_substs.types.pop(SelfSpace);
+            *candidate = ty::Binder(Rc::new(ty::TraitRef::new(candidate.def_id(),
+                                                              tcx.mk_substs(dummy_substs))));
+        }
+    }
+
+    if candidates.len() > 1 {
+        tcx.sess.span_err(
+            binding.span,
+            format!("ambiguous associated type: `{}` defined in multiple supertraits `{}`",
+                    token::get_name(binding.item_name),
+                    candidates.user_string(tcx)).as_slice());
+        return Err(ErrorReported);
+    }
+
+    let candidate = match candidates.pop() {
+        Some(c) => c,
+        None => {
+            tcx.sess.span_err(
+                binding.span,
+                format!("no associated type `{}` defined in `{}`",
+                        token::get_name(binding.item_name),
+                        trait_ref.user_string(tcx)).as_slice());
+            return Err(ErrorReported);
+        }
+    };
+
+    if ty::binds_late_bound_regions(tcx, &candidate) {
+        tcx.sess.span_err(
             binding.span,
-            format!("no associated type `{}` defined in `{}`",
+            format!("associated type `{}` defined in higher-ranked supertrait `{}`",
                     token::get_name(binding.item_name),
-                    trait_ref.user_string(this.tcx())).as_slice());
+                    candidate.user_string(tcx)).as_slice());
         return Err(ErrorReported);
     }
 
     Ok(ty::ProjectionPredicate {
         projection_ty: ty::ProjectionTy {
-            trait_ref: trait_ref,
+            trait_ref: candidate.0,
             item_name: binding.item_name,
         },
         ty: binding.ty,
     })
 }
 
-pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
-    this: &AC,
-    rscope: &RS,
+pub fn ast_path_to_ty<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     did: ast::DefId,
     path: &ast::Path)
     -> TypeAndSubsts<'tcx>
@@ -712,13 +774,12 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 /// and/or region variables are substituted.
 ///
 /// This is used when checking the constructor in struct literals.
-pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
-    this: &AC,
-    rscope: &RS,
+pub fn ast_path_to_ty_relaxed<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     did: ast::DefId,
     path: &ast::Path)
     -> TypeAndSubsts<'tcx>
-    where AC : AstConv<'tcx>, RS : RegionScope
 {
     let tcx = this.tcx();
     let ty::TypeScheme {
@@ -754,9 +815,9 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
 
 /// Converts the given AST type to a built-in type. A "built-in type" is, at
 /// present, either a core numeric type, a string, or `Box`.
-pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
-        this: &AC,
-        rscope: &RS,
+pub fn ast_ty_to_builtin_ty<'tcx>(
+        this: &AstConv<'tcx>,
+        rscope: &RegionScope,
         ast_ty: &ast::Ty)
         -> Option<Ty<'tcx>> {
     match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
@@ -807,12 +868,11 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 
 type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
 
-fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
-                                   rscope: &RS,
-                                   ty: &ast::Ty,
-                                   bounds: &[ast::TyParamBound])
-                                   -> Result<TraitAndProjections<'tcx>, ErrorReported>
-    where AC : AstConv<'tcx>, RS : RegionScope
+fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
+                             rscope: &RegionScope,
+                             ty: &ast::Ty,
+                             bounds: &[ast::TyParamBound])
+                             -> Result<TraitAndProjections<'tcx>, ErrorReported>
 {
     /*!
      * In a type like `Foo + Send`, we want to wait to collect the
@@ -878,14 +938,13 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
     }
 }
 
-fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
-                                        rscope: &RS,
-                                        span: Span,
-                                        trait_ref: ty::PolyTraitRef<'tcx>,
-                                        projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
-                                        bounds: &[ast::TyParamBound])
-                                        -> Ty<'tcx>
-    where AC : AstConv<'tcx>, RS : RegionScope
+fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
+                                  rscope: &RegionScope,
+                                  span: Span,
+                                  trait_ref: ty::PolyTraitRef<'tcx>,
+                                  projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
+                                  bounds: &[ast::TyParamBound])
+                                  -> Ty<'tcx>
 {
     let existential_bounds = conv_existential_bounds(this,
                                                      rscope,
@@ -909,6 +968,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 {
     let tcx = this.tcx();
     let ty_param_def_id = provenance.def_id();
+
     let mut suitable_bounds: Vec<_>;
     let ty_param_name: ast::Name;
     { // contain scope of refcell:
@@ -916,13 +976,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         let ty_param_def = &ty_param_defs[ty_param_def_id.node];
         ty_param_name = ty_param_def.name;
 
-        // FIXME(#19541): we should consider associated types in
-        // super-traits. Probably by elaborating the bounds.
-
+        // FIXME(#20300) -- search where clauses, not bounds
         suitable_bounds =
-            ty_param_def.bounds.trait_bounds // FIXME(#20300) -- search where clauses, not bounds
-            .iter()
-            .cloned()
+            traits::transitive_bounds(tcx, ty_param_def.bounds.trait_bounds.as_slice())
             .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
             .collect();
     }
@@ -963,12 +1019,11 @@ fn trait_defines_associated_type_named(this: &AstConv,
     trait_def.associated_type_names.contains(&assoc_name)
 }
 
-fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
-                           rscope: &RS,
-                           ast_ty: &ast::Ty, // the TyQPath
-                           qpath: &ast::QPath)
-                           -> Ty<'tcx>
-    where AC: AstConv<'tcx>, RS: RegionScope
+fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
+                     rscope: &RegionScope,
+                     ast_ty: &ast::Ty, // the TyQPath
+                     qpath: &ast::QPath)
+                     -> Ty<'tcx>
 {
     debug!("qpath_to_ty(ast_ty={})",
            ast_ty.repr(this.tcx()));
@@ -992,8 +1047,8 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
 
 // Parses the programmer's textual representation of a type into our
 // internal notion of a type.
-pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
-        this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>
+pub fn ast_ty_to_ty<'tcx>(
+        this: &AstConv<'tcx>, rscope: &RegionScope, ast_ty: &ast::Ty) -> Ty<'tcx>
 {
     debug!("ast_ty_to_ty(ast_ty={})",
            ast_ty.repr(this.tcx()));
@@ -1057,28 +1112,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                 let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
                 ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
             }
-            ast::TyClosure(ref f) => {
-                // Use corresponding trait store to figure out default bounds
-                // if none were specified.
-                let bounds = conv_existential_bounds(this,
-                                                     rscope,
-                                                     ast_ty.span,
-                                                     None,
-                                                     Vec::new(),
-                                                     f.bounds.as_slice());
-                let region_bound = bounds.region_bound;
-                let fn_decl = ty_of_closure(this,
-                                            f.unsafety,
-                                            f.onceness,
-                                            bounds,
-                                            ty::RegionTraitStore(
-                                                region_bound,
-                                                ast::MutMutable),
-                                            &*f.decl,
-                                            abi::Rust,
-                                            None);
-                ty::mk_closure(tcx, fn_decl)
-            }
             ast::TyPolyTraitRef(ref bounds) => {
                 conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds[])
             }
@@ -1205,10 +1238,12 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     return typ;
 }
 
-pub fn ty_of_arg<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(this: &AC, rscope: &RS,
-                                                           a: &ast::Arg,
-                                                           expected_ty: Option<Ty<'tcx>>)
-                                                           -> Ty<'tcx> {
+pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx>,
+                       rscope: &RegionScope,
+                       a: &ast::Arg,
+                       expected_ty: Option<Ty<'tcx>>)
+                       -> Ty<'tcx>
+{
     match a.ty.node {
         ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
         ast::TyInfer => this.ty_infer(a.ty.span),
@@ -1221,14 +1256,13 @@ struct SelfInfo<'a, 'tcx> {
     explicit_self: &'a ast::ExplicitSelf,
 }
 
-pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
-                    this: &AC,
-                    unsafety: ast::Unsafety,
-                    untransformed_self_ty: Ty<'tcx>,
-                    explicit_self: &ast::ExplicitSelf,
-                    decl: &ast::FnDecl,
-                    abi: abi::Abi)
-                    -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
+pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
+                          unsafety: ast::Unsafety,
+                          untransformed_self_ty: Ty<'tcx>,
+                          explicit_self: &ast::ExplicitSelf,
+                          decl: &ast::FnDecl,
+                          abi: abi::Abi)
+                          -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
     let self_info = Some(SelfInfo {
         untransformed_self_ty: untransformed_self_ty,
         explicit_self: explicit_self,
@@ -1242,20 +1276,18 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
     (bare_fn_ty, optional_explicit_self_category.unwrap())
 }
 
-pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, unsafety: ast::Unsafety, abi: abi::Abi,
+pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi,
                                               decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> {
     let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
     bare_fn_ty
 }
 
-fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
-                           this: &AC,
-                           unsafety: ast::Unsafety,
-                           abi: abi::Abi,
-                           opt_self_info: Option<SelfInfo<'a, 'tcx>>,
-                           decl: &ast::FnDecl)
-                           -> (ty::BareFnTy<'tcx>,
-                               Option<ty::ExplicitSelfCategory>)
+fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
+                                     unsafety: ast::Unsafety,
+                                     abi: abi::Abi,
+                                     opt_self_info: Option<SelfInfo<'a, 'tcx>>,
+                                     decl: &ast::FnDecl)
+                                     -> (ty::BareFnTy<'tcx>, Option<ty::ExplicitSelfCategory>)
 {
     debug!("ty_of_method_or_bare_fn");
 
@@ -1357,12 +1389,10 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
     }, explicit_self_category_result)
 }
 
-fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>,
-                                    RS:RegionScope>(
-                                    this: &AC,
-                                    rscope: &RS,
-                                    self_info: &SelfInfo<'a, 'tcx>)
-                                    -> ty::ExplicitSelfCategory
+fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
+                                              rscope: &RegionScope,
+                                              self_info: &SelfInfo<'a, 'tcx>)
+                                              -> ty::ExplicitSelfCategory
 {
     return match self_info.explicit_self.node {
         ast::SelfStatic => ty::StaticExplicitSelfCategory,
@@ -1439,8 +1469,8 @@ fn count_modifiers(ty: Ty) -> uint {
     }
 }
 
-pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
-    this: &AC,
+pub fn ty_of_closure<'tcx>(
+    this: &AstConv<'tcx>,
     unsafety: ast::Unsafety,
     onceness: ast::Onceness,
     bounds: ty::ExistentialBounds<'tcx>,
@@ -1501,9 +1531,9 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
 /// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
 /// for closures. Eventually this should all be normalized, I think, so that there is no "main
 /// trait ref" and instead we just have a flat list of bounds as the existential type.
-pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
-    this: &AC,
-    rscope: &RS,
+pub fn conv_existential_bounds<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     span: Span,
     principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
     projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
@@ -1517,13 +1547,12 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
         this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
 }
 
-fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
-    this: &AC,
-    rscope: &RS,
+fn conv_ty_poly_trait_ref<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     span: Span,
     ast_bounds: &[ast::TyParamBound])
     -> Ty<'tcx>
-    where AC: AstConv<'tcx>, RS:RegionScope
 {
     let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
 
@@ -1556,15 +1585,14 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
     }
 }
 
-pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
-    this: &AC,
-    rscope: &RS,
+pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     span: Span,
     principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
     mut projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
     partitioned_bounds: PartitionedBounds)
     -> ty::ExistentialBounds<'tcx>
-    where AC: AstConv<'tcx>, RS:RegionScope
 {
     let PartitionedBounds { builtin_bounds,
                             trait_bounds,
@@ -1657,9 +1685,9 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
 /// A version of `compute_opt_region_bound` for use where some region bound is required
 /// (existential types, basically). Reports an error if no region bound can be derived and we are
 /// in an `rscope` that does not provide a default.
-fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
-    this: &AC,
-    rscope: &RS,
+fn compute_region_bound<'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
     span: Span,
     region_bounds: &[&ast::Lifetime],
     principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for closures
index d8b410abf84492056bb9d57b9790eb5531cba866..aef856b2b2bfcd0262af44d0012e3316bee0c718 100644 (file)
@@ -30,7 +30,9 @@
 use syntax::ptr::P;
 
 pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
-                           pat: &ast::Pat, expected: Ty<'tcx>) {
+                           pat: &ast::Pat,
+                           expected: Ty<'tcx>)
+{
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
@@ -46,6 +48,19 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             check_expr(fcx, &**lt);
             let expr_ty = fcx.expr_ty(&**lt);
             fcx.write_ty(pat.id, expr_ty);
+
+            // somewhat surprising: in this case, the subtyping
+            // relation goes the opposite way as the other
+            // cases. Actually what we really want is not a subtyping
+            // relation at all but rather that there exists a LUB (so
+            // that they can be compared). However, in practice,
+            // constants are always scalars or strings.  For scalars
+            // subtyping is irrelevant, and for strings `expr_ty` is
+            // type is `&'static str`, so if we say that
+            //
+            //     &'static str <: expected
+            //
+            // that's equivalent to there existing a LUB.
             demand::suptype(fcx, pat.span, expected, expr_ty);
         }
         ast::PatRange(ref begin, ref end) => {
@@ -54,10 +69,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
             let lhs_ty = fcx.expr_ty(&**begin);
             let rhs_ty = fcx.expr_ty(&**end);
-            if require_same_types(
-                tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty,
-                || "mismatched types in range".to_string())
-                && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(rhs_ty)) {
+
+            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 valid_range_bounds(fcx.ccx, &**begin, &**end) {
                     Some(false) => {
                         span_err!(tcx.sess, begin.span, E0030,
@@ -71,17 +92,29 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 }
             } else {
                 span_err!(tcx.sess, begin.span, E0029,
-                    "only char and numeric types are allowed in range");
+                          "only char and numeric types are allowed in range");
             }
 
             fcx.write_ty(pat.id, lhs_ty);
+
+            // subtyping doens't matter here, as the value is some kind of scalar
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
             let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
             let const_scheme = ty::lookup_item_type(tcx, const_did);
-            fcx.write_ty(pat.id, const_scheme.ty);
-            demand::suptype(fcx, pat.span, expected, const_scheme.ty);
+            assert!(const_scheme.generics.is_empty());
+            let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
+                                                           &Substs::empty(),
+                                                           &const_scheme.ty);
+            fcx.write_ty(pat.id, const_ty);
+
+            // FIXME(#20489) -- we should limit the types here to scalars or something!
+
+            // As with PatLit, what we really want here is that there
+            // exist a LUB, but for the cases that can occur, subtype
+            // is good enough.
+            demand::suptype(fcx, pat.span, expected, const_ty);
         }
         ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
             let typ = fcx.local_ty(pat.span, pat.id);
@@ -89,20 +122,29 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 ast::BindByRef(mutbl) => {
                     // if the binding is like
                     //    ref x | ref const x | ref mut x
-                    // then the type of x is &M T where M is the mutability
-                    // and T is the expected type
+                    // then `x` is assigned a value of type `&M T` where M is the mutability
+                    // and T is the expected type.
                     let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
                     let mt = ty::mt { ty: expected, mutbl: mutbl };
                     let region_ty = ty::mk_rptr(tcx, tcx.mk_region(region_var), mt);
+
+                    // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
+                    // required. However, we use equality, which is stronger. See (*) for
+                    // an explanation.
                     demand::eqtype(fcx, pat.span, region_ty, typ);
                 }
                 // otherwise the type of x is the expected type T
                 ast::BindByValue(_) => {
+                    // As above, `T <: typeof(x)` is required but we
+                    // use equality, see (*) below.
                     demand::eqtype(fcx, pat.span, expected, typ);
                 }
             }
+
             fcx.write_ty(pat.id, typ);
 
+            // if there are multiple arms, make sure they all agree on
+            // what the type of the binding `x` ought to be
             let canon_id = pcx.map[path.node];
             if canon_id != pat.id {
                 let ct = fcx.local_ty(pat.span, canon_id);
@@ -124,8 +166,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected);
         }
         ast::PatTup(ref elements) => {
-            let element_tys: Vec<_> = range(0, elements.len()).map(|_| fcx.infcx()
-                .next_ty_var()).collect();
+            let element_tys: Vec<_> =
+                range(0, elements.len()).map(|_| fcx.infcx().next_ty_var())
+                                        .collect();
             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);
@@ -138,7 +181,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let uniq_ty = ty::mk_uniq(tcx, inner_ty);
 
             if check_dereferencable(pcx, pat.span, expected, &**inner) {
-                demand::suptype(fcx, pat.span, expected, uniq_ty);
+                // Here, `demand::subtype` is good enough, but I don't
+                // think any errors can be introduced by using
+                // `demand::eqtype`.
+                demand::eqtype(fcx, pat.span, expected, uniq_ty);
                 fcx.write_ty(pat.id, uniq_ty);
                 check_pat(pcx, &**inner, inner_ty);
             } else {
@@ -150,15 +196,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let inner_ty = fcx.infcx().next_ty_var();
 
             let mutbl =
-                ty::deref(fcx.infcx().shallow_resolve(expected), true)
-                .map_or(ast::MutImmutable, |mt| mt.mutbl);
+                ty::deref(fcx.infcx().shallow_resolve(expected), true).map(|mt| mt.mutbl)
+                                                                      .unwrap_or(ast::MutImmutable);
 
             let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
             let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
             let rptr_ty = ty::mk_rptr(tcx, tcx.mk_region(region), mt);
 
             if check_dereferencable(pcx, pat.span, expected, &**inner) {
-                demand::suptype(fcx, pat.span, expected, rptr_ty);
+                // `demand::subtype` would be good enough, but using
+                // `eqtype` turns out to be equally general. See (*)
+                // below for details.
+                demand::eqtype(fcx, pat.span, expected, rptr_ty);
                 fcx.write_ty(pat.id, rptr_ty);
                 check_pat(pcx, &**inner, inner_ty);
             } else {
@@ -181,14 +230,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
                     ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
                         ty: inner_ty,
-                        mutbl: ty::deref(expected_ty, true)
-                            .map_or(ast::MutImmutable, |mt| mt.mutbl)
+                        mutbl: ty::deref(expected_ty, true).map(|mt| mt.mutbl)
+                                                           .unwrap_or(ast::MutImmutable)
                     })
                 }
             };
 
             fcx.write_ty(pat.id, pat_ty);
-            demand::suptype(fcx, pat.span, expected, pat_ty);
+
+            // `demand::subtype` would be good enough, but using
+            // `eqtype` turns out to be equally general. See (*)
+            // below for details.
+            demand::eqtype(fcx, pat.span, expected, pat_ty);
 
             for elt in before.iter() {
                 check_pat(pcx, &**elt, inner_ty);
@@ -210,6 +263,56 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         ast::PatMac(_) => tcx.sess.bug("unexpanded macro")
     }
+
+
+    // (*) In most of the cases above (literals and constants being
+    // the exception), we relate types using strict equality, evewn
+    // though subtyping would be sufficient. There are a few reasons
+    // for this, some of which are fairly subtle and which cost me
+    // (nmatsakis) an hour or two debugging to remember, so I thought
+    // I'd write them down this time.
+    //
+    // 1. Most importantly, there is no loss of expressiveness
+    // here. What we are saying is that the type of `x`
+    // becomes *exactly* what is expected. This might seem
+    // like it will cause errors in a case like this:
+    //
+    // ```
+    // fn foo<'x>(x: &'x int) {
+    //    let a = 1;
+    //    let mut z = x;
+    //    z = &a;
+    // }
+    // ```
+    //
+    // The reason we might get an error is that `z` might be
+    // assigned a type like `&'x int`, and then we would have
+    // a problem when we try to assign `&a` to `z`, because
+    // the lifetime of `&a` (i.e., the enclosing block) is
+    // shorter than `'x`.
+    //
+    // HOWEVER, this code works fine. The reason is that the
+    // expected type here is whatever type the user wrote, not
+    // the initializer's type. In this case the user wrote
+    // nothing, so we are going to create a type variable `Z`.
+    // Then we will assign the type of the initializer (`&'x
+    // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
+    // will instantiate `Z` as a type `&'0 int` where `'0` is
+    // a fresh region variable, with the constraint that `'x :
+    // '0`.  So basically we're all set.
+    //
+    // Note that there are two tests to check that this remains true
+    // (`regions-reassign-{match,let}-bound-pointer.rs`).
+    //
+    // 2. Things go horribly wrong if we use subtype. The reason for
+    // THIS is a fairly subtle case involving bound regions. See the
+    // `givens` field in `region_inference`, as well as the test
+    // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
+    // for details. Short version is that we must sometimes detect
+    // relationships between specific region variables and regions
+    // bound in a closure signature, and that detection gets thrown
+    // off when we substitute fresh region variables here to enable
+    // subtyping.
 }
 
 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
@@ -496,7 +599,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     // Typecheck each field.
     for &Spanned { node: ref field, span } in fields.iter() {
-        let field_type = match used_fields.entry(field.ident.name) {
+        let field_type = match used_fields.entry(&field.ident.name) {
             Occupied(occupied) => {
                 span_err!(tcx.sess, span, E0025,
                     "field `{}` bound multiple times in the pattern",
@@ -507,7 +610,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 tcx.types.err
             }
             Vacant(vacant) => {
-                vacant.set(span);
+                vacant.insert(span);
                 field_type_map.get(&field.ident.name).cloned()
                     .unwrap_or_else(|| {
                         span_err!(tcx.sess, span, E0026,
index ee93c896433a18bf95a8621d4e2a05aef066a84d..98a826355a73ac8e78719c637f9853b7e9674703 100644 (file)
@@ -8,8 +8,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use super::autoderef;
+use super::AutorefArgs;
+use super::check_argument_types;
+use super::check_expr;
+use super::check_method_argument_types;
+use super::err_args;
+use super::FnCtxt;
+use super::LvaluePreference;
+use super::method;
+use super::structurally_resolved_type;
+use super::TupleArgumentsFlag;
+use super::write_call;
+
+use middle::infer;
+use middle::ty::{mod, Ty};
 use syntax::ast;
 use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::ptr::P;
 use CrateCtxt;
 
 /// Check that it is legal to call methods of the trait corresponding
@@ -44,3 +61,164 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
                    "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
     }
 }
+
+pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                            call_expr: &ast::Expr,
+                            callee_expr: &ast::Expr,
+                            arg_exprs: &[P<ast::Expr>])
+{
+    check_expr(fcx, callee_expr);
+    let original_callee_ty = fcx.expr_ty(callee_expr);
+    let (callee_ty, _, result) =
+        autoderef(fcx,
+                  callee_expr.span,
+                  original_callee_ty,
+                  Some(callee_expr.id),
+                  LvaluePreference::NoPreference,
+                  |adj_ty, idx| {
+                      let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
+                      try_overloaded_call_step(fcx, call_expr, callee_expr,
+                                               adj_ty, autoderefref)
+                  });
+
+    match result {
+        None => {
+            // this will report an error since original_callee_ty is not a fn
+            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs);
+        }
+
+        Some(CallStep::Builtin) => {
+            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs);
+        }
+
+        Some(CallStep::Overloaded(method_callee)) => {
+            confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee);
+        }
+    }
+}
+
+enum CallStep<'tcx> {
+    Builtin,
+    Overloaded(ty::MethodCallee<'tcx>)
+}
+
+fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                      call_expr: &ast::Expr,
+                                      callee_expr: &ast::Expr,
+                                      adjusted_ty: Ty<'tcx>,
+                                      autoderefref: ty::AutoDerefRef<'tcx>)
+                                      -> Option<CallStep<'tcx>>
+{
+    // 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(..) => {
+            fcx.write_adjustment(callee_expr.id,
+                                 callee_expr.span,
+                                 ty::AdjustDerefRef(autoderefref));
+            return Some(CallStep::Builtin);
+        }
+
+        _ => {}
+    }
+
+    // Try the options that are least restrictive on the caller first.
+    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,
+        };
+
+        match method::lookup_in_trait_adjusted(fcx,
+                                               call_expr.span,
+                                               Some(&*callee_expr),
+                                               method_name,
+                                               trait_def_id,
+                                               autoderefref.clone(),
+                                               adjusted_ty,
+                                               None) {
+            None => continue,
+            Some(method_callee) => {
+                return Some(CallStep::Overloaded(method_callee));
+            }
+        }
+    }
+
+    None
+}
+
+fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+                                 call_expr: &ast::Expr,
+                                 callee_ty: Ty<'tcx>,
+                                 arg_exprs: &[P<ast::Expr>])
+{
+    let error_fn_sig;
+
+    let fn_sig = match callee_ty.sty {
+        ty::ty_bare_fn(_, &ty::BareFnTy {ref sig, ..}) => {
+            sig
+        }
+        _ => {
+            fcx.type_error_message(call_expr.span, |actual| {
+                format!("expected function, found `{}`", actual)
+            }, callee_ty, None);
+
+            // This is the "default" function signature, used in case of error.
+            // In that case, we check each argument against "error" in order to
+            // set up all the node type bindings.
+            error_fn_sig = ty::Binder(ty::FnSig {
+                inputs: err_args(fcx.tcx(), arg_exprs.len()),
+                output: ty::FnConverging(fcx.tcx().types.err),
+                variadic: false
+            });
+
+            &error_fn_sig
+        }
+    };
+
+    // Replace any late-bound regions that appear in the function
+    // signature with region variables. We also have to
+    // renormalize the associated types at this point, since they
+    // previously appeared within a `Binder<>` and hence would not
+    // have been normalized before.
+    let fn_sig =
+        fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
+                                                              infer::FnCall,
+                                                              fn_sig).0;
+    let fn_sig =
+        fcx.normalize_associated_types_in(call_expr.span, &fn_sig);
+
+    // Call the generic checker.
+    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
+    check_argument_types(fcx,
+                         call_expr.span,
+                         fn_sig.inputs[],
+                         arg_exprs.as_slice(),
+                         AutorefArgs::No,
+                         fn_sig.variadic,
+                         TupleArgumentsFlag::DontTupleArguments);
+
+    write_call(fcx, call_expr, fn_sig.output);
+}
+
+fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                    call_expr: &ast::Expr,
+                                    arg_exprs: &[P<ast::Expr>],
+                                    method_callee: ty::MethodCallee<'tcx>)
+{
+    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
+    let output_type = check_method_argument_types(fcx,
+                                                  call_expr.span,
+                                                  method_callee.ty,
+                                                  call_expr,
+                                                  arg_exprs.as_slice(),
+                                                  AutorefArgs::No,
+                                                  TupleArgumentsFlag::TupleArguments);
+    let method_call = ty::MethodCall::expr(call_expr.id);
+    fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
+    write_call(fcx, call_expr, output_type);
+}
+
index db84f1dce975110459fe775e623f1f7c19b17c71..9945e264bfc2a4ae3493f4acb1d14f53c8f4d4b0 100644 (file)
 use super::{check_fn, Expectation, FnCtxt};
 
 use astconv;
-use middle::infer;
 use middle::region::CodeExtent;
 use middle::subst;
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use rscope::RegionScope;
 use syntax::abi;
 use syntax::ast;
-use syntax::ast::CaptureClause::*;
 use syntax::ast_util;
 use util::ppaux::Repr;
 
 pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                    expr: &ast::Expr,
-                                   capture: ast::CaptureClause,
+                                   _capture: ast::CaptureClause,
                                    opt_kind: Option<ast::UnboxedClosureKind>,
                                    decl: &ast::FnDecl,
                                    body: &ast::Block,
@@ -46,30 +44,17 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             // evidence than an unboxed closure is desired, we'll use
             // that, otherwise we'll fall back to boxed closures.
             match expected_sig_and_kind {
-                None => { // doesn't look like an unboxed closure
-                    let region = astconv::opt_ast_region_to_region(fcx,
-                                                                   fcx,
-                                                                   expr.span,
-                                                                   &None);
-
-                    check_boxed_closure(fcx,
-                                        expr,
-                                        ty::RegionTraitStore(region, ast::MutMutable),
-                                        decl,
-                                        body,
-                                        expected);
-
-                    match capture {
-                        CaptureByValue => {
-                            fcx.ccx.tcx.sess.span_err(
-                                expr.span,
-                                "boxed closures can't capture by value, \
-                                if you want to use an unboxed closure, \
-                                explicitly annotate its kind: e.g. `move |:|`");
-                        },
-                        CaptureByRef => {}
-                    }
-                }
+                None => { // don't have information about the kind, request explicit annotation
+                    // NB We still need to typeck the body, so assume `FnMut` kind just for that
+                    let kind = ty::FnMutUnboxedClosureKind;
+
+                    check_unboxed_closure(fcx, expr, kind, decl, body, None);
+
+                    fcx.ccx.tcx.sess.span_err(
+                        expr.span,
+                        "can't infer the \"kind\" of the closure, explicitly annotate it. e.g. \
+                        `|&:| {}`");
+                },
                 Some((sig, kind)) => {
                     check_unboxed_closure(fcx, expr, kind, decl, body, Some(sig));
                 }
@@ -254,92 +239,3 @@ fn deduce_unboxed_closure_expectations_from_obligations<'a,'tcx>(
 
     None
 }
-
-
-fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                expr: &ast::Expr,
-                                store: ty::TraitStore,
-                                decl: &ast::FnDecl,
-                                body: &ast::Block,
-                                expected: Expectation<'tcx>) {
-    let tcx = fcx.ccx.tcx;
-
-    // Find the expected input/output types (if any). Substitute
-    // fresh bound regions for any bound regions we find in the
-    // expected types so as to avoid capture.
-    let expected_cenv = expected.map_to_option(fcx, |ty| match ty.sty {
-        ty::ty_closure(ref cenv) => Some(cenv),
-        _ => None
-    });
-    let (expected_sig, expected_onceness, expected_bounds) = match expected_cenv {
-        Some(cenv) => {
-            let (sig, _) =
-                ty::replace_late_bound_regions(
-                    tcx,
-                    &cenv.sig,
-                    |_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
-            let onceness = match (&store, &cenv.store) {
-                // As the closure type and onceness go, only three
-                // combinations are legit:
-                //      once closure
-                //      many closure
-                //      once proc
-                // If the actual and expected closure type disagree with
-                // each other, set expected onceness to be always Once or
-                // Many according to the actual type. Otherwise, it will
-                // yield either an illegal "many proc" or a less known
-                // "once closure" in the error message.
-                (&ty::UniqTraitStore, &ty::UniqTraitStore) |
-                (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
-                    cenv.onceness,
-                (&ty::UniqTraitStore, _) => ast::Once,
-                (&ty::RegionTraitStore(..), _) => ast::Many,
-            };
-            (Some(sig), onceness, cenv.bounds.clone())
-        }
-        _ => {
-            // Not an error! Means we're inferring the closure type
-            let region = fcx.infcx().next_region_var(
-                infer::AddrOfRegion(expr.span));
-            let bounds = ty::region_existential_bound(region);
-            let onceness = ast::Many;
-            (None, onceness, bounds)
-        }
-    };
-
-    // construct the function type
-    let fn_ty = astconv::ty_of_closure(fcx,
-                                       ast::Unsafety::Normal,
-                                       expected_onceness,
-                                       expected_bounds,
-                                       store,
-                                       decl,
-                                       abi::Rust,
-                                       expected_sig);
-    let fn_sig = fn_ty.sig.clone();
-    let fty = ty::mk_closure(tcx, fn_ty);
-    debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
-
-    fcx.write_ty(expr.id, fty);
-
-    // If the closure is a stack closure and hasn't had some non-standard
-    // style inferred for it, then check it under its parent's style.
-    // Otherwise, use its own
-    let (inherited_style, inherited_style_id) = match store {
-        ty::RegionTraitStore(..) => (fcx.ps.borrow().unsafety,
-                                     fcx.ps.borrow().def),
-        ty::UniqTraitStore => (ast::Unsafety::Normal, expr.id)
-    };
-
-    let fn_sig =
-        ty::liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), &fn_sig);
-
-    check_fn(fcx.ccx,
-             inherited_style,
-             inherited_style_id,
-             &fn_sig,
-             &*decl,
-             expr.id,
-             &*body,
-             fcx.inh);
-}
index 5b586bb0b669a2503468444881436e886b75605c..a51e89c1669de7cd6d4fa0d8972ab5f17c68c528 100644 (file)
 use syntax::codemap::Span;
 use util::ppaux::Repr;
 
-// Requires that the two types unify, and prints an error message if they
-// don't.
+// Requires that the two types unify, and prints an error message if
+// they don't.
 pub fn suptype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
-                         expected: Ty<'tcx>, actual: Ty<'tcx>) {
-    suptype_with_fn(fcx, sp, false, expected, actual,
+                         ty_expected: Ty<'tcx>, ty_actual: Ty<'tcx>) {
+    suptype_with_fn(fcx, sp, false, ty_expected, ty_actual,
         |sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) })
 }
 
+/// As `suptype`, but call `handle_err` if unification for subtyping fails.
 pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                     sp: Span,
                                     b_is_expected: bool,
@@ -48,9 +49,7 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
                         expected: Ty<'tcx>, actual: Ty<'tcx>) {
     match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
         Ok(()) => { /* ok */ }
-        Err(ref err) => {
-            fcx.report_mismatched_types(sp, expected, actual, err);
-        }
+        Err(ref err) => { fcx.report_mismatched_types(sp, expected, actual, err); }
     }
 }
 
index 54d2378256d3a7fef70a78cdcc7456fe4e0f6eec..adea5084aab2b54383b13b08b62248110f3e46ab 100644 (file)
@@ -462,7 +462,6 @@ 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::ty_closure(ref f) => f.sig.clone(),
             _ => return,
         };
 
index 8adb592633f5edd7070252727e7d573d6f8aa594..beb51590b4159249338029abcf52a678e6149b2f 100644 (file)
@@ -387,14 +387,18 @@ fn assemble_inherent_candidates_from_param(&mut self,
 
     // Do a search through a list of bounds, using a callback to actually
     // create the candidates.
-    fn elaborate_bounds(
+    fn elaborate_bounds<F>(
         &mut self,
         bounds: &[ty::PolyTraitRef<'tcx>],
         num_includes_types: bool,
-        mk_cand: for<'b> |this: &mut ProbeContext<'b, 'tcx>,
-                          tr: ty::PolyTraitRef<'tcx>,
-                          m: Rc<ty::Method<'tcx>>,
-                          method_num: uint|)
+        mut mk_cand: F,
+    ) where
+        F: for<'b> FnMut(
+            &mut ProbeContext<'b, 'tcx>,
+            ty::PolyTraitRef<'tcx>,
+            Rc<ty::Method<'tcx>>,
+            uint,
+        ),
     {
         debug!("elaborate_bounds(bounds={})", bounds.repr(self.tcx()));
 
index e6ae5f0a447d30c779298e248918756092d98790..1b51434a58cc130c5f20b9a73810ee4ba797b0c9 100644 (file)
@@ -699,7 +699,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
         check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
       }
-      ast::ItemImpl(_, _, _, _, ref impl_items) => {
+      ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
 
         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
@@ -1850,7 +1850,6 @@ fn register_adjustment_obligations(&self,
                                        span: Span,
                                        adj: &ty::AutoAdjustment<'tcx>) {
         match *adj {
-            ty::AdjustAddEnv(..) |
             ty::AdjustReifyFnPointer(..) => {
             }
             ty::AdjustDerefRef(ref d_r) => {
@@ -2229,7 +2228,8 @@ pub enum LvaluePreference {
 ///
 /// Note: this method does not modify the adjustments table. The caller is responsible for
 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
-pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
+                                 sp: Span,
                                  base_ty: Ty<'tcx>,
                                  expr_id: Option<ast::NodeId>,
                                  mut lvalue_pref: LvaluePreference,
@@ -2276,58 +2276,6 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     (fcx.tcx().types.err, 0, None)
 }
 
-/// Attempts to resolve a call expression as an overloaded call.
-fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                 call_expression: &ast::Expr,
-                                 callee: &ast::Expr,
-                                 callee_type: Ty<'tcx>,
-                                 args: &[&P<ast::Expr>])
-                                 -> bool {
-    // Bail out if the callee is a bare function or a closure. We check those
-    // manually.
-    match structurally_resolved_type(fcx, callee.span, callee_type).sty {
-        ty::ty_bare_fn(..) | ty::ty_closure(_) => return false,
-        _ => {}
-    }
-
-    // Try the options that are least restrictive on the caller first.
-    for &(maybe_function_trait, 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 function_trait = match maybe_function_trait {
-            None => continue,
-            Some(function_trait) => function_trait,
-        };
-        let method_callee =
-            match method::lookup_in_trait(fcx,
-                                          call_expression.span,
-                                          Some(&*callee),
-                                          method_name,
-                                          function_trait,
-                                          callee_type,
-                                          None) {
-                None => continue,
-                Some(method_callee) => method_callee,
-            };
-        let method_call = MethodCall::expr(call_expression.id);
-        let output_type = check_method_argument_types(fcx,
-                                                      call_expression.span,
-                                                      method_callee.ty,
-                                                      call_expression,
-                                                      args,
-                                                      AutorefArgs::No,
-                                                      TupleArguments);
-        fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
-        write_call(fcx, call_expression, output_type);
-
-        return true
-    }
-
-    false
-}
-
 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   span: Span,
                                   method_call: Option<MethodCall>,
@@ -2689,7 +2637,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         check_argument_types(fcx,
                              sp,
                              err_inputs[],
-                             callee_expr,
                              args_no_rcvr,
                              autoref_args,
                              false,
@@ -2702,7 +2649,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 check_argument_types(fcx,
                                      sp,
                                      fty.sig.0.inputs.slice_from(1),
-                                     callee_expr,
                                      args_no_rcvr,
                                      autoref_args,
                                      fty.sig.0.variadic,
@@ -2722,7 +2668,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   sp: Span,
                                   fn_inputs: &[Ty<'tcx>],
-                                  _callee_expr: &ast::Expr,
                                   args: &[&P<ast::Expr>],
                                   autoref_args: AutorefArgs,
                                   variadic: bool,
@@ -3106,63 +3051,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     debug!(">> typechecking: expr={} expected={}",
            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
 
-    // A generic function for doing all of the checking for call expressions
-    fn check_call(fcx: &FnCtxt,
-                  call_expr: &ast::Expr,
-                  f: &ast::Expr,
-                  args: &[&P<ast::Expr>]) {
-        // Store the type of `f` as the type of the callee
-        let fn_ty = fcx.expr_ty(f);
-
-        // Extract the function signature from `in_fty`.
-        let fn_ty = structurally_resolved_type(fcx, f.span, fn_ty);
-
-        // This is the "default" function signature, used in case of error.
-        // In that case, we check each argument against "error" in order to
-        // set up all the node type bindings.
-        let error_fn_sig = ty::Binder(FnSig {
-            inputs: err_args(fcx.tcx(), args.len()),
-            output: ty::FnConverging(fcx.tcx().types.err),
-            variadic: false
-        });
-
-        let fn_sig = match fn_ty.sty {
-            ty::ty_bare_fn(_, &ty::BareFnTy {ref sig, ..}) |
-            ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
-            _ => {
-                fcx.type_error_message(call_expr.span, |actual| {
-                    format!("expected function, found `{}`", actual)
-                }, fn_ty, None);
-                &error_fn_sig
-            }
-        };
-
-        // Replace any late-bound regions that appear in the function
-        // signature with region variables. We also have to
-        // renormalize the associated types at this point, since they
-        // previously appeared within a `Binder<>` and hence would not
-        // have been normalized before.
-        let fn_sig =
-            fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                                  infer::FnCall,
-                                                                  fn_sig).0;
-        let fn_sig =
-            fcx.normalize_associated_types_in(call_expr.span,
-                                              &fn_sig);
-
-        // Call the generic checker.
-        check_argument_types(fcx,
-                             call_expr.span,
-                             fn_sig.inputs[],
-                             f,
-                             args,
-                             AutorefArgs::No,
-                             fn_sig.variadic,
-                             DontTupleArguments);
-
-        write_call(fcx, call_expr, fn_sig.output);
-    }
-
     // Checks a method call.
     fn check_method_call(fcx: &FnCtxt,
                          expr: &ast::Expr,
@@ -4164,24 +4052,8 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         check_block_with_expected(fcx, &**b, expected);
         fcx.write_ty(id, fcx.node_ty(b.id));
       }
-      ast::ExprCall(ref f, ref args) => {
-          // Index expressions need to be handled separately, to inform them
-          // that they appear in call position.
-          check_expr(fcx, &**f);
-          let f_ty = fcx.expr_ty(&**f);
-
-          let args: Vec<_> = args.iter().map(|x| x).collect();
-          if !try_overloaded_call(fcx, expr, &**f, f_ty, args[]) {
-              check_call(fcx, expr, &**f, args[]);
-              let args_err = args.iter().fold(false,
-                 |rest_err, a| {
-                     // is this not working?
-                     let a_ty = fcx.expr_ty(&***a);
-                     rest_err || ty::type_is_error(a_ty)});
-              if ty::type_is_error(f_ty) || args_err {
-                  fcx.write_error(id);
-              }
-          }
+      ast::ExprCall(ref callee, ref args) => {
+          callee::check_call(fcx, expr, &**callee, args.as_slice());
       }
       ast::ExprMethodCall(ident, ref tps, ref args) => {
         check_method_call(fcx, expr, ident, args[], tps[], lvalue_pref);
@@ -4682,7 +4554,7 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 pub fn check_decl_initializer(fcx: &FnCtxt,
                               nid: ast::NodeId,
                               init: &ast::Expr)
-                            {
+{
     let local_ty = fcx.local_ty(init.span, nid);
     check_expr_coercable_to_type(fcx, init, local_ty)
 }
@@ -5066,7 +4938,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 Some(i) => {
                     span_err!(ccx.tcx.sess, v.span, E0081,
                         "discriminant value `{}` already exists", disr_vals[i]);
-                    span_note!(ccx.tcx.sess, ccx.tcx().map.span(variants[i].id.node),
+                    span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
                         "conflicting discriminant here")
                 }
                 None => {}
index b5ddb528c2f2f405589c33c16207c3a9ead7c722..b7397b5f9ee61468097c5b0c7b40b3b1b7896095 100644 (file)
@@ -92,7 +92,7 @@
 use middle::traits;
 use middle::ty::{ReScope};
 use middle::ty::{self, Ty, MethodCall};
-use middle::infer;
+use middle::infer::{mod, GenericKind};
 use middle::pat_util;
 use util::ppaux::{ty_to_string, Repr};
 
@@ -164,7 +164,7 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 pub struct Rcx<'a, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
 
-    region_param_pairs: Vec<(ty::Region, ty::ParamTy)>,
+    region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>,
 
     // id of innermost fn or loop
     repeating_scope: ast::NodeId,
@@ -205,7 +205,7 @@ pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
         Rcx { fcx: fcx,
               repeating_scope: initial_repeating_scope,
               subject: subject,
-              region_param_pairs: Vec::new() }
+              region_bound_pairs: Vec::new() }
     }
 
     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
@@ -286,12 +286,12 @@ fn visit_fn_body(&mut self,
             }
         };
 
-        let len = self.region_param_pairs.len();
+        let len = self.region_bound_pairs.len();
         self.relate_free_regions(fn_sig[], body.id);
         link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs[]);
         self.visit_block(body);
         self.visit_region_obligations(body.id);
-        self.region_param_pairs.truncate(len);
+        self.region_bound_pairs.truncate(len);
     }
 
     fn visit_region_obligations(&mut self, node_id: ast::NodeId)
@@ -357,11 +357,11 @@ fn relate_free_regions(&mut self,
                         // relationship that arises here, but
                         // presently we do not.)
                     }
-                    regionmanip::RegionSubParamConstraint(_, r_a, p_b) => {
-                        debug!("RegionSubParamConstraint: {} <= {}",
-                               r_a.repr(tcx), p_b.repr(tcx));
+                    regionmanip::RegionSubGenericConstraint(_, r_a, ref generic_b) => {
+                        debug!("RegionSubGenericConstraint: {} <= {}",
+                               r_a.repr(tcx), generic_b.repr(tcx));
 
-                        self.region_param_pairs.push((r_a, p_b));
+                        self.region_bound_pairs.push((r_a, generic_b.clone()));
                     }
                 }
             }
@@ -735,29 +735,6 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     let function_type = rcx.resolve_node_type(expr.id);
 
     match function_type.sty {
-        ty::ty_closure(box ty::ClosureTy{store: ty::RegionTraitStore(..),
-                                         ref bounds,
-                                         ..}) => {
-            // For closure, ensure that the variables outlive region
-            // bound, since they are captured by reference.
-            ty::with_freevars(tcx, expr.id, |freevars| {
-                if freevars.is_empty() {
-                    // No free variables means that the environment
-                    // will be NULL at runtime and hence the closure
-                    // has static lifetime.
-                } else {
-                    // Variables being referenced must outlive closure.
-                    constrain_free_variables_in_by_ref_closure(
-                        rcx, bounds.region_bound, expr, freevars);
-
-                    // Closure is stack allocated and hence cannot
-                    // outlive the appropriate temporary scope.
-                    let s = rcx.repeating_scope;
-                    rcx.fcx.mk_subr(infer::InfStackClosure(expr.span),
-                                    bounds.region_bound, ty::ReScope(CodeExtent::from_node_id(s)));
-                }
-            });
-        }
         ty::ty_unboxed_closure(_, region, _) => {
             if tcx.capture_modes.borrow()[expr.id].clone() == ast::CaptureByRef {
                 ty::with_freevars(tcx, expr.id, |freevars| {
@@ -778,11 +755,6 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     rcx.set_repeating_scope(repeating_scope);
 
     match function_type.sty {
-        ty::ty_closure(box ty::ClosureTy {ref bounds, ..}) => {
-            ty::with_freevars(tcx, expr.id, |freevars| {
-                ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
-            })
-        }
         ty::ty_unboxed_closure(_, region, _) => {
             ty::with_freevars(tcx, expr.id, |freevars| {
                 let bounds = ty::region_existential_bound(*region);
@@ -884,33 +856,11 @@ fn constrain_free_variables_in_by_ref_closure(
 
 fn constrain_callee(rcx: &mut Rcx,
                     callee_id: ast::NodeId,
-                    call_expr: &ast::Expr,
-                    callee_expr: &ast::Expr) {
-    let call_region = ty::ReScope(CodeExtent::from_node_id(call_expr.id));
-
+                    _call_expr: &ast::Expr,
+                    _callee_expr: &ast::Expr) {
     let callee_ty = rcx.resolve_node_type(callee_id);
     match callee_ty.sty {
         ty::ty_bare_fn(..) => { }
-        ty::ty_closure(ref closure_ty) => {
-            let region = match closure_ty.store {
-                ty::RegionTraitStore(r, _) => {
-                    // While we're here, link the closure's region with a unique
-                    // immutable borrow (gathered later in borrowck)
-                    let mc = mc::MemCategorizationContext::new(rcx.fcx);
-                    let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
-                    link_region(rcx, callee_expr.span, call_region,
-                                ty::UniqueImmBorrow, expr_cmt);
-                    r
-                }
-                ty::UniqTraitStore => ty::ReStatic
-            };
-            rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
-                            call_region, region);
-
-            let region = closure_ty.bounds.region_bound;
-            rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
-                            call_region, region);
-        }
         _ => {
             // this should not happen, but it does if the program is
             // erroneous
@@ -1477,31 +1427,31 @@ fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
                 rcx.fcx.mk_subr(o1, r_a, r_b);
             }
-            regionmanip::RegionSubParamConstraint(None, r_a, param_b) => {
-                param_must_outlive(rcx, origin.clone(), r_a, param_b);
+            regionmanip::RegionSubGenericConstraint(None, r_a, ref generic_b) => {
+                generic_must_outlive(rcx, origin.clone(), r_a, generic_b);
             }
-            regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => {
+            regionmanip::RegionSubGenericConstraint(Some(ty), r_a, ref generic_b) => {
                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
-                param_must_outlive(rcx, o1, r_a, param_b);
+                generic_must_outlive(rcx, o1, r_a, generic_b);
             }
         }
     }
 }
 
-fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
-                                origin: infer::SubregionOrigin<'tcx>,
-                                region: ty::Region,
-                                param_ty: ty::ParamTy) {
+fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
+                                  origin: infer::SubregionOrigin<'tcx>,
+                                  region: ty::Region,
+                                  generic: &GenericKind<'tcx>) {
     let param_env = &rcx.fcx.inh.param_env;
 
-    debug!("param_must_outlive(region={}, param_ty={})",
+    debug!("param_must_outlive(region={}, generic={})",
            region.repr(rcx.tcx()),
-           param_ty.repr(rcx.tcx()));
+           generic.repr(rcx.tcx()));
 
     // To start, collect bounds from user:
     let mut param_bounds =
         ty::required_region_bounds(rcx.tcx(),
-                                   param_ty.to_ty(rcx.tcx()),
+                                   generic.to_ty(rcx.tcx()),
                                    param_env.caller_bounds.predicates.as_slice().to_vec());
 
     // Add in the default bound of fn body that applies to all in
@@ -1517,22 +1467,21 @@ fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     //     fn foo<'a, A>(x: &'a A) { x.bar() }
     //
     // The problem is that the type of `x` is `&'a A`. To be
-    // well-formed, then, A must be lower-bounded by `'a`, but we
+    // 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_param_pairs.iter() {
-        debug!("param_ty={} p={}",
-               param_ty.repr(rcx.tcx()),
+    for &(ref r, ref p) in rcx.region_bound_pairs.iter() {
+        debug!("generic={} p={}",
+               generic.repr(rcx.tcx()),
                p.repr(rcx.tcx()));
-        if param_ty == *p {
+        if generic == p {
             param_bounds.push(*r);
         }
     }
 
-    // Inform region inference that this parameter type must be
-    // properly bounded.
-    infer::verify_param_bound(rcx.fcx.infcx(),
-                              origin,
-                              param_ty,
-                              region,
-                              param_bounds);
+    // Inform region inference that this generic must be properly
+    // bounded.
+    rcx.fcx.infcx().verify_generic_bound(origin,
+                                         generic.clone(),
+                                         region,
+                                         param_bounds);
 }
index 66cf077d4c21fbc9925cbc33b1b4d3233775d3f1..7ca21bdf5b83f7eaacac5c1114a9107cb9e25801 100644 (file)
@@ -12,6 +12,7 @@
 
 pub use self::WfConstraint::*;
 
+use middle::infer::GenericKind;
 use middle::subst::{ParamSpace, Subst, Substs};
 use middle::ty::{self, Ty};
 use middle::ty_fold::{TypeFolder};
@@ -24,7 +25,7 @@
 
 pub enum WfConstraint<'tcx> {
     RegionSubRegionConstraint(Option<Ty<'tcx>>, ty::Region, ty::Region),
-    RegionSubParamConstraint(Option<Ty<'tcx>>, ty::Region, ty::ParamTy),
+    RegionSubGenericConstraint(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
 }
 
 struct Wf<'a, 'tcx: 'a> {
@@ -67,10 +68,6 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
                 // No borrowed content reachable here.
             }
 
-            ty::ty_closure(box ref c) => {
-                self.accumulate_from_closure_ty(ty, c);
-            }
-
             ty::ty_unboxed_closure(_, region, _) => {
                 // An "unboxed closure type" is basically
                 // modeled here as equivalent to a struct like
@@ -125,8 +122,7 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
             ty::ty_projection(ref data) => {
                 // `<T as TraitRef<..>>::Name`
 
-                // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region,
-                // like a type parameter
+                self.push_projection_constraint_from_top(data);
 
                 // this seems like a minimal requirement:
                 let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id);
@@ -215,12 +211,21 @@ fn push_param_constraint_from_top(&mut self,
         self.push_param_constraint(region, opt_ty, param_ty);
     }
 
+    /// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
+    fn push_projection_constraint_from_top(&mut self,
+                                           projection_ty: &ty::ProjectionTy<'tcx>) {
+        let &(region, opt_ty) = self.stack.last().unwrap();
+        self.out.push(RegionSubGenericConstraint(
+            opt_ty, region, GenericKind::Projection(projection_ty.clone())));
+    }
+
     /// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
     fn push_param_constraint(&mut self,
                              region: ty::Region,
                              opt_ty: Option<Ty<'tcx>>,
                              param_ty: ty::ParamTy) {
-        self.out.push(RegionSubParamConstraint(opt_ty, region, param_ty));
+        self.out.push(RegionSubGenericConstraint(
+            opt_ty, region, GenericKind::Param(param_ty)));
     }
 
     fn accumulate_from_adt(&mut self,
@@ -323,22 +328,6 @@ fn accumulate_from_adt(&mut self,
         }
     }
 
-    fn accumulate_from_closure_ty(&mut self,
-                                  ty: Ty<'tcx>,
-                                  c: &ty::ClosureTy<'tcx>)
-    {
-        match c.store {
-            ty::RegionTraitStore(r_b, _) => {
-                self.push_region_constraint_from_top(r_b);
-            }
-            ty::UniqTraitStore => { }
-        }
-
-        let required_region_bounds =
-            ty::object_region_bounds(self.tcx, None, c.bounds.builtin_bounds);
-        self.accumulate_from_object_ty(ty, c.bounds.region_bound, required_region_bounds);
-    }
-
     fn accumulate_from_object_ty(&mut self,
                                  ty: Ty<'tcx>,
                                  region_bound: ty::Region,
@@ -393,16 +382,16 @@ fn accumulate_from_object_ty(&mut self,
 }
 
 impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
-            RegionSubRegionConstraint(_, r_a, r_b) => {
+            RegionSubRegionConstraint(_, ref r_a, ref r_b) => {
                 format!("RegionSubRegionConstraint({}, {})",
                         r_a.repr(tcx),
                         r_b.repr(tcx))
             }
 
-            RegionSubParamConstraint(_, r, p) => {
-                format!("RegionSubParamConstraint({}, {})",
+            RegionSubGenericConstraint(_, ref r, ref p) => {
+                format!("RegionSubGenericConstraint({}, {})",
                         r.repr(tcx),
                         p.repr(tcx))
             }
index 1fdb68854c01fd4a7b76ba3284e61ff6f8d277b6..92fda96595c7bab805f73eee53d20fe823e70cad 100644 (file)
@@ -122,7 +122,6 @@ fn check_closure(&mut self,
                      _body: &ast::Block)
     {
         let is_old_skool_closure = match self.fcx.expr_ty(expr).sty {
-            ty::ty_closure(..) => true,
             _ => false,
         };
 
index 704025f38ce0d726c5454830bdf487a827a0e77b..d4a5bda5f97f9e930f5c8f5055e45d08c9408070 100644 (file)
@@ -81,10 +81,9 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
         }
     }
 
-    fn with_fcx(&mut self,
-                item: &ast::Item,
-                f: for<'fcx> |&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>,
-                              &FnCtxt<'fcx, 'tcx>|) {
+    fn with_fcx<F>(&mut self, item: &ast::Item, mut f: F) where
+        F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
+    {
         let ccx = self.ccx;
         let item_def_id = local_def(item.id);
         let polytype = ty::lookup_item_type(ccx.tcx, item_def_id);
@@ -100,10 +99,8 @@ fn with_fcx(&mut self,
     }
 
     /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn(&mut self,
-                       item: &ast::Item,
-                       lookup_fields: for<'fcx> |&FnCtxt<'fcx, 'tcx>|
-                                                 -> Vec<AdtVariant<'tcx>>)
+    fn check_type_defn<F>(&mut self, item: &ast::Item, mut lookup_fields: F) where
+        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
     {
         self.with_fcx(item, |this, fcx| {
             let variants = lookup_fields(fcx);
@@ -301,6 +298,18 @@ fn tcx(&self) -> &ty::ctxt<'tcx> {
         self.fcx.tcx()
     }
 
+    fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
+        where T : TypeFoldable<'tcx> + Repr<'tcx>
+    {
+        self.binding_count += 1;
+        let value = liberate_late_bound_regions(self.fcx.tcx(), self.scope, binder);
+        debug!("BoundsChecker::fold_binder: late-bound regions replaced: {}",
+               value.repr(self.tcx()));
+        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()));
@@ -361,19 +370,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
 
                 self.fold_substs(substs);
             }
-            ty::ty_bare_fn(_, &ty::BareFnTy{sig: ref fn_sig, ..}) |
-            ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => {
-                self.binding_count += 1;
-
-                let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope, fn_sig);
-
-                debug!("late-bound regions replaced: {}",
-                       fn_sig.repr(self.tcx()));
-
-                self.fold_fn_sig(&fn_sig);
-
-                self.binding_count -= 1;
-            }
             _ => {
                 super_fold_ty(self, t);
             }
index 4154937b3fdcd2b77b4cd561889e4ff5b101d260..70644b6e7de5d5386b9822c655205263188547aa 100644 (file)
@@ -266,10 +266,6 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
             Some(adjustment) => {
                 let adj_object = ty::adjust_is_object(&adjustment);
                 let resolved_adjustment = match adjustment {
-                    ty::AdjustAddEnv(def_id, store) => {
-                        ty::AdjustAddEnv(def_id, self.resolve(&store, reason))
-                    }
-
                     ty::AdjustReifyFnPointer(def_id) => {
                         ty::AdjustReifyFnPointer(def_id)
                     }
index 45b248dac9353e7dee18a721b6bd653ec2a555d5..09ab98745bd6a59a1d1573ca603a6a1508badabd 100644 (file)
@@ -22,7 +22,7 @@
 use middle::ty::RegionEscape;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
 use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
-use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err};
+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, ty_open};
@@ -69,7 +69,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         }
 
         ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
-        ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
+        ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
         ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
         ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
             None
@@ -102,7 +102,7 @@ fn visit_item(&mut self, item: &Item) {
         //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
 
         match item.node {
-            ItemImpl(_, _, ref opt_trait, _, _) => {
+            ItemImpl(_, _, _, ref opt_trait, _, _) => {
                 match opt_trait.clone() {
                     Some(opt_trait) => {
                         self.cc.check_implementation(item, &[opt_trait]);
@@ -283,7 +283,7 @@ fn get_self_type_for_implementation(&self, impl_did: DefId)
     // 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 trait_refs, _, ref ast_items) => {
+            ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
                 let mut items: Vec<ImplOrTraitItemId> =
                         ast_items.iter()
                                  .map(|ast_item| {
index 1da49799712bd6e3166639e85819b35fe57688da..d90bfe04ea1e78ceaa700c888b7a604a2e21f71e 100644 (file)
@@ -44,7 +44,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         let def_id = ast_util::local_def(item.id);
         match item.node {
-            ast::ItemImpl(_, _, None, _, _) => {
+            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));
@@ -69,7 +69,7 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     }
                 }
             }
-            ast::ItemImpl(_, _, Some(_), _, _) => {
+            ast::ItemImpl(_, _, _, Some(_), _, _) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
                 match traits::orphan_check(self.tcx, def_id) {
index 07a84846c47ad26d96192b791939b2030dff9a84..1acea6fd58179eac948cd3085b65f8247ffa2981 100644 (file)
@@ -30,7 +30,7 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         match item.node {
-            ast::ItemImpl(unsafety, _, _, _, _) => {
+            ast::ItemImpl(unsafety, _, _, _, _, _) => {
                 match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
                     None => {
                         // Inherent impl.
index 009f1e50e9b4b535c16dde3631cbb9f175a4a6d9..bbafcdae1bba104b27a4ad05f95b2f03834fd224 100644 (file)
 use middle::ty::{self, RegionEscape, Ty, TypeScheme};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::infer;
+use no_params;
 use rscope::*;
-use {CrateCtxt, no_params, write_ty_to_tcx};
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use util::ppaux;
 use util::ppaux::{Repr,UserString};
+use write_ty_to_tcx;
 
 use std::rc::Rc;
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
 
-pub fn collect_item_types(ccx: &CrateCtxt) {
-    fn collect_intrinsic_type(ccx: &CrateCtxt,
-                              lang_item: ast::DefId) {
-        let ty::TypeScheme { ty, .. } =
-            ccx.get_item_type_scheme(lang_item);
-        ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
-    }
+pub fn collect_item_types(tcx: &ty::ctxt) {
+    let ccx = &CollectCtxt { tcx: tcx };
 
     match ccx.tcx.lang_items.ty_desc() {
         Some(id) => { collect_intrinsic_type(ccx, id); }
@@ -85,13 +81,29 @@ fn collect_intrinsic_type(ccx: &CrateCtxt,
     visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
 }
 
+///////////////////////////////////////////////////////////////////////////
+
+struct CollectCtxt<'a,'tcx:'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Zeroth phase: collect types of intrinsics
+
+fn collect_intrinsic_type(ccx: &CollectCtxt,
+                          lang_item: ast::DefId) {
+    let ty::TypeScheme { ty, .. } =
+        ccx.get_item_type_scheme(lang_item);
+    ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // First phase: just collect *trait definitions* -- basically, the set
 // of type parameters and supertraits. This is information we need to
 // know later when parsing field defs.
 
 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CrateCtxt<'a, 'tcx>
+    ccx: &'a CollectCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
@@ -112,7 +124,7 @@ fn visit_item(&mut self, i: &ast::Item) {
 // Second phase: collection proper.
 
 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CrateCtxt<'a, 'tcx>
+    ccx: &'a CollectCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
@@ -133,13 +145,13 @@ pub trait ToTy<'tcx> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
 }
 
-impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> {
+impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
         ast_ty_to_ty(self, rs, ast_ty)
     }
 }
 
-impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
+impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
 
     fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
@@ -148,7 +160,9 @@ fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
         }
 
         match self.tcx.map.find(id.node) {
-            Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
+            Some(ast_map::NodeItem(item)) => {
+                ty_of_item(self, &*item)
+            }
             Some(ast_map::NodeForeignItem(foreign_item)) => {
                 let abi = self.tcx.map.get_foreign_abi(id.node);
                 ty_of_foreign_item(self, &*foreign_item, abi)
@@ -181,7 +195,7 @@ fn projected_ty(&self,
     }
 }
 
-pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                         enum_ty: Ty<'tcx>,
                                         variants: &[P<ast::Variant>],
                                         generics: &ast::Generics) {
@@ -226,7 +240,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    trait_def: &ty::TraitDef<'tcx>) {
     let tcx = ccx.tcx;
@@ -322,7 +336,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }
     }
 
-    fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
+    fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
         ccx.tcx.tcache.borrow_mut().insert(
             m.def_id,
             TypeScheme {
@@ -330,7 +344,7 @@ fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
                 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
     }
 
-    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                            trait_id: ast::NodeId,
                                            trait_generics: &ty::Generics<'tcx>,
                                            _trait_items: &[ast::TraitItem],
@@ -372,7 +386,7 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                 struct_generics: &ty::Generics<'tcx>,
                                 v: &ast::StructField,
                                 origin: ast::DefId) -> ty::field_ty {
@@ -405,7 +419,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                      trait_def: &ty::TraitDef<'tcx>,
                                      associated_type: &ast::AssociatedType)
 {
@@ -422,7 +436,7 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                ty::TypeTraitItem(associated_type));
 }
 
-fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
+fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
                                  container: ImplOrTraitItemContainer,
                                  mut ms: I,
                                  untransformed_rcvr_ty: Ty<'tcx>,
@@ -469,7 +483,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
            .insert(mty.def_id, ty::MethodTraitItem(mty));
     }
 
-    fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+    fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                               container: ImplOrTraitItemContainer,
                               m: &ast::Method,
                               untransformed_rcvr_ty: Ty<'tcx>,
@@ -506,7 +520,7 @@ fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
+fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
                                  span: Span,
                                  generics: &ast::Generics,
                                  thing: &'static str) {
@@ -535,7 +549,7 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
     }
 }
 
-pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
+fn convert(ccx: &CollectCtxt, it: &ast::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
     match it.node {
@@ -549,7 +563,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                                    enum_definition.variants.as_slice(),
                                    generics);
         },
-        ast::ItemImpl(_,
+        ast::ItemImpl(_, _,
                       ref generics,
                       ref opt_trait_ref,
                       ref selfty,
@@ -636,7 +650,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
 
             debug!("trait_def: ident={} trait_def={}",
                    it.ident.repr(ccx.tcx),
-                   trait_def.repr(ccx.tcx()));
+                   trait_def.repr(ccx.tcx));
 
             for trait_method in trait_methods.iter() {
                 let self_type = ty::mk_self_type(tcx);
@@ -706,7 +720,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
     }
 }
 
-pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                 struct_def: &ast::StructDef,
                                 scheme: ty::TypeScheme<'tcx>,
                                 id: ast::NodeId) {
@@ -773,7 +787,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
+fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
     // As above, this call populates the type table with the converted
     // type of the foreign item. We simply write it into the node type
     // table.
@@ -790,7 +804,7 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
     ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
 }
 
-fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                            trait_id: ast::DefId)
                            -> Rc<ty::TraitDef<'tcx>> {
     if trait_id.krate != ast::LOCAL_CRATE {
@@ -806,9 +820,9 @@ fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                   it: &ast::Item)
-                                   -> Rc<ty::TraitDef<'tcx>>
+fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+                               it: &ast::Item)
+                               -> Rc<ty::TraitDef<'tcx>>
 {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
@@ -872,7 +886,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     return trait_def;
 
-    fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+    fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                  generics: &ast::Generics)
                                  -> subst::Substs<'tcx>
     {
@@ -903,7 +917,7 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
+fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
                             -> ty::TypeScheme<'tcx> {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
@@ -985,7 +999,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
     }
 }
 
-pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                     it: &ast::ForeignItem,
                                     abi: abi::Abi) -> ty::TypeScheme<'tcx>
 {
@@ -1006,7 +1020,7 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                           generics: &ast::Generics)
                                           -> ty::Generics<'tcx> {
     ty_generics(ccx,
@@ -1017,7 +1031,7 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 &generics.where_clause)
 }
 
-fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    substs: &'tcx subst::Substs<'tcx>,
                                    ast_generics: &ast::Generics,
@@ -1077,7 +1091,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     return generics;
 
-    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                                  self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
                                                  trait_items: &[ast::TraitItem])
                                                  -> Vec<ty::Predicate<'tcx>>
@@ -1108,14 +1122,13 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn ty_generics_for_fn_or_method<'tcx,AC>(
-        this: &AC,
-        generics: &ast::Generics,
-        base_generics: ty::Generics<'tcx>)
-        -> ty::Generics<'tcx>
-        where AC: AstConv<'tcx> {
+fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+                                         generics: &ast::Generics,
+                                         base_generics: ty::Generics<'tcx>)
+                                         -> ty::Generics<'tcx>
+{
     let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
-    ty_generics(this,
+    ty_generics(ccx,
                 subst::FnSpace,
                 early_lifetimes[],
                 generics.ty_params[],
@@ -1124,11 +1137,11 @@ fn ty_generics_for_fn_or_method<'tcx,AC>(
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'tcx,AC>(this: &AC,
+fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                               bounds: &mut ty::BuiltinBounds,
                               ast_bounds: &[ast::TyParamBound],
                               span: Span)
-                              where AC: AstConv<'tcx> {
+{
     // Try to find an unbound in bounds.
     let mut unbound = None;
     for ab in ast_bounds.iter() {
@@ -1137,24 +1150,24 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
                 assert!(ptr.bound_lifetimes.is_empty());
                 unbound = Some(ptr.trait_ref.clone());
             } else {
-                this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \
+                ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
                                                 bound, only one is supported");
             }
         }
     }
 
-    let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
+    let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
     match unbound {
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
-            let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
+            let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
             match kind_id {
                 Ok(kind_id) if trait_def_id != kind_id => {
-                    this.tcx().sess.span_warn(span,
+                    ccx.tcx.sess.span_warn(span,
                                               "default bound relaxed for a type parameter, but \
                                                this does nothing because the given bound is not \
                                                a default. Only `?Sized` is supported");
-                    ty::try_add_builtin_trait(this.tcx(),
+                    ty::try_add_builtin_trait(ccx.tcx,
                                               kind_id,
                                               bounds);
                 }
@@ -1162,27 +1175,26 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
             }
         }
         _ if kind_id.is_ok() => {
-            ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
+            ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
         }
         // No lang item for Sized, so we can't add it as a bound.
         None => {}
     }
 }
 
-fn ty_generics<'tcx,AC>(this: &AC,
+fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                         space: subst::ParamSpace,
                         lifetime_defs: &[ast::LifetimeDef],
                         types: &[ast::TyParam],
                         base_generics: ty::Generics<'tcx>,
                         where_clause: &ast::WhereClause)
                         -> ty::Generics<'tcx>
-                        where AC: AstConv<'tcx>
 {
     let mut result = base_generics;
 
     for (i, l) in lifetime_defs.iter().enumerate() {
         let bounds = l.bounds.iter()
-                             .map(|l| ast_region_to_region(this.tcx(), l))
+                             .map(|l| ast_region_to_region(ccx.tcx, l))
                              .collect();
         let def = ty::RegionParameterDef { name: l.lifetime.name,
                                            space: space,
@@ -1197,25 +1209,25 @@ fn ty_generics<'tcx,AC>(this: &AC,
 
     // Now create the real type parameters.
     for (i, param) in types.iter().enumerate() {
-        let def = get_or_create_type_parameter_def(this,
+        let def = get_or_create_type_parameter_def(ccx,
                                                    space,
                                                    param,
                                                    i as u32);
         debug!("ty_generics: def for type param: {}, {}",
-               def.repr(this.tcx()),
+               def.repr(ccx.tcx),
                space);
         result.types.push(space, def);
     }
 
     // Just for fun, also push the bounds from the type parameters
     // into the predicates list. This is currently kind of non-DRY.
-    create_predicates(this.tcx(), &mut result, space);
+    create_predicates(ccx.tcx, &mut result, space);
 
     // Add the bounds not associated with a type parameter
     for predicate in where_clause.predicates.iter() {
         match predicate {
             &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                let ty = ast_ty_to_ty(this, &ExplicitRscope, &*bound_pred.bounded_ty);
+                let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
@@ -1223,7 +1235,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
                             let mut projections = Vec::new();
 
                             let trait_ref = astconv::instantiate_poly_trait_ref(
-                                this,
+                                ccx,
                                 &ExplicitRscope,
                                 poly_trait_ref,
                                 Some(ty),
@@ -1238,7 +1250,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
                         }
 
                         &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
-                            let region = ast_region_to_region(this.tcx(), lifetime);
+                            let region = ast_region_to_region(ccx.tcx, lifetime);
                             let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
                             result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
                         }
@@ -1247,9 +1259,9 @@ fn ty_generics<'tcx,AC>(this: &AC,
             }
 
             &ast::WherePredicate::RegionPredicate(ref region_pred) => {
-                let r1 = ast_region_to_region(this.tcx(), &region_pred.lifetime);
+                let r1 = ast_region_to_region(ccx.tcx, &region_pred.lifetime);
                 for bound in region_pred.bounds.iter() {
-                    let r2 = ast_region_to_region(this.tcx(), bound);
+                    let r2 = ast_region_to_region(ccx.tcx, bound);
                     let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
                     result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
                 }
@@ -1257,7 +1269,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
 
             &ast::WherePredicate::EqPredicate(ref eq_pred) => {
                 // FIXME(#20041)
-                this.tcx().sess.span_bug(eq_pred.span,
+                ccx.tcx.sess.span_bug(eq_pred.span,
                                          "Equality constraints are not yet \
                                             implemented (#20041)")
             }
@@ -1292,34 +1304,33 @@ fn create_predicates<'tcx>(
     }
 }
 
-fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
+fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                                              space: subst::ParamSpace,
                                              param: &ast::TyParam,
                                              index: u32)
                                              -> ty::TypeParameterDef<'tcx>
-    where AC: AstConv<'tcx>
 {
-    match this.tcx().ty_param_defs.borrow().get(&param.id) {
+    match ccx.tcx.ty_param_defs.borrow().get(&param.id) {
         Some(d) => { return (*d).clone(); }
         None => { }
     }
 
     let param_ty = ty::ParamTy::new(space, index, param.ident.name);
-    let bounds = compute_bounds(this,
-                                param_ty.to_ty(this.tcx()),
+    let bounds = compute_bounds(ccx,
+                                param_ty.to_ty(ccx.tcx),
                                 param.bounds[],
                                 SizedByDefault::Yes,
                                 param.span);
     let default = match param.default {
         None => None,
         Some(ref path) => {
-            let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
+            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
             let cur_idx = index;
 
             ty::walk_ty(ty, |t| {
                 match t.sty {
                     ty::ty_param(p) => if p.idx > cur_idx {
-                        span_err!(this.tcx().sess, path.span, E0128,
+                        span_err!(ccx.tcx.sess, path.span, E0128,
                                   "type parameters with a default cannot use \
                                    forward declared identifiers");
                         },
@@ -1340,7 +1351,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
         default: default
     };
 
-    this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
+    ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
 
     def
 }
@@ -1350,26 +1361,25 @@ enum SizedByDefault { Yes, No }
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'tcx,AC>(this: &AC,
+fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                            param_ty: ty::Ty<'tcx>,
                            ast_bounds: &[ast::TyParamBound],
                            sized_by_default: SizedByDefault,
                            span: Span)
                            -> ty::ParamBounds<'tcx>
-                           where AC: AstConv<'tcx>
 {
-    let mut param_bounds = conv_param_bounds(this,
+    let mut param_bounds = conv_param_bounds(ccx,
                                              span,
                                              param_ty,
                                              ast_bounds);
 
     if let SizedByDefault::Yes = sized_by_default {
-        add_unsized_bound(this,
+        add_unsized_bound(ccx,
                           &mut param_bounds.builtin_bounds,
                           ast_bounds,
                           span);
 
-        check_bounds_compatible(this.tcx(),
+        check_bounds_compatible(ccx.tcx,
                                 param_ty,
                                 &param_bounds,
                                 span);
@@ -1404,24 +1414,23 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-fn conv_param_bounds<'tcx,AC>(this: &AC,
+fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[ast::TyParamBound])
                               -> ty::ParamBounds<'tcx>
-                              where AC: AstConv<'tcx>
 {
     let astconv::PartitionedBounds { builtin_bounds,
                                      trait_bounds,
                                      region_bounds } =
-        astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
+        astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
 
     let mut projection_bounds = Vec::new();
 
     let trait_bounds: Vec<ty::PolyTraitRef> =
         trait_bounds.into_iter()
         .map(|bound| {
-            astconv::instantiate_poly_trait_ref(this,
+            astconv::instantiate_poly_trait_ref(ccx,
                                                 &ExplicitRscope,
                                                 bound,
                                                 Some(param_ty),
@@ -1430,7 +1439,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
         .collect();
     let region_bounds: Vec<ty::Region> =
         region_bounds.into_iter()
-        .map(|r| ast_region_to_region(this.tcx(), r))
+        .map(|r| ast_region_to_region(ccx.tcx, r))
         .collect();
     ty::ParamBounds {
         region_bounds: region_bounds,
@@ -1440,7 +1449,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
     }
 }
 
-pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                        decl: &ast::FnDecl,
                                        def_id: ast::DefId,
                                        ast_generics: &ast::Generics,
@@ -1492,9 +1501,9 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     return scheme;
 }
 
-pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                ty_generics: &ty::Generics<'tcx>)
-                                -> subst::Substs<'tcx>
+fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+                            ty_generics: &ty::Generics<'tcx>)
+                            -> subst::Substs<'tcx>
 {
     let types =
         ty_generics.types.map(
@@ -1514,14 +1523,14 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 /// comes back to check after the fact that explicit type the user
 /// wrote actually matches what the pre-defined option said.
 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
-    crate_context: &CrateCtxt<'a, 'tcx>,
+    ccx: &CollectCtxt<'a, 'tcx>,
     rs: &RS,
     required_type: Ty<'tcx>,
     explicit_self: &ast::ExplicitSelf,
     body_id: ast::NodeId)
 {
     if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
-        let typ = crate_context.to_ty(rs, &**ast_type);
+        let typ = ccx.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,
@@ -1537,27 +1546,27 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         assert!(!base_type.has_regions_escaping_depth(1));
         let required_type_free =
             liberate_early_bound_regions(
-                crate_context.tcx, body_scope,
+                ccx.tcx, body_scope,
                 &ty::liberate_late_bound_regions(
-                    crate_context.tcx, body_scope, &ty::Binder(required_type)));
+                    ccx.tcx, body_scope, &ty::Binder(required_type)));
 
         // The "base type" comes from the impl. It too may have late-bound
         // regions from the method.
         assert!(!base_type.has_regions_escaping_depth(1));
         let base_type_free =
             liberate_early_bound_regions(
-                crate_context.tcx, body_scope,
+                ccx.tcx, body_scope,
                 &ty::liberate_late_bound_regions(
-                    crate_context.tcx, body_scope, &ty::Binder(base_type)));
+                    ccx.tcx, body_scope, &ty::Binder(base_type)));
 
         debug!("required_type={} required_type_free={} \
                 base_type={} base_type_free={}",
-               required_type.repr(crate_context.tcx),
-               required_type_free.repr(crate_context.tcx),
-               base_type.repr(crate_context.tcx),
-               base_type_free.repr(crate_context.tcx));
-        let infcx = infer::new_infer_ctxt(crate_context.tcx);
-        drop(::require_same_types(crate_context.tcx,
+               required_type.repr(ccx.tcx),
+               required_type_free.repr(ccx.tcx),
+               base_type.repr(ccx.tcx),
+               base_type_free.repr(ccx.tcx));
+        let infcx = infer::new_infer_ctxt(ccx.tcx);
+        drop(::require_same_types(ccx.tcx,
                                   Some(&infcx),
                                   false,
                                   explicit_self.span,
@@ -1565,7 +1574,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                                   required_type_free,
                                   || {
                 format!("mismatched self type: expected `{}`",
-                        ppaux::ty_to_string(crate_context.tcx, required_type))
+                        ppaux::ty_to_string(ccx.tcx, required_type))
         }));
         infcx.resolve_regions_and_report_errors(body_id);
     }
index 48f9b129719719bedc2dc22ab2a4613aaa782c1a..3146a1181396b439ca00885e59d85d340940d110 100644 (file)
@@ -119,7 +119,7 @@ struct TypeAndSubsts<'tcx> {
 struct CrateCtxt<'a, 'tcx: 'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: ty::TraitMap,
-    tcx: &'a ty::ctxt<'tcx>
+    tcx: &'a ty::ctxt<'tcx>,
 }
 
 // Functions that write types into the node type table
@@ -320,7 +320,7 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     };
 
     time(time_passes, "type collecting", (), |_|
-        collect::collect_item_types(&ccx));
+         collect::collect_item_types(tcx));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
index 6bef7e713af28b2bd0df4bad7ea94143580c8954..e58c2275fcd96448c9836330cfe2bad49df4120f 100644 (file)
@@ -831,20 +831,7 @@ fn add_constraints_from_ty(&mut self,
                 }
             }
 
-            ty::ty_bare_fn(_, &ty::BareFnTy { ref sig, .. }) |
-            ty::ty_closure(box ty::ClosureTy {
-                    ref sig,
-                    store: ty::UniqTraitStore,
-                    ..
-                }) =>
-            {
-                self.add_constraints_from_sig(generics, sig, variance);
-            }
-
-            ty::ty_closure(box ty::ClosureTy { ref sig,
-                    store: ty::RegionTraitStore(region, _), .. }) => {
-                let contra = self.contravariant(variance);
-                self.add_constraints_from_region(generics, region, contra);
+            ty::ty_bare_fn(_, &ty::BareFnTy { ref sig, .. }) => {
                 self.add_constraints_from_sig(generics, sig, variance);
             }
 
index 3f5b0eaee124f1dfef3c32644f89ba01ce92f7b8..e01dbac68ee8d8ff6ae82a84c995519914a9fee9 100644 (file)
@@ -50,7 +50,6 @@
 use std::rc::Rc;
 use std::u32;
 use std::str::Str as StrTrait; // Conflicts with Str variant
-use std::char::Char as CharTrait; // Conflicts with Char variant
 use std::path::Path as FsPath; // Conflicts with Path struct
 
 use core::DocContext;
@@ -1367,7 +1366,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                     }
                 }
             }
-            TyClosure(ref c) => Closure(box c.clean(cx)),
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyParen(ref ty) => ty.clean(cx),
             TyQPath(ref qp) => qp.clean(cx),
@@ -1427,19 +1425,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                 decl: (ast_util::local_def(0), &fty.sig).clean(cx),
                 abi: fty.abi.to_string(),
             }),
-            ty::ty_closure(ref fty) => {
-                let decl = box ClosureDecl {
-                    lifetimes: Vec::new(), // FIXME: this looks wrong...
-                    decl: (ast_util::local_def(0), &fty.sig).clean(cx),
-                    onceness: fty.onceness,
-                    unsafety: fty.unsafety,
-                    bounds: fty.bounds.clean(cx),
-                };
-                match fty.store {
-                    ty::UniqTraitStore => Proc(decl),
-                    ty::RegionTraitStore(..) => Closure(decl),
-                }
-            }
             ty::ty_struct(did, substs) |
             ty::ty_enum(did, substs) => {
                 let fqn = csearch::get_item_path(cx.tcx(), did);
@@ -2243,8 +2228,12 @@ fn name_from_pat(p: &ast::Pat) -> String {
         },
         PatRange(..) => panic!("tried to get argument name from PatRange, \
                               which is not allowed in function arguments"),
-        PatVec(..) => panic!("tried to get argument name from pat_vec, \
-                             which is not allowed in function arguments"),
+        PatVec(ref begin, ref mid, ref end) => {
+            let begin = begin.iter().map(|p| name_from_pat(&**p));
+            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
+            let end = end.iter().map(|p| name_from_pat(&**p));
+            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().connect(", "))
+        },
         PatMac(..) => {
             warn!("can't document the name of a function argument \
                    produced by a pattern macro");
index d05e15ff2513258016a9b37d394c919766677e37..99afef4173fdd9213433c00cf236078b7e7db50f 100644 (file)
@@ -182,6 +182,7 @@ pub struct Trait {
 
 pub struct Impl {
     pub unsafety: ast::Unsafety,
+    pub polarity: ast::ImplPolarity,
     pub generics: ast::Generics,
     pub trait_: Option<ast::TraitRef>,
     pub for_: P<ast::Ty>,
index 0f0dbf6a24dffc7de58cbf2bdeb6a4fc18a8870c..dcc90117d26606041d1cc721e52e893706df9c8d 100644 (file)
@@ -20,8 +20,8 @@
 
 #[cfg(unix)]
 mod imp {
+    use std::ffi::CString;
     use libc;
-    use std::c_str::ToCStr;
 
     #[cfg(target_os = "linux")]
     mod os {
@@ -111,9 +111,11 @@ pub struct Lock {
 
     impl Lock {
         pub fn new(p: &Path) -> Lock {
-            let fd = p.with_c_str(|s| unsafe {
-                libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
-            });
+            let buf = CString::from_slice(p.as_vec());
+            let fd = unsafe {
+                libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
+                           libc::S_IRWXU)
+            };
             assert!(fd > 0);
             let flock = os::flock {
                 l_start: 0,
index 9d003eca27f3dd11ad067352adb3f048b85b0ac9..3b9265cf569765a39822fea60f54c567ddc9a46a 100644 (file)
@@ -29,7 +29,7 @@
 
 use libc;
 use std::ascii::AsciiExt;
-use std::c_str::ToCStr;
+use std::ffi::CString;
 use std::cell::{RefCell, Cell};
 use std::collections::HashMap;
 use std::fmt;
@@ -215,7 +215,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                 let id = id.as_ref().map(|a| a.as_slice());
                 s.push_str(highlight::highlight(text.as_slice(), None, id)
                                      .as_slice());
-                let output = s.to_c_str();
+                let output = CString::from_vec(s.into_bytes());
                 hoedown_buffer_puts(ob, output.as_ptr());
             })
         }
@@ -224,15 +224,16 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
     extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
                      level: libc::c_int, opaque: *mut libc::c_void) {
         // hoedown does this, we may as well too
-        "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+        unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
 
         // Extract the text provided
         let s = if text.is_null() {
             "".to_string()
         } else {
-            unsafe {
-                String::from_raw_buf_len((*text).data, (*text).size as uint)
-            }
+            let s = unsafe {
+                slice::from_raw_buf(&(*text).data, (*text).size as uint)
+            };
+            str::from_utf8(s).unwrap().to_string()
         };
 
         // Transform the contents of the header into a hyphenated string
@@ -273,7 +274,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
                                format!("{} ", sec)
                            });
 
-        text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+        let text = CString::from_vec(text.into_bytes());
+        unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
     }
 
     reset_headers();
index 338b9b3e0eba417c07efb5a046d3edb13f01d414..ddb14d6944b9d8f358aed8347577e7bf06d57887 100644 (file)
@@ -36,7 +36,6 @@
 
 use std::cell::RefCell;
 use std::cmp::Ordering::{self, Less, Greater, Equal};
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::collections::{HashMap, HashSet};
 use std::default::Default;
 use std::fmt;
@@ -822,10 +821,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         if let clean::ImplItem(ref i) = item.inner {
             match i.trait_ {
                 Some(clean::ResolvedPath{ did, .. }) => {
-                    let v = match self.implementors.entry(did) {
-                        Vacant(entry) => entry.set(Vec::with_capacity(1)),
-                        Occupied(entry) => entry.into_mut(),
-                    };
+                    let v = self.implementors.entry(&did).get().unwrap_or_else(
+                        |vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
                     v.push(Implementor {
                         def_id: item.def_id,
                         generics: i.generics.clone(),
@@ -1014,10 +1011,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                         };
 
                         if let Some(did) = did {
-                            let v = match self.impls.entry(did) {
-                                Vacant(entry) => entry.set(Vec::with_capacity(1)),
-                                Occupied(entry) => entry.into_mut(),
-                            };
+                            let v = self.impls.entry(&did).get().unwrap_or_else(
+                                |vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
                             v.push(Impl {
                                 impl_: i,
                                 dox: dox,
@@ -1264,10 +1259,9 @@ fn build_sidebar(&self, m: &clean::Module) -> HashMap<String, Vec<String>> {
                 None => continue,
                 Some(ref s) => s.to_string(),
             };
-            let v = match map.entry(short.to_string()) {
-                Vacant(entry) => entry.set(Vec::with_capacity(1)),
-                Occupied(entry) => entry.into_mut(),
-            };
+            let short = short.to_string();
+            let v = map.entry(&short).get().unwrap_or_else(
+                |vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
             v.push(myname);
         }
 
@@ -2259,9 +2253,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
             cols += 1;
             tmp /= 10;
         }
-        try!(write!(fmt, "<pre class='line-numbers'>"));
+        try!(write!(fmt, "<pre class=\"line-numbers\">"));
         for i in range(1, lines + 1) {
-            try!(write!(fmt, "<span id='{0}'>{0:1$}</span>\n", i, cols));
+            try!(write!(fmt, "<span id=\"{0}\">{0:1$}</span>\n", i, cols));
         }
         try!(write!(fmt, "</pre>"));
         try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None)));
index 9d4f341a30e25fa018dacb1e0fe9f508cd3c1e09..a5a482541410938bcfbbad6ba50cc27d93170ba2 100644 (file)
@@ -157,6 +157,7 @@ nav.sub {
     left: 0;
     top: 0;
     min-height: 100%;
+    z-index: -1;
 }
 
 .content, nav { max-width: 960px; }
@@ -217,10 +218,18 @@ nav.sub {
     overflow: auto;
     padding-left: 0;
 }
-.content pre.line-numbers { float: left; border: none; }
-.line-numbers span { color: #c67e2d; }
+.content pre.line-numbers {
+    float: left;
+    border: none;
+
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+.line-numbers span { color: #c67e2d; cursor: pointer; }
 .line-numbers .line-highlighted {
-    background-color: #f6fdb0;
+    background-color: #f6fdb0 !important;
 }
 
 .content .highlighted {
@@ -470,6 +479,7 @@ h1 .stability {
 .summary.Unmarked { background-color: #BBBBBB; }
 
 :target { background: #FDFFD3; }
+.line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
 pre.rust .kw { color: #8959A8; }
index 978af31cdc6895a00ae3527149fc33796d3ec25a..2d575c226c5d0de5d938793553ec7d29ab64ae44 100644 (file)
@@ -50,7 +50,7 @@
     resizeShortBlocks();
     $(window).on('resize', resizeShortBlocks);
 
-    function highlightSourceLines() {
+    function highlightSourceLines(ev) {
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
             from = parseInt(match[1], 10);
             if ($('#' + from).length === 0) {
                 return;
             }
-            $('#' + 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');
             }
         }
     }
-    highlightSourceLines();
+    highlightSourceLines(null);
     $(window).on('hashchange', highlightSourceLines);
 
     $(document).on('keyup', function(e) {
         $("#main > .docblock").before(wrapper);
     });
 
+    $('pre.line-numbers').on('click', 'span', function() {
+        var prev_id = 0;
+
+        function set_fragment(name) {
+            if (history.replaceState) {
+                history.replaceState(null, null, '#' + name);
+                $(window).trigger('hashchange');
+            } else {
+                location.replace('#' + name);
+            }
+        }
+
+        return function(ev) {
+            var cur_id = parseInt(ev.target.id);
+
+            if (ev.shiftKey && prev_id) {
+                if (prev_id > cur_id) {
+                    var tmp = prev_id;
+                    prev_id = cur_id;
+                    cur_id = tmp;
+                }
+
+                set_fragment(prev_id + '-' + cur_id);
+            } else {
+                prev_id = cur_id;
+
+                set_fragment(cur_id);
+            }
+        };
+    }());
+
 }());
index 125bc21d79d067dc99f17903f953c88ebe638a21..106fe452f46a6059a931a1973681f516f3454096 100644 (file)
@@ -38,7 +38,6 @@
 
 use std::cell::RefCell;
 use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::io::File;
 use std::io;
 use std::rc::Rc;
@@ -321,10 +320,9 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
                 return Err("--extern value must be of the format `foo=bar`".to_string());
             }
         };
-        let locs = match externs.entry(name.to_string()) {
-            Vacant(entry) => entry.set(Vec::with_capacity(1)),
-            Occupied(entry) => entry.into_mut(),
-        };
+        let name = name.to_string();
+        let locs = externs.entry(&name).get().unwrap_or_else(
+            |vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
         locs.push(location.to_string());
     }
     Ok(externs)
index e71711aa8d6e77d80efdb56cf74d6e0aec444f1f..c98ec97ab87f0b806eb83c297b8428f78e186835 100644 (file)
@@ -337,9 +337,10 @@ pub fn visit_item(&mut self, item: &ast::Item,
                 };
                 om.traits.push(t);
             },
-            ast::ItemImpl(unsafety, ref gen, ref tr, ref ty, ref items) => {
+            ast::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
                 let i = Impl {
                     unsafety: unsafety,
+                    polarity: polarity,
                     generics: gen.clone(),
                     trait_: tr.clone(),
                     for_: ty.clone(),
index f2d79b133469958d48a5a3d8b3519871b5f494c0..7ba329c518e91074cd0f5bddab7b1d96139c2e21 100644 (file)
 use collections::enum_set::{EnumSet, CLike};
 
 impl<
-    E,
-    S: Encoder<E>,
-    T: Encodable<S, E>
-> Encodable<S, E> for DList<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+    T: Encodable
+> Encodable for DList<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 try!(s.emit_seq_elt(i, |s| e.encode(s)));
@@ -33,8 +31,8 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
-    fn decode(d: &mut D) -> Result<DList<T>, E> {
+impl<T:Decodable> Decodable for DList<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<DList<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut list = DList::new();
             for i in range(0u, len) {
@@ -45,12 +43,8 @@ fn decode(d: &mut D) -> Result<DList<T>, E> {
     }
 }
 
-impl<
-    E,
-    S: Encoder<E>,
-    T: Encodable<S, E>
-> Encodable<S, E> for RingBuf<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T: Encodable> Encodable for RingBuf<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 try!(s.emit_seq_elt(i, |s| e.encode(s)));
@@ -60,8 +54,8 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
-    fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
+impl<T:Decodable> Decodable for RingBuf<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<RingBuf<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut deque: RingBuf<T> = RingBuf::new();
             for i in range(0u, len) {
@@ -73,12 +67,10 @@ fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
 }
 
 impl<
-    E,
-    S: Encoder<E>,
-    K: Encodable<S, E> + PartialEq + Ord,
-    V: Encodable<S, E> + PartialEq
-> Encodable<S, E> for BTreeMap<K, V> {
-    fn encode(&self, e: &mut S) -> Result<(), E> {
+    K: Encodable + PartialEq + Ord,
+    V: Encodable + PartialEq
+> Encodable for BTreeMap<K, V> {
+    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
             for (key, val) in self.iter() {
@@ -92,12 +84,10 @@ fn encode(&self, e: &mut S) -> Result<(), E> {
 }
 
 impl<
-    E,
-    D: Decoder<E>,
-    K: Decodable<D, E> + PartialEq + Ord,
-    V: Decodable<D, E> + PartialEq
-> Decodable<D, E> for BTreeMap<K, V> {
-    fn decode(d: &mut D) -> Result<BTreeMap<K, V>, E> {
+    K: Decodable + PartialEq + Ord,
+    V: Decodable + PartialEq
+> Decodable for BTreeMap<K, V> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
         d.read_map(|d, len| {
             let mut map = BTreeMap::new();
             for i in range(0u, len) {
@@ -111,11 +101,9 @@ fn decode(d: &mut D) -> Result<BTreeMap<K, V>, E> {
 }
 
 impl<
-    E,
-    S: Encoder<E>,
-    T: Encodable<S, E> + PartialEq + Ord
-> Encodable<S, E> for BTreeSet<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+    T: Encodable + PartialEq + Ord
+> Encodable for BTreeSet<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
             for e in self.iter() {
@@ -128,11 +116,9 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
 }
 
 impl<
-    E,
-    D: Decoder<E>,
-    T: Decodable<D, E> + PartialEq + Ord
-> Decodable<D, E> for BTreeSet<T> {
-    fn decode(d: &mut D) -> Result<BTreeSet<T>, E> {
+    T: Decodable + PartialEq + Ord
+> Decodable for BTreeSet<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut set = BTreeSet::new();
             for i in range(0u, len) {
@@ -144,11 +130,9 @@ fn decode(d: &mut D) -> Result<BTreeSet<T>, E> {
 }
 
 impl<
-    E,
-    S: Encoder<E>,
-    T: Encodable<S, E> + CLike
-> Encodable<S, E> for EnumSet<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+    T: Encodable + CLike
+> Encodable for EnumSet<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         let mut bits = 0;
         for item in self.iter() {
             bits |= item.to_uint();
@@ -158,11 +142,9 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
 }
 
 impl<
-    E,
-    D: Decoder<E>,
-    T: Decodable<D, E> + CLike
-> Decodable<D, E> for EnumSet<T> {
-    fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
+    T: Decodable + CLike
+> Decodable for EnumSet<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<EnumSet<T>, D::Error> {
         let bits = try!(d.read_uint());
         let mut set = EnumSet::new();
         for bit in range(0, uint::BITS) {
@@ -175,14 +157,12 @@ fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
 }
 
 impl<
-    E,
-    S: Encoder<E>,
-    K: Encodable<S, E> + Hash<X> + Eq,
-    V: Encodable<S, E>,
+    K: Encodable + Hash<X> + Eq,
+    V: Encodable,
     X,
     H: Hasher<X>
-> Encodable<S, E> for HashMap<K, V, H> {
-    fn encode(&self, e: &mut S) -> Result<(), E> {
+> Encodable for HashMap<K, V, H> {
+    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
             for (key, val) in self.iter() {
@@ -196,14 +176,12 @@ fn encode(&self, e: &mut S) -> Result<(), E> {
 }
 
 impl<
-    E,
-    D: Decoder<E>,
-    K: Decodable<D, E> + Hash<S> + Eq,
-    V: Decodable<D, E>,
+    K: Decodable + Hash<S> + Eq,
+    V: Decodable,
     S,
     H: Hasher<S> + Default
-> Decodable<D, E> for HashMap<K, V, H> {
-    fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
+> Decodable for HashMap<K, V, H> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, H>, D::Error> {
         d.read_map(|d, len| {
             let hasher = Default::default();
             let mut map = HashMap::with_capacity_and_hasher(len, hasher);
@@ -218,13 +196,11 @@ fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
 }
 
 impl<
-    E,
-    S: Encoder<E>,
-    T: Encodable<S, E> + Hash<X> + Eq,
+    T: Encodable + Hash<X> + Eq,
     X,
     H: Hasher<X>
-> Encodable<S, E> for HashSet<T, H> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+> Encodable for HashSet<T, H> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
             for e in self.iter() {
@@ -237,13 +213,11 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
 }
 
 impl<
-    E,
-    D: Decoder<E>,
-    T: Decodable<D, E> + Hash<S> + Eq,
+    T: Decodable + Hash<S> + Eq,
     S,
     H: Hasher<S> + Default
-> Decodable<D, E> for HashSet<T, H> {
-    fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
+> Decodable for HashSet<T, H> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, H>, D::Error> {
         d.read_seq(|d, len| {
             let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
             for i in range(0u, len) {
@@ -254,12 +228,8 @@ fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
     }
 }
 
-impl<
-    E,
-    S: Encoder<E>,
-    V: Encodable<S, E>
-> Encodable<S, E> for VecMap<V> {
-    fn encode(&self, e: &mut S) -> Result<(), E> {
+impl<V: Encodable> Encodable for VecMap<V> {
+    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
                 for (i, (key, val)) in self.iter().enumerate() {
                     try!(e.emit_map_elt_key(i, |e| key.encode(e)));
@@ -270,12 +240,8 @@ fn encode(&self, e: &mut S) -> Result<(), E> {
     }
 }
 
-impl<
-    E,
-    D: Decoder<E>,
-    V: Decodable<D, E>
-> Decodable<D, E> for VecMap<V> {
-    fn decode(d: &mut D) -> Result<VecMap<V>, E> {
+impl<V: Decodable> Decodable for VecMap<V> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<VecMap<V>, D::Error> {
         d.read_map(|d, len| {
             let mut map = VecMap::new();
             for i in range(0u, len) {
diff --git a/src/libserialize/collection_impls_stage0.rs b/src/libserialize/collection_impls_stage0.rs
new file mode 100644 (file)
index 0000000..f2d79b1
--- /dev/null
@@ -0,0 +1,289 @@
+// 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.
+
+//! Implementations of serialization for structures found in libcollections
+
+use std::uint;
+use std::default::Default;
+use std::hash::{Hash, Hasher};
+
+use {Decodable, Encodable, Decoder, Encoder};
+use std::collections::{DList, RingBuf, BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
+use collections::enum_set::{EnumSet, CLike};
+
+impl<
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E>
+> Encodable<S, E> for DList<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
+    fn decode(d: &mut D) -> Result<DList<T>, E> {
+        d.read_seq(|d, len| {
+            let mut list = DList::new();
+            for i in range(0u, len) {
+                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(list)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E>
+> Encodable<S, E> for RingBuf<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
+    fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
+        d.read_seq(|d, len| {
+            let mut deque: RingBuf<T> = RingBuf::new();
+            for i in range(0u, len) {
+                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(deque)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    K: Encodable<S, E> + PartialEq + Ord,
+    V: Encodable<S, E> + PartialEq
+> Encodable<S, E> for BTreeMap<K, V> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
+        e.emit_map(self.len(), |e| {
+            let mut i = 0;
+            for (key, val) in self.iter() {
+                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    K: Decodable<D, E> + PartialEq + Ord,
+    V: Decodable<D, E> + PartialEq
+> Decodable<D, E> for BTreeMap<K, V> {
+    fn decode(d: &mut D) -> Result<BTreeMap<K, V>, E> {
+        d.read_map(|d, len| {
+            let mut map = BTreeMap::new();
+            for i in range(0u, len) {
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
+                map.insert(key, val);
+            }
+            Ok(map)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + PartialEq + Ord
+> Encodable<S, E> for BTreeSet<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            let mut i = 0;
+            for e in self.iter() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + PartialEq + Ord
+> Decodable<D, E> for BTreeSet<T> {
+    fn decode(d: &mut D) -> Result<BTreeSet<T>, E> {
+        d.read_seq(|d, len| {
+            let mut set = BTreeSet::new();
+            for i in range(0u, len) {
+                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(set)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + CLike
+> Encodable<S, E> for EnumSet<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        let mut bits = 0;
+        for item in self.iter() {
+            bits |= item.to_uint();
+        }
+        s.emit_uint(bits)
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + CLike
+> Decodable<D, E> for EnumSet<T> {
+    fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
+        let bits = try!(d.read_uint());
+        let mut set = EnumSet::new();
+        for bit in range(0, uint::BITS) {
+            if bits & (1 << bit) != 0 {
+                set.insert(CLike::from_uint(1 << bit));
+            }
+        }
+        Ok(set)
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    K: Encodable<S, E> + Hash<X> + Eq,
+    V: Encodable<S, E>,
+    X,
+    H: Hasher<X>
+> Encodable<S, E> for HashMap<K, V, H> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
+        e.emit_map(self.len(), |e| {
+            let mut i = 0;
+            for (key, val) in self.iter() {
+                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    K: Decodable<D, E> + Hash<S> + Eq,
+    V: Decodable<D, E>,
+    S,
+    H: Hasher<S> + Default
+> Decodable<D, E> for HashMap<K, V, H> {
+    fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
+        d.read_map(|d, len| {
+            let hasher = Default::default();
+            let mut map = HashMap::with_capacity_and_hasher(len, hasher);
+            for i in range(0u, len) {
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
+                map.insert(key, val);
+            }
+            Ok(map)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    T: Encodable<S, E> + Hash<X> + Eq,
+    X,
+    H: Hasher<X>
+> Encodable<S, E> for HashSet<T, H> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            let mut i = 0;
+            for e in self.iter() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)));
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    T: Decodable<D, E> + Hash<S> + Eq,
+    S,
+    H: Hasher<S> + Default
+> Decodable<D, E> for HashSet<T, H> {
+    fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
+        d.read_seq(|d, len| {
+            let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
+            for i in range(0u, len) {
+                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(set)
+        })
+    }
+}
+
+impl<
+    E,
+    S: Encoder<E>,
+    V: Encodable<S, E>
+> Encodable<S, E> for VecMap<V> {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
+        e.emit_map(self.len(), |e| {
+                for (i, (key, val)) in self.iter().enumerate() {
+                    try!(e.emit_map_elt_key(i, |e| key.encode(e)));
+                    try!(e.emit_map_elt_val(i, |e| val.encode(e)));
+                }
+                Ok(())
+            })
+    }
+}
+
+impl<
+    E,
+    D: Decoder<E>,
+    V: Decodable<D, E>
+> Decodable<D, E> for VecMap<V> {
+    fn decode(d: &mut D) -> Result<VecMap<V>, E> {
+        d.read_map(|d, len| {
+            let mut map = VecMap::new();
+            for i in range(0u, len) {
+                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
+                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
+                map.insert(key, val);
+            }
+            Ok(map)
+        })
+    }
+}
index e31d8157332c98f5fc1c8470144208970717e72d..bd4cb1884a69a5b6708de57a5c575ff371877c8b 100644 (file)
@@ -300,7 +300,7 @@ pub fn error_str(error: ErrorCode) -> &'static str {
 }
 
 /// Shortcut function to decode a JSON `&str` into an object
-pub fn decode<T: ::Decodable<Decoder, DecoderError>>(s: &str) -> DecodeResult<T> {
+pub fn decode<T: ::Decodable>(s: &str) -> DecodeResult<T> {
     let json = match from_str(s) {
         Ok(x) => x,
         Err(e) => return Err(ParseError(e))
@@ -311,9 +311,7 @@ pub fn decode<T: ::Decodable<Decoder, DecoderError>>(s: &str) -> DecodeResult<T>
 }
 
 /// Shortcut function to encode a `T` into a JSON `String`
-pub fn encode<T>(object: &T) -> string::String
-                 where T: for<'a> Encodable<Encoder<'a>, fmt::Error>
-{
+pub fn encode<T: ::Encodable>(object: &T) -> string::String {
     let mut s = String::new();
     {
         let mut encoder = Encoder::new(&mut s);
@@ -444,7 +442,9 @@ pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> {
     }
 }
 
-impl<'a> ::Encoder<fmt::Error> for Encoder<'a> {
+impl<'a> ::Encoder for Encoder<'a> {
+    type Error = fmt::Error;
+
     fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
 
     fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
@@ -664,7 +664,9 @@ pub fn set_indent(&mut self, indent: uint) {
     }
 }
 
-impl<'a> ::Encoder<fmt::Error> for PrettyEncoder<'a> {
+impl<'a> ::Encoder for PrettyEncoder<'a> {
+    type Error = fmt::Error;
+
     fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
 
     fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
@@ -909,8 +911,8 @@ fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
     }
 }
 
-impl<E: ::Encoder<S>, S> Encodable<E, S> for Json {
-    fn encode(&self, e: &mut E) -> Result<(), S> {
+impl Encodable for Json {
+    fn encode<E: ::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         match *self {
             Json::I64(v) => v.encode(e),
             Json::U64(v) => v.encode(e),
@@ -1123,15 +1125,6 @@ pub fn as_null(&self) -> Option<()> {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a> ops::Index<&'a str, Json>  for Json {
-    fn index(&self, idx: & &str) -> &Json {
-        self.find(*idx).unwrap()
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 impl<'a> ops::Index<&'a str>  for Json {
     type Output = Json;
 
@@ -1140,18 +1133,6 @@ fn index(&self, idx: & &str) -> &Json {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl ops::Index<uint, Json> for Json {
-    fn index<'a>(&'a self, idx: &uint) -> &'a Json {
-        match self {
-            &Json::Array(ref v) => v.index(idx),
-            _ => panic!("can only index Json with uint if it is an array")
-        }
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 impl ops::Index<uint> for Json {
     type Output = Json;
 
@@ -2062,7 +2043,9 @@ fn $name(&mut self) -> DecodeResult<$ty> {
     }
 }
 
-impl ::Decoder<DecoderError> for Decoder {
+impl ::Decoder for Decoder {
+    type Error = DecoderError;
+
     fn read_nil(&mut self) -> DecodeResult<()> {
         expect!(self.pop(), Null)
     }
@@ -2474,9 +2457,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'a, T> fmt::Show for AsJson<'a, T>
-    where T: for<'b> Encodable<Encoder<'b>, fmt::Error>
-{
+impl<'a, T: Encodable> fmt::Show for AsJson<'a, T> {
     /// Encodes a json value into a string
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut shim = FormatShim { inner: f };
@@ -2493,9 +2474,7 @@ pub fn indent(mut self, indent: uint) -> AsPrettyJson<'a, T> {
     }
 }
 
-impl<'a, T> fmt::Show for AsPrettyJson<'a, T>
-    where T: for<'b> Encodable<PrettyEncoder<'b>, fmt::Error>
-{
+impl<'a, T: Encodable> fmt::Show for AsPrettyJson<'a, T> {
     /// Encodes a json value into a string
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut shim = FormatShim { inner: f };
@@ -3155,8 +3134,7 @@ enum DecodeEnum {
         A(f64),
         B(string::String)
     }
-    fn check_err<T: Decodable<Decoder, DecoderError>>(to_parse: &'static str,
-                                                      expected: DecoderError) {
+    fn check_err<T: Decodable>(to_parse: &'static str, expected: DecoderError) {
         let res: DecodeResult<T> = match from_str(to_parse) {
             Err(e) => Err(ParseError(e)),
             Ok(json) => Decodable::decode(&mut Decoder::new(json))
diff --git a/src/libserialize/json_stage0.rs b/src/libserialize/json_stage0.rs
new file mode 100644 (file)
index 0000000..9932f8d
--- /dev/null
@@ -0,0 +1,3862 @@
+// 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.
+
+// Rust JSON serialization library
+// Copyright (c) 2011 Google Inc.
+
+#![forbid(non_camel_case_types)]
+#![allow(missing_docs)]
+
+//! JSON parsing and serialization
+//!
+//! # What is JSON?
+//!
+//! JSON (JavaScript Object Notation) is a way to write data in Javascript.
+//! Like XML, it allows to encode structured data in a text format that can be easily read by humans
+//! Its simple syntax and native compatibility with JavaScript have made it a widely used format.
+//!
+//! Data types that can be encoded are JavaScript types (see the `Json` enum for more details):
+//!
+//! * `Boolean`: equivalent to rust's `bool`
+//! * `Number`: equivalent to rust's `f64`
+//! * `String`: equivalent to rust's `String`
+//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
+//!   same array
+//! * `Object`: equivalent to rust's `BTreeMap<String, json::Json>`
+//! * `Null`
+//!
+//! An object is a series of string keys mapping to values, in `"key": value` format.
+//! Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).
+//! A simple JSON document encoding a person, his/her age, address and phone numbers could look like
+//!
+//! ```ignore
+//! {
+//!     "FirstName": "John",
+//!     "LastName": "Doe",
+//!     "Age": 43,
+//!     "Address": {
+//!         "Street": "Downing Street 10",
+//!         "City": "London",
+//!         "Country": "Great Britain"
+//!     },
+//!     "PhoneNumbers": [
+//!         "+44 1234567",
+//!         "+44 2345678"
+//!     ]
+//! }
+//! ```
+//!
+//! # Rust Type-based Encoding and Decoding
+//!
+//! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via
+//! the serialization API.
+//! To be able to encode a piece of data, it must implement the `serialize::RustcEncodable` trait.
+//! To be able to decode a piece of data, it must implement the `serialize::RustcDecodable` trait.
+//! The Rust compiler provides an annotation to automatically generate the code for these traits:
+//! `#[derive(RustcDecodable, RustcEncodable)]`
+//!
+//! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects.
+//! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value.
+//! A `json::Json` value can be encoded as a string or buffer using the functions described above.
+//! You can also use the `json::Encoder` object, which implements the `Encoder` trait.
+//!
+//! When using `ToJson` the `RustcEncodable` trait implementation is not mandatory.
+//!
+//! # Examples of use
+//!
+//! ## Using Autoserialization
+//!
+//! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
+//! serialization API, using the derived serialization code.
+//!
+//! ```notrust
+//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! extern crate serialize;
+//! use serialize::json;
+//!
+//! // Automatically generate `Decodable` and `Encodable` trait implementations
+//! #[derive(RustcDecodable, RustcEncodable)]
+//! pub struct TestStruct  {
+//!     data_int: u8,
+//!     data_str: String,
+//!     data_vector: Vec<u8>,
+//! }
+//!
+//! fn main() {
+//!     let object = TestStruct {
+//!         data_int: 1,
+//!         data_str: "homura".to_string(),
+//!         data_vector: vec![2,3,4,5],
+//!     };
+//!
+//!     // Serialize using `json::encode`
+//!     let encoded = json::encode(&object);
+//!
+//!     // Deserialize using `json::decode`
+//!     let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap();
+//! }
+//! ```
+//!
+//! ## Using the `ToJson` trait
+//!
+//! The examples above use the `ToJson` trait to generate the JSON string, which is required
+//! for custom mappings.
+//!
+//! ### Simple example of `ToJson` usage
+//!
+//! ```notrust
+//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! extern crate serialize;
+//! use serialize::json::{mod, ToJson, Json};
+//!
+//! // A custom data structure
+//! struct ComplexNum {
+//!     a: f64,
+//!     b: f64,
+//! }
+//!
+//! // JSON value representation
+//! impl ToJson for ComplexNum {
+//!     fn to_json(&self) -> Json {
+//!         Json::String(format!("{}+{}i", self.a, self.b))
+//!     }
+//! }
+//!
+//! // Only generate `RustcEncodable` trait implementation
+//! #[derive(Encodable)]
+//! pub struct ComplexNumRecord {
+//!     uid: u8,
+//!     dsc: String,
+//!     val: Json,
+//! }
+//!
+//! fn main() {
+//!     let num = ComplexNum { a: 0.0001, b: 12.539 };
+//!     let data: String = json::encode(&ComplexNumRecord{
+//!         uid: 1,
+//!         dsc: "test".to_string(),
+//!         val: num.to_json(),
+//!     });
+//!     println!("data: {}", data);
+//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539j"};
+//! }
+//! ```
+//!
+//! ### Verbose example of `ToJson` usage
+//!
+//! ```notrust
+//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! extern crate serialize;
+//! use std::collections::BTreeMap;
+//! use serialize::json::{mod, Json, ToJson};
+//!
+//! // Only generate `Decodable` trait implementation
+//! #[derive(Decodable)]
+//! pub struct TestStruct {
+//!     data_int: u8,
+//!     data_str: String,
+//!     data_vector: Vec<u8>,
+//! }
+//!
+//! // Specify encoding method manually
+//! impl ToJson for TestStruct {
+//!     fn to_json(&self) -> Json {
+//!         let mut d = BTreeMap::new();
+//!         // All standard types implement `to_json()`, so use it
+//!         d.insert("data_int".to_string(), self.data_int.to_json());
+//!         d.insert("data_str".to_string(), self.data_str.to_json());
+//!         d.insert("data_vector".to_string(), self.data_vector.to_json());
+//!         Json::Object(d)
+//!     }
+//! }
+//!
+//! fn main() {
+//!     // Serialize using `ToJson`
+//!     let input_data = TestStruct {
+//!         data_int: 1,
+//!         data_str: "madoka".to_string(),
+//!         data_vector: vec![2,3,4,5],
+//!     };
+//!     let json_obj: Json = input_data.to_json();
+//!     let json_str: String = json_obj.to_string();
+//!
+//!     // Deserialize like before
+//!     let decoded: TestStruct = json::decode(json_str.as_slice()).unwrap();
+//! }
+//! ```
+
+use self::JsonEvent::*;
+use self::StackElement::*;
+use self::ErrorCode::*;
+use self::ParserError::*;
+use self::DecoderError::*;
+use self::ParserState::*;
+use self::InternalStackElement::*;
+
+use std;
+use std::collections::{HashMap, BTreeMap};
+use std::{char, f64, fmt, io, num, str};
+use std::mem::{swap, transmute};
+use std::num::{Float, Int};
+use std::num::FpCategory as Fp;
+use std::str::FromStr;
+use std::string;
+use std::ops;
+use unicode::str as unicode_str;
+use unicode::str::Utf16Item;
+
+use Encodable;
+
+/// Represents a json value
+#[derive(Clone, PartialEq, PartialOrd)]
+pub enum Json {
+    I64(i64),
+    U64(u64),
+    F64(f64),
+    String(string::String),
+    Boolean(bool),
+    Array(self::Array),
+    Object(self::Object),
+    Null,
+}
+
+pub type Array = Vec<Json>;
+pub type Object = BTreeMap<string::String, Json>;
+
+pub struct PrettyJson<'a> { inner: &'a Json }
+
+pub struct AsJson<'a, T: 'a> { inner: &'a T }
+pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option<uint> }
+
+/// The errors that can arise while parsing a JSON stream.
+#[derive(Clone, Copy, PartialEq)]
+pub enum ErrorCode {
+    InvalidSyntax,
+    InvalidNumber,
+    EOFWhileParsingObject,
+    EOFWhileParsingArray,
+    EOFWhileParsingValue,
+    EOFWhileParsingString,
+    KeyMustBeAString,
+    ExpectedColon,
+    TrailingCharacters,
+    TrailingComma,
+    InvalidEscape,
+    InvalidUnicodeCodePoint,
+    LoneLeadingSurrogateInHexEscape,
+    UnexpectedEndOfHexEscape,
+    UnrecognizedHex,
+    NotFourDigit,
+    NotUtf8,
+}
+
+#[derive(Clone, Copy, PartialEq, Show)]
+pub enum ParserError {
+    /// msg, line, col
+    SyntaxError(ErrorCode, uint, uint),
+    IoError(io::IoErrorKind, &'static str),
+}
+
+// Builder and Parser have the same errors.
+pub type BuilderError = ParserError;
+
+#[derive(Clone, PartialEq, Show)]
+pub enum DecoderError {
+    ParseError(ParserError),
+    ExpectedError(string::String, string::String),
+    MissingFieldError(string::String),
+    UnknownVariantError(string::String),
+    ApplicationError(string::String)
+}
+
+/// Returns a readable error string for a given error code.
+pub fn error_str(error: ErrorCode) -> &'static str {
+    match error {
+        InvalidSyntax => "invalid syntax",
+        InvalidNumber => "invalid number",
+        EOFWhileParsingObject => "EOF While parsing object",
+        EOFWhileParsingArray => "EOF While parsing array",
+        EOFWhileParsingValue => "EOF While parsing value",
+        EOFWhileParsingString => "EOF While parsing string",
+        KeyMustBeAString => "key must be a string",
+        ExpectedColon => "expected `:`",
+        TrailingCharacters => "trailing characters",
+        TrailingComma => "trailing comma",
+        InvalidEscape => "invalid escape",
+        UnrecognizedHex => "invalid \\u{ esc}ape (unrecognized hex)",
+        NotFourDigit => "invalid \\u{ esc}ape (not four digits)",
+        NotUtf8 => "contents not utf-8",
+        InvalidUnicodeCodePoint => "invalid Unicode code point",
+        LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape",
+        UnexpectedEndOfHexEscape => "unexpected end of hex escape",
+    }
+}
+
+/// Shortcut function to decode a JSON `&str` into an object
+pub fn decode<T: ::Decodable<Decoder, DecoderError>>(s: &str) -> DecodeResult<T> {
+    let json = match from_str(s) {
+        Ok(x) => x,
+        Err(e) => return Err(ParseError(e))
+    };
+
+    let mut decoder = Decoder::new(json);
+    ::Decodable::decode(&mut decoder)
+}
+
+/// Shortcut function to encode a `T` into a JSON `String`
+pub fn encode<T>(object: &T) -> string::String
+                 where T: for<'a> Encodable<Encoder<'a>, fmt::Error>
+{
+    let mut s = String::new();
+    {
+        let mut encoder = Encoder::new(&mut s);
+        let _ = object.encode(&mut encoder);
+    }
+    s
+}
+
+impl fmt::Show for ErrorCode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        error_str(*self).fmt(f)
+    }
+}
+
+fn io_error_to_error(io: io::IoError) -> ParserError {
+    IoError(io.kind, io.desc)
+}
+
+impl std::error::Error for DecoderError {
+    fn description(&self) -> &str { "decoder error" }
+    fn detail(&self) -> Option<std::string::String> { Some(self.to_string()) }
+}
+
+pub type EncodeResult = fmt::Result;
+pub type DecodeResult<T> = Result<T, DecoderError>;
+
+fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result {
+    try!(wr.write_str("\""));
+
+    let mut start = 0;
+
+    for (i, byte) in v.bytes().enumerate() {
+        let escaped = match byte {
+            b'"' => "\\\"",
+            b'\\' => "\\\\",
+            b'\x00' => "\\u0000",
+            b'\x01' => "\\u0001",
+            b'\x02' => "\\u0002",
+            b'\x03' => "\\u0003",
+            b'\x04' => "\\u0004",
+            b'\x05' => "\\u0005",
+            b'\x06' => "\\u0006",
+            b'\x07' => "\\u0007",
+            b'\x08' => "\\b",
+            b'\t' => "\\t",
+            b'\n' => "\\n",
+            b'\x0b' => "\\u000b",
+            b'\x0c' => "\\f",
+            b'\r' => "\\r",
+            b'\x0e' => "\\u000e",
+            b'\x0f' => "\\u000f",
+            b'\x10' => "\\u0010",
+            b'\x11' => "\\u0011",
+            b'\x12' => "\\u0012",
+            b'\x13' => "\\u0013",
+            b'\x14' => "\\u0014",
+            b'\x15' => "\\u0015",
+            b'\x16' => "\\u0016",
+            b'\x17' => "\\u0017",
+            b'\x18' => "\\u0018",
+            b'\x19' => "\\u0019",
+            b'\x1a' => "\\u001a",
+            b'\x1b' => "\\u001b",
+            b'\x1c' => "\\u001c",
+            b'\x1d' => "\\u001d",
+            b'\x1e' => "\\u001e",
+            b'\x1f' => "\\u001f",
+            b'\x7f' => "\\u007f",
+            _ => { continue; }
+        };
+
+        if start < i {
+            try!(wr.write_str(v[start..i]));
+        }
+
+        try!(wr.write_str(escaped));
+
+        start = i + 1;
+    }
+
+    if start != v.len() {
+        try!(wr.write_str(v[start..]));
+    }
+
+    wr.write_str("\"")
+}
+
+fn escape_char(writer: &mut fmt::Writer, v: char) -> fmt::Result {
+    let mut buf = [0; 4];
+    let n = v.encode_utf8(&mut buf).unwrap();
+    let buf = unsafe { str::from_utf8_unchecked(buf[0..n]) };
+    escape_str(writer, buf)
+}
+
+fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
+    const BUF: &'static str = "                ";
+
+    while n >= BUF.len() {
+        try!(wr.write_str(BUF));
+        n -= BUF.len();
+    }
+
+    if n > 0 {
+        wr.write_str(BUF[..n])
+    } else {
+        Ok(())
+    }
+}
+
+fn fmt_number_or_null(v: f64) -> string::String {
+    match v.classify() {
+        Fp::Nan | Fp::Infinite => string::String::from_str("null"),
+        _ if v.fract() != 0f64 => f64::to_str_digits(v, 6u),
+        _ => f64::to_str_digits(v, 6u) + ".0",
+    }
+}
+
+/// A structure for implementing serialization to JSON.
+pub struct Encoder<'a> {
+    writer: &'a mut (fmt::Writer+'a),
+}
+
+impl<'a> Encoder<'a> {
+    /// Creates a new JSON encoder whose output will be written to the writer
+    /// specified.
+    pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> {
+        Encoder { writer: writer }
+    }
+}
+
+impl<'a> ::Encoder<fmt::Error> for Encoder<'a> {
+    fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
+
+    fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
+
+    fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
+
+    fn emit_bool(&mut self, v: bool) -> EncodeResult {
+        if v {
+            write!(self.writer, "true")
+        } else {
+            write!(self.writer, "false")
+        }
+    }
+
+    fn emit_f64(&mut self, v: f64) -> EncodeResult {
+        write!(self.writer, "{}", fmt_number_or_null(v))
+    }
+    fn emit_f32(&mut self, v: f32) -> EncodeResult {
+        self.emit_f64(v as f64)
+    }
+
+    fn emit_char(&mut self, v: char) -> EncodeResult {
+        escape_char(self.writer, v)
+    }
+    fn emit_str(&mut self, v: &str) -> EncodeResult {
+        escape_str(self.writer, v)
+    }
+
+    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+
+    fn emit_enum_variant<F>(&mut self,
+                            name: &str,
+                            _id: uint,
+                            cnt: uint,
+                            f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        // enums are encoded as strings or objects
+        // Bunny => "Bunny"
+        // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
+        if cnt == 0 {
+            escape_str(self.writer, name)
+        } else {
+            try!(write!(self.writer, "{{\"variant\":"));
+            try!(escape_str(self.writer, name));
+            try!(write!(self.writer, ",\"fields\":["));
+            try!(f(self));
+            write!(self.writer, "]}}")
+        }
+    }
+
+    fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        if idx != 0 {
+            try!(write!(self.writer, ","));
+        }
+        f(self)
+    }
+
+    fn emit_enum_struct_variant<F>(&mut self,
+                                   name: &str,
+                                   id: uint,
+                                   cnt: uint,
+                                   f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_enum_variant(name, id, cnt, f)
+    }
+
+    fn emit_enum_struct_variant_field<F>(&mut self,
+                                         _: &str,
+                                         idx: uint,
+                                         f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_enum_variant_arg(idx, f)
+    }
+
+    fn emit_struct<F>(&mut self, _: &str, _: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        try!(write!(self.writer, "{{"));
+        try!(f(self));
+        write!(self.writer, "}}")
+    }
+
+    fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        if idx != 0 { try!(write!(self.writer, ",")); }
+        try!(escape_str(self.writer, name));
+        try!(write!(self.writer, ":"));
+        f(self)
+    }
+
+    fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_tuple_struct<F>(&mut self, _name: &str, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_option<F>(&mut self, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+    fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
+    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+
+    fn emit_seq<F>(&mut self, _len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        try!(write!(self.writer, "["));
+        try!(f(self));
+        write!(self.writer, "]")
+    }
+
+    fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        if idx != 0 {
+            try!(write!(self.writer, ","));
+        }
+        f(self)
+    }
+
+    fn emit_map<F>(&mut self, _len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        try!(write!(self.writer, "{{"));
+        try!(f(self));
+        write!(self.writer, "}}")
+    }
+
+    fn emit_map_elt_key<F>(&mut self, idx: uint, mut f: F) -> EncodeResult where
+        F: FnMut(&mut Encoder<'a>) -> EncodeResult,
+    {
+        if idx != 0 { try!(write!(self.writer, ",")) }
+        // ref #12967, make sure to wrap a key in double quotes,
+        // in the event that its of a type that omits them (eg numbers)
+        let mut buf = Vec::new();
+        // FIXME(14302) remove the transmute and unsafe block.
+        unsafe {
+            let mut check_encoder = Encoder::new(&mut buf);
+            try!(f(transmute(&mut check_encoder)));
+        }
+        let out = str::from_utf8(buf[]).unwrap();
+        let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
+        if needs_wrapping { try!(write!(self.writer, "\"")); }
+        try!(f(self));
+        if needs_wrapping { try!(write!(self.writer, "\"")); }
+        Ok(())
+    }
+
+    fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    {
+        try!(write!(self.writer, ":"));
+        f(self)
+    }
+}
+
+/// Another encoder for JSON, but prints out human-readable JSON instead of
+/// compact data
+pub struct PrettyEncoder<'a> {
+    writer: &'a mut (fmt::Writer+'a),
+    curr_indent: uint,
+    indent: uint,
+}
+
+impl<'a> PrettyEncoder<'a> {
+    /// Creates a new encoder whose output will be written to the specified writer
+    pub fn new(writer: &'a mut fmt::Writer) -> PrettyEncoder<'a> {
+        PrettyEncoder { writer: writer, curr_indent: 0, indent: 2, }
+    }
+
+    /// Set the number of spaces to indent for each level.
+    /// This is safe to set during encoding.
+    pub fn set_indent(&mut self, indent: uint) {
+        // self.indent very well could be 0 so we need to use checked division.
+        let level = self.curr_indent.checked_div(self.indent).unwrap_or(0);
+        self.indent = indent;
+        self.curr_indent = level * self.indent;
+    }
+}
+
+impl<'a> ::Encoder<fmt::Error> for PrettyEncoder<'a> {
+    fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") }
+
+    fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u64(&mut self, v: u64) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u32(&mut self, v: u32) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u16(&mut self, v: u16) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_u8(&mut self, v: u8) -> EncodeResult { write!(self.writer, "{}", v) }
+
+    fn emit_int(&mut self, v: int) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i64(&mut self, v: i64) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i32(&mut self, v: i32) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i16(&mut self, v: i16) -> EncodeResult { write!(self.writer, "{}", v) }
+    fn emit_i8(&mut self, v: i8) -> EncodeResult { write!(self.writer, "{}", v) }
+
+    fn emit_bool(&mut self, v: bool) -> EncodeResult {
+        if v {
+            write!(self.writer, "true")
+        } else {
+            write!(self.writer, "false")
+        }
+    }
+
+    fn emit_f64(&mut self, v: f64) -> EncodeResult {
+        write!(self.writer, "{}", fmt_number_or_null(v))
+    }
+    fn emit_f32(&mut self, v: f32) -> EncodeResult {
+        self.emit_f64(v as f64)
+    }
+
+    fn emit_char(&mut self, v: char) -> EncodeResult {
+        escape_char(self.writer, v)
+    }
+    fn emit_str(&mut self, v: &str) -> EncodeResult {
+        escape_str(self.writer, v)
+    }
+
+    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+
+    fn emit_enum_variant<F>(&mut self,
+                            name: &str,
+                            _id: uint,
+                            cnt: uint,
+                            f: F)
+                            -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if cnt == 0 {
+            escape_str(self.writer, name)
+        } else {
+            try!(write!(self.writer, "{{\n"));
+            self.curr_indent += self.indent;
+            try!(spaces(self.writer, self.curr_indent));
+            try!(write!(self.writer, "\"variant\": "));
+            try!(escape_str(self.writer, name));
+            try!(write!(self.writer, ",\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            try!(write!(self.writer, "\"fields\": [\n"));
+            self.curr_indent += self.indent;
+            try!(f(self));
+            self.curr_indent -= self.indent;
+            try!(write!(self.writer, "\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            self.curr_indent -= self.indent;
+            try!(write!(self.writer, "]\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            write!(self.writer, "}}")
+        }
+    }
+
+    fn emit_enum_variant_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if idx != 0 {
+            try!(write!(self.writer, ",\n"));
+        }
+        try!(spaces(self.writer, self.curr_indent));
+        f(self)
+    }
+
+    fn emit_enum_struct_variant<F>(&mut self,
+                                   name: &str,
+                                   id: uint,
+                                   cnt: uint,
+                                   f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_enum_variant(name, id, cnt, f)
+    }
+
+    fn emit_enum_struct_variant_field<F>(&mut self,
+                                         _: &str,
+                                         idx: uint,
+                                         f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_enum_variant_arg(idx, f)
+    }
+
+
+    fn emit_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if len == 0 {
+            write!(self.writer, "{{}}")
+        } else {
+            try!(write!(self.writer, "{{"));
+            self.curr_indent += self.indent;
+            try!(f(self));
+            self.curr_indent -= self.indent;
+            try!(write!(self.writer, "\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            write!(self.writer, "}}")
+        }
+    }
+
+    fn emit_struct_field<F>(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if idx == 0 {
+            try!(write!(self.writer, "\n"));
+        } else {
+            try!(write!(self.writer, ",\n"));
+        }
+        try!(spaces(self.writer, self.curr_indent));
+        try!(escape_str(self.writer, name));
+        try!(write!(self.writer, ": "));
+        f(self)
+    }
+
+    fn emit_tuple<F>(&mut self, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_tuple_struct<F>(&mut self, _: &str, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_struct_arg<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        self.emit_seq_elt(idx, f)
+    }
+
+    fn emit_option<F>(&mut self, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+    fn emit_option_none(&mut self) -> EncodeResult { self.emit_nil() }
+    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        f(self)
+    }
+
+    fn emit_seq<F>(&mut self, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if len == 0 {
+            write!(self.writer, "[]")
+        } else {
+            try!(write!(self.writer, "["));
+            self.curr_indent += self.indent;
+            try!(f(self));
+            self.curr_indent -= self.indent;
+            try!(write!(self.writer, "\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            write!(self.writer, "]")
+        }
+    }
+
+    fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if idx == 0 {
+            try!(write!(self.writer, "\n"));
+        } else {
+            try!(write!(self.writer, ",\n"));
+        }
+        try!(spaces(self.writer, self.curr_indent));
+        f(self)
+    }
+
+    fn emit_map<F>(&mut self, len: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if len == 0 {
+            write!(self.writer, "{{}}")
+        } else {
+            try!(write!(self.writer, "{{"));
+            self.curr_indent += self.indent;
+            try!(f(self));
+            self.curr_indent -= self.indent;
+            try!(write!(self.writer, "\n"));
+            try!(spaces(self.writer, self.curr_indent));
+            write!(self.writer, "}}")
+        }
+    }
+
+    fn emit_map_elt_key<F>(&mut self, idx: uint, mut f: F) -> EncodeResult where
+        F: FnMut(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        if idx == 0 {
+            try!(write!(self.writer, "\n"));
+        } else {
+            try!(write!(self.writer, ",\n"));
+        }
+        try!(spaces(self.writer, self.curr_indent));
+        // ref #12967, make sure to wrap a key in double quotes,
+        // in the event that its of a type that omits them (eg numbers)
+        let mut buf = Vec::new();
+        // FIXME(14302) remove the transmute and unsafe block.
+        unsafe {
+            let mut check_encoder = PrettyEncoder::new(&mut buf);
+            try!(f(transmute(&mut check_encoder)));
+        }
+        let out = str::from_utf8(buf[]).unwrap();
+        let needs_wrapping = out.char_at(0) != '"' && out.char_at_reverse(out.len()) != '"';
+        if needs_wrapping { try!(write!(self.writer, "\"")); }
+        try!(f(self));
+        if needs_wrapping { try!(write!(self.writer, "\"")); }
+        Ok(())
+    }
+
+    fn emit_map_elt_val<F>(&mut self, _idx: uint, f: F) -> EncodeResult where
+        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
+    {
+        try!(write!(self.writer, ": "));
+        f(self)
+    }
+}
+
+impl<E: ::Encoder<S>, S> Encodable<E, S> for Json {
+    fn encode(&self, e: &mut E) -> Result<(), S> {
+        match *self {
+            Json::I64(v) => v.encode(e),
+            Json::U64(v) => v.encode(e),
+            Json::F64(v) => v.encode(e),
+            Json::String(ref v) => v.encode(e),
+            Json::Boolean(v) => v.encode(e),
+            Json::Array(ref v) => v.encode(e),
+            Json::Object(ref v) => v.encode(e),
+            Json::Null => e.emit_nil(),
+        }
+    }
+}
+
+/// Create an `AsJson` wrapper which can be used to print a value as JSON
+/// on-the-fly via `write!`
+pub fn as_json<T>(t: &T) -> AsJson<T> {
+    AsJson { inner: t }
+}
+
+/// Create an `AsPrettyJson` wrapper which can be used to print a value as JSON
+/// on-the-fly via `write!`
+pub fn as_pretty_json<T>(t: &T) -> AsPrettyJson<T> {
+    AsPrettyJson { inner: t, indent: None }
+}
+
+impl Json {
+    /// Borrow this json object as a pretty object to generate a pretty
+    /// representation for it via `Show`.
+    pub fn pretty(&self) -> PrettyJson {
+        PrettyJson { inner: self }
+    }
+
+     /// If the Json value is an Object, returns the value associated with the provided key.
+    /// Otherwise, returns None.
+    pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
+        match self {
+            &Json::Object(ref map) => map.get(key),
+            _ => None
+        }
+    }
+
+    /// Attempts to get a nested Json Object for each key in `keys`.
+    /// If any key is found not to exist, find_path will return None.
+    /// Otherwise, it will return the Json value associated with the final key.
+    pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Json>{
+        let mut target = self;
+        for key in keys.iter() {
+            match target.find(*key) {
+                Some(t) => { target = t; },
+                None => return None
+            }
+        }
+        Some(target)
+    }
+
+    /// If the Json value is an Object, performs a depth-first search until
+    /// a value associated with the provided key is found. If no value is found
+    /// or the Json value is not an Object, returns None.
+    pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
+        match self {
+            &Json::Object(ref map) => {
+                match map.get(key) {
+                    Some(json_value) => Some(json_value),
+                    None => {
+                        for (_, v) in map.iter() {
+                            match v.search(key) {
+                                x if x.is_some() => return x,
+                                _ => ()
+                            }
+                        }
+                        None
+                    }
+                }
+            },
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is an Object. Returns false otherwise.
+    pub fn is_object<'a>(&'a self) -> bool {
+        self.as_object().is_some()
+    }
+
+    /// If the Json value is an Object, returns the associated BTreeMap.
+    /// Returns None otherwise.
+    pub fn as_object<'a>(&'a self) -> Option<&'a Object> {
+        match self {
+            &Json::Object(ref map) => Some(map),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is an Array. Returns false otherwise.
+    pub fn is_array<'a>(&'a self) -> bool {
+        self.as_array().is_some()
+    }
+
+    /// If the Json value is an Array, returns the associated vector.
+    /// Returns None otherwise.
+    pub fn as_array<'a>(&'a self) -> Option<&'a Array> {
+        match self {
+            &Json::Array(ref array) => Some(&*array),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a String. Returns false otherwise.
+    pub fn is_string<'a>(&'a self) -> bool {
+        self.as_string().is_some()
+    }
+
+    /// If the Json value is a String, returns the associated str.
+    /// Returns None otherwise.
+    pub fn as_string<'a>(&'a self) -> Option<&'a str> {
+        match *self {
+            Json::String(ref s) => Some(s[]),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Number. Returns false otherwise.
+    pub fn is_number(&self) -> bool {
+        match *self {
+            Json::I64(_) | Json::U64(_) | Json::F64(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the Json value is a i64. Returns false otherwise.
+    pub fn is_i64(&self) -> bool {
+        match *self {
+            Json::I64(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the Json value is a u64. Returns false otherwise.
+    pub fn is_u64(&self) -> bool {
+        match *self {
+            Json::U64(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the Json value is a f64. Returns false otherwise.
+    pub fn is_f64(&self) -> bool {
+        match *self {
+            Json::F64(_) => true,
+            _ => false,
+        }
+    }
+
+    /// If the Json value is a number, return or cast it to a i64.
+    /// Returns None otherwise.
+    pub fn as_i64(&self) -> Option<i64> {
+        match *self {
+            Json::I64(n) => Some(n),
+            Json::U64(n) => num::cast(n),
+            _ => None
+        }
+    }
+
+    /// If the Json value is a number, return or cast it to a u64.
+    /// Returns None otherwise.
+    pub fn as_u64(&self) -> Option<u64> {
+        match *self {
+            Json::I64(n) => num::cast(n),
+            Json::U64(n) => Some(n),
+            _ => None
+        }
+    }
+
+    /// If the Json value is a number, return or cast it to a f64.
+    /// Returns None otherwise.
+    pub fn as_f64(&self) -> Option<f64> {
+        match *self {
+            Json::I64(n) => num::cast(n),
+            Json::U64(n) => num::cast(n),
+            Json::F64(n) => Some(n),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Boolean. Returns false otherwise.
+    pub fn is_boolean(&self) -> bool {
+        self.as_boolean().is_some()
+    }
+
+    /// If the Json value is a Boolean, returns the associated bool.
+    /// Returns None otherwise.
+    pub fn as_boolean(&self) -> Option<bool> {
+        match self {
+            &Json::Boolean(b) => Some(b),
+            _ => None
+        }
+    }
+
+    /// Returns true if the Json value is a Null. Returns false otherwise.
+    pub fn is_null(&self) -> bool {
+        self.as_null().is_some()
+    }
+
+    /// If the Json value is a Null, returns ().
+    /// Returns None otherwise.
+    pub fn as_null(&self) -> Option<()> {
+        match self {
+            &Json::Null => Some(()),
+            _ => None
+        }
+    }
+}
+
+impl<'a> ops::Index<&'a str>  for Json {
+    type Output = Json;
+
+    fn index(&self, idx: & &str) -> &Json {
+        self.find(*idx).unwrap()
+    }
+}
+
+impl ops::Index<uint> for Json {
+    type Output = Json;
+
+    fn index<'a>(&'a self, idx: &uint) -> &'a Json {
+        match self {
+            &Json::Array(ref v) => v.index(idx),
+            _ => panic!("can only index Json with uint if it is an array")
+        }
+    }
+}
+
+/// The output of the streaming parser.
+#[derive(PartialEq, Clone, Show)]
+pub enum JsonEvent {
+    ObjectStart,
+    ObjectEnd,
+    ArrayStart,
+    ArrayEnd,
+    BooleanValue(bool),
+    I64Value(i64),
+    U64Value(u64),
+    F64Value(f64),
+    StringValue(string::String),
+    NullValue,
+    Error(ParserError),
+}
+
+#[derive(PartialEq, Show)]
+enum ParserState {
+    // Parse a value in an array, true means first element.
+    ParseArray(bool),
+    // Parse ',' or ']' after an element in an array.
+    ParseArrayComma,
+    // Parse a key:value in an object, true means first element.
+    ParseObject(bool),
+    // Parse ',' or ']' after an element in an object.
+    ParseObjectComma,
+    // Initial state.
+    ParseStart,
+    // Expecting the stream to end.
+    ParseBeforeFinish,
+    // Parsing can't continue.
+    ParseFinished,
+}
+
+/// A Stack represents the current position of the parser in the logical
+/// structure of the JSON stream.
+/// For example foo.bar[3].x
+pub struct Stack {
+    stack: Vec<InternalStackElement>,
+    str_buffer: Vec<u8>,
+}
+
+/// StackElements compose a Stack.
+/// For example, Key("foo"), Key("bar"), Index(3) and Key("x") are the
+/// StackElements compositing the stack that represents foo.bar[3].x
+#[derive(PartialEq, Clone, Show)]
+pub enum StackElement<'l> {
+    Index(u32),
+    Key(&'l str),
+}
+
+// Internally, Key elements are stored as indices in a buffer to avoid
+// allocating a string for every member of an object.
+#[derive(PartialEq, Clone, Show)]
+enum InternalStackElement {
+    InternalIndex(u32),
+    InternalKey(u16, u16), // start, size
+}
+
+impl Stack {
+    pub fn new() -> Stack {
+        Stack { stack: Vec::new(), str_buffer: Vec::new() }
+    }
+
+    /// Returns The number of elements in the Stack.
+    pub fn len(&self) -> uint { self.stack.len() }
+
+    /// Returns true if the stack is empty.
+    pub fn is_empty(&self) -> bool { self.stack.is_empty() }
+
+    /// Provides access to the StackElement at a given index.
+    /// lower indices are at the bottom of the stack while higher indices are
+    /// at the top.
+    pub fn get<'l>(&'l self, idx: uint) -> StackElement<'l> {
+        match self.stack[idx] {
+            InternalIndex(i) => Index(i),
+            InternalKey(start, size) => {
+                Key(str::from_utf8(
+                    self.str_buffer[start as uint .. start as uint + size as uint]).unwrap())
+            }
+        }
+    }
+
+    /// Compares this stack with an array of StackElements.
+    pub fn is_equal_to(&self, rhs: &[StackElement]) -> bool {
+        if self.stack.len() != rhs.len() { return false; }
+        for i in range(0, rhs.len()) {
+            if self.get(i) != rhs[i] { return false; }
+        }
+        return true;
+    }
+
+    /// Returns true if the bottom-most elements of this stack are the same as
+    /// the ones passed as parameter.
+    pub fn starts_with(&self, rhs: &[StackElement]) -> bool {
+        if self.stack.len() < rhs.len() { return false; }
+        for i in range(0, rhs.len()) {
+            if self.get(i) != rhs[i] { return false; }
+        }
+        return true;
+    }
+
+    /// Returns true if the top-most elements of this stack are the same as
+    /// the ones passed as parameter.
+    pub fn ends_with(&self, rhs: &[StackElement]) -> bool {
+        if self.stack.len() < rhs.len() { return false; }
+        let offset = self.stack.len() - rhs.len();
+        for i in range(0, rhs.len()) {
+            if self.get(i + offset) != rhs[i] { return false; }
+        }
+        return true;
+    }
+
+    /// Returns the top-most element (if any).
+    pub fn top<'l>(&'l self) -> Option<StackElement<'l>> {
+        return match self.stack.last() {
+            None => None,
+            Some(&InternalIndex(i)) => Some(Index(i)),
+            Some(&InternalKey(start, size)) => {
+                Some(Key(str::from_utf8(
+                    self.str_buffer[start as uint .. (start+size) as uint]
+                ).unwrap()))
+            }
+        }
+    }
+
+    // Used by Parser to insert Key elements at the top of the stack.
+    fn push_key(&mut self, key: string::String) {
+        self.stack.push(InternalKey(self.str_buffer.len() as u16, key.len() as u16));
+        for c in key.as_bytes().iter() {
+            self.str_buffer.push(*c);
+        }
+    }
+
+    // Used by Parser to insert Index elements at the top of the stack.
+    fn push_index(&mut self, index: u32) {
+        self.stack.push(InternalIndex(index));
+    }
+
+    // Used by Parser to remove the top-most element of the stack.
+    fn pop(&mut self) {
+        assert!(!self.is_empty());
+        match *self.stack.last().unwrap() {
+            InternalKey(_, sz) => {
+                let new_size = self.str_buffer.len() - sz as uint;
+                self.str_buffer.truncate(new_size);
+            }
+            InternalIndex(_) => {}
+        }
+        self.stack.pop();
+    }
+
+    // Used by Parser to test whether the top-most element is an index.
+    fn last_is_index(&self) -> bool {
+        if self.is_empty() { return false; }
+        return match *self.stack.last().unwrap() {
+            InternalIndex(_) => true,
+            _ => false,
+        }
+    }
+
+    // Used by Parser to increment the index of the top-most element.
+    fn bump_index(&mut self) {
+        let len = self.stack.len();
+        let idx = match *self.stack.last().unwrap() {
+            InternalIndex(i) => { i + 1 }
+            _ => { panic!(); }
+        };
+        self.stack[len - 1] = InternalIndex(idx);
+    }
+}
+
+/// A streaming JSON parser implemented as an iterator of JsonEvent, consuming
+/// an iterator of char.
+pub struct Parser<T> {
+    rdr: T,
+    ch: Option<char>,
+    line: uint,
+    col: uint,
+    // We maintain a stack representing where we are in the logical structure
+    // of the JSON stream.
+    stack: Stack,
+    // A state machine is kept to make it possible to interrupt and resume parsing.
+    state: ParserState,
+}
+
+impl<T: Iterator<Item=char>> Iterator for Parser<T> {
+    type Item = JsonEvent;
+
+    fn next(&mut self) -> Option<JsonEvent> {
+        if self.state == ParseFinished {
+            return None;
+        }
+
+        if self.state == ParseBeforeFinish {
+            self.parse_whitespace();
+            // Make sure there is no trailing characters.
+            if self.eof() {
+                self.state = ParseFinished;
+                return None;
+            } else {
+                return Some(self.error_event(TrailingCharacters));
+            }
+        }
+
+        return Some(self.parse());
+    }
+}
+
+impl<T: Iterator<Item=char>> Parser<T> {
+    /// Creates the JSON parser.
+    pub fn new(rdr: T) -> Parser<T> {
+        let mut p = Parser {
+            rdr: rdr,
+            ch: Some('\x00'),
+            line: 1,
+            col: 0,
+            stack: Stack::new(),
+            state: ParseStart,
+        };
+        p.bump();
+        return p;
+    }
+
+    /// Provides access to the current position in the logical structure of the
+    /// JSON stream.
+    pub fn stack<'l>(&'l self) -> &'l Stack {
+        return &self.stack;
+    }
+
+    fn eof(&self) -> bool { self.ch.is_none() }
+    fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
+    fn bump(&mut self) {
+        self.ch = self.rdr.next();
+
+        if self.ch_is('\n') {
+            self.line += 1u;
+            self.col = 1u;
+        } else {
+            self.col += 1u;
+        }
+    }
+
+    fn next_char(&mut self) -> Option<char> {
+        self.bump();
+        self.ch
+    }
+    fn ch_is(&self, c: char) -> bool {
+        self.ch == Some(c)
+    }
+
+    fn error<T>(&self, reason: ErrorCode) -> Result<T, ParserError> {
+        Err(SyntaxError(reason, self.line, self.col))
+    }
+
+    fn parse_whitespace(&mut self) {
+        while self.ch_is(' ') ||
+              self.ch_is('\n') ||
+              self.ch_is('\t') ||
+              self.ch_is('\r') { self.bump(); }
+    }
+
+    fn parse_number(&mut self) -> JsonEvent {
+        let mut neg = false;
+
+        if self.ch_is('-') {
+            self.bump();
+            neg = true;
+        }
+
+        let res = match self.parse_u64() {
+            Ok(res) => res,
+            Err(e) => { return Error(e); }
+        };
+
+        if self.ch_is('.') || self.ch_is('e') || self.ch_is('E') {
+            let mut res = res as f64;
+
+            if self.ch_is('.') {
+                res = match self.parse_decimal(res) {
+                    Ok(res) => res,
+                    Err(e) => { return Error(e); }
+                };
+            }
+
+            if self.ch_is('e') || self.ch_is('E') {
+                res = match self.parse_exponent(res) {
+                    Ok(res) => res,
+                    Err(e) => { return Error(e); }
+                };
+            }
+
+            if neg {
+                res *= -1.0;
+            }
+
+            F64Value(res)
+        } else {
+            if neg {
+                let res = -(res as i64);
+
+                // Make sure we didn't underflow.
+                if res > 0 {
+                    Error(SyntaxError(InvalidNumber, self.line, self.col))
+                } else {
+                    I64Value(res)
+                }
+            } else {
+                U64Value(res)
+            }
+        }
+    }
+
+    fn parse_u64(&mut self) -> Result<u64, ParserError> {
+        let mut accum = 0;
+        let last_accum = 0; // necessary to detect overflow.
+
+        match self.ch_or_null() {
+            '0' => {
+                self.bump();
+
+                // A leading '0' must be the only digit before the decimal point.
+                match self.ch_or_null() {
+                    '0' ... '9' => return self.error(InvalidNumber),
+                    _ => ()
+                }
+            },
+            '1' ... '9' => {
+                while !self.eof() {
+                    match self.ch_or_null() {
+                        c @ '0' ... '9' => {
+                            accum *= 10;
+                            accum += (c as u64) - ('0' as u64);
+
+                            // Detect overflow by comparing to the last value.
+                            if accum <= last_accum { return self.error(InvalidNumber); }
+
+                            self.bump();
+                        }
+                        _ => break,
+                    }
+                }
+            }
+            _ => return self.error(InvalidNumber),
+        }
+
+        Ok(accum)
+    }
+
+    fn parse_decimal(&mut self, mut res: f64) -> Result<f64, ParserError> {
+        self.bump();
+
+        // Make sure a digit follows the decimal place.
+        match self.ch_or_null() {
+            '0' ... '9' => (),
+             _ => return self.error(InvalidNumber)
+        }
+
+        let mut dec = 1.0;
+        while !self.eof() {
+            match self.ch_or_null() {
+                c @ '0' ... '9' => {
+                    dec /= 10.0;
+                    res += (((c as int) - ('0' as int)) as f64) * dec;
+                    self.bump();
+                }
+                _ => break,
+            }
+        }
+
+        Ok(res)
+    }
+
+    fn parse_exponent(&mut self, mut res: f64) -> Result<f64, ParserError> {
+        self.bump();
+
+        let mut exp = 0u;
+        let mut neg_exp = false;
+
+        if self.ch_is('+') {
+            self.bump();
+        } else if self.ch_is('-') {
+            self.bump();
+            neg_exp = true;
+        }
+
+        // Make sure a digit follows the exponent place.
+        match self.ch_or_null() {
+            '0' ... '9' => (),
+            _ => return self.error(InvalidNumber)
+        }
+        while !self.eof() {
+            match self.ch_or_null() {
+                c @ '0' ... '9' => {
+                    exp *= 10;
+                    exp += (c as uint) - ('0' as uint);
+
+                    self.bump();
+                }
+                _ => break
+            }
+        }
+
+        let exp = 10_f64.powi(exp as i32);
+        if neg_exp {
+            res /= exp;
+        } else {
+            res *= exp;
+        }
+
+        Ok(res)
+    }
+
+    fn decode_hex_escape(&mut self) -> Result<u16, ParserError> {
+        let mut i = 0u;
+        let mut n = 0u16;
+        while i < 4 && !self.eof() {
+            self.bump();
+            n = match self.ch_or_null() {
+                c @ '0' ... '9' => n * 16 + ((c as u16) - ('0' as u16)),
+                'a' | 'A' => n * 16 + 10,
+                'b' | 'B' => n * 16 + 11,
+                'c' | 'C' => n * 16 + 12,
+                'd' | 'D' => n * 16 + 13,
+                'e' | 'E' => n * 16 + 14,
+                'f' | 'F' => n * 16 + 15,
+                _ => return self.error(InvalidEscape)
+            };
+
+            i += 1u;
+        }
+
+        // Error out if we didn't parse 4 digits.
+        if i != 4 {
+            return self.error(InvalidEscape);
+        }
+
+        Ok(n)
+    }
+
+    fn parse_str(&mut self) -> Result<string::String, ParserError> {
+        let mut escape = false;
+        let mut res = string::String::new();
+
+        loop {
+            self.bump();
+            if self.eof() {
+                return self.error(EOFWhileParsingString);
+            }
+
+            if escape {
+                match self.ch_or_null() {
+                    '"' => res.push('"'),
+                    '\\' => res.push('\\'),
+                    '/' => res.push('/'),
+                    'b' => res.push('\x08'),
+                    'f' => res.push('\x0c'),
+                    'n' => res.push('\n'),
+                    'r' => res.push('\r'),
+                    't' => res.push('\t'),
+                    'u' => match try!(self.decode_hex_escape()) {
+                        0xDC00 ... 0xDFFF => {
+                            return self.error(LoneLeadingSurrogateInHexEscape)
+                        }
+
+                        // Non-BMP characters are encoded as a sequence of
+                        // two hex escapes, representing UTF-16 surrogates.
+                        n1 @ 0xD800 ... 0xDBFF => {
+                            match (self.next_char(), self.next_char()) {
+                                (Some('\\'), Some('u')) => (),
+                                _ => return self.error(UnexpectedEndOfHexEscape),
+                            }
+
+                            let buf = [n1, try!(self.decode_hex_escape())];
+                            match unicode_str::utf16_items(&buf).next() {
+                                Some(Utf16Item::ScalarValue(c)) => res.push(c),
+                                _ => return self.error(LoneLeadingSurrogateInHexEscape),
+                            }
+                        }
+
+                        n => match char::from_u32(n as u32) {
+                            Some(c) => res.push(c),
+                            None => return self.error(InvalidUnicodeCodePoint),
+                        },
+                    },
+                    _ => return self.error(InvalidEscape),
+                }
+                escape = false;
+            } else if self.ch_is('\\') {
+                escape = true;
+            } else {
+                match self.ch {
+                    Some('"') => {
+                        self.bump();
+                        return Ok(res);
+                    },
+                    Some(c) => res.push(c),
+                    None => unreachable!()
+                }
+            }
+        }
+    }
+
+    // Invoked at each iteration, consumes the stream until it has enough
+    // information to return a JsonEvent.
+    // Manages an internal state so that parsing can be interrupted and resumed.
+    // Also keeps track of the position in the logical structure of the json
+    // stream int the form of a stack that can be queried by the user using the
+    // stack() method.
+    fn parse(&mut self) -> JsonEvent {
+        loop {
+            // The only paths where the loop can spin a new iteration
+            // are in the cases ParseArrayComma and ParseObjectComma if ','
+            // is parsed. In these cases the state is set to (respectively)
+            // ParseArray(false) and ParseObject(false), which always return,
+            // so there is no risk of getting stuck in an infinite loop.
+            // All other paths return before the end of the loop's iteration.
+            self.parse_whitespace();
+
+            match self.state {
+                ParseStart => {
+                    return self.parse_start();
+                }
+                ParseArray(first) => {
+                    return self.parse_array(first);
+                }
+                ParseArrayComma => {
+                    match self.parse_array_comma_or_end() {
+                        Some(evt) => { return evt; }
+                        None => {}
+                    }
+                }
+                ParseObject(first) => {
+                    return self.parse_object(first);
+                }
+                ParseObjectComma => {
+                    self.stack.pop();
+                    if self.ch_is(',') {
+                        self.state = ParseObject(false);
+                        self.bump();
+                    } else {
+                        return self.parse_object_end();
+                    }
+                }
+                _ => {
+                    return self.error_event(InvalidSyntax);
+                }
+            }
+        }
+    }
+
+    fn parse_start(&mut self) -> JsonEvent {
+        let val = self.parse_value();
+        self.state = match val {
+            Error(_) => ParseFinished,
+            ArrayStart => ParseArray(true),
+            ObjectStart => ParseObject(true),
+            _ => ParseBeforeFinish,
+        };
+        return val;
+    }
+
+    fn parse_array(&mut self, first: bool) -> JsonEvent {
+        if self.ch_is(']') {
+            if !first {
+                self.error_event(InvalidSyntax)
+            } else {
+                self.state = if self.stack.is_empty() {
+                    ParseBeforeFinish
+                } else if self.stack.last_is_index() {
+                    ParseArrayComma
+                } else {
+                    ParseObjectComma
+                };
+                self.bump();
+                ArrayEnd
+            }
+        } else {
+            if first {
+                self.stack.push_index(0);
+            }
+            let val = self.parse_value();
+            self.state = match val {
+                Error(_) => ParseFinished,
+                ArrayStart => ParseArray(true),
+                ObjectStart => ParseObject(true),
+                _ => ParseArrayComma,
+            };
+            val
+        }
+    }
+
+    fn parse_array_comma_or_end(&mut self) -> Option<JsonEvent> {
+        if self.ch_is(',') {
+            self.stack.bump_index();
+            self.state = ParseArray(false);
+            self.bump();
+            None
+        } else if self.ch_is(']') {
+            self.stack.pop();
+            self.state = if self.stack.is_empty() {
+                ParseBeforeFinish
+            } else if self.stack.last_is_index() {
+                ParseArrayComma
+            } else {
+                ParseObjectComma
+            };
+            self.bump();
+            Some(ArrayEnd)
+        } else if self.eof() {
+            Some(self.error_event(EOFWhileParsingArray))
+        } else {
+            Some(self.error_event(InvalidSyntax))
+        }
+    }
+
+    fn parse_object(&mut self, first: bool) -> JsonEvent {
+        if self.ch_is('}') {
+            if !first {
+                if self.stack.is_empty() {
+                    return self.error_event(TrailingComma);
+                } else {
+                    self.stack.pop();
+                }
+            }
+            self.state = if self.stack.is_empty() {
+                ParseBeforeFinish
+            } else if self.stack.last_is_index() {
+                ParseArrayComma
+            } else {
+                ParseObjectComma
+            };
+            self.bump();
+            return ObjectEnd;
+        }
+        if self.eof() {
+            return self.error_event(EOFWhileParsingObject);
+        }
+        if !self.ch_is('"') {
+            return self.error_event(KeyMustBeAString);
+        }
+        let s = match self.parse_str() {
+            Ok(s) => s,
+            Err(e) => {
+                self.state = ParseFinished;
+                return Error(e);
+            }
+        };
+        self.parse_whitespace();
+        if self.eof() {
+            return self.error_event(EOFWhileParsingObject);
+        } else if self.ch_or_null() != ':' {
+            return self.error_event(ExpectedColon);
+        }
+        self.stack.push_key(s);
+        self.bump();
+        self.parse_whitespace();
+
+        let val = self.parse_value();
+
+        self.state = match val {
+            Error(_) => ParseFinished,
+            ArrayStart => ParseArray(true),
+            ObjectStart => ParseObject(true),
+            _ => ParseObjectComma,
+        };
+        return val;
+    }
+
+    fn parse_object_end(&mut self) -> JsonEvent {
+        if self.ch_is('}') {
+            self.state = if self.stack.is_empty() {
+                ParseBeforeFinish
+            } else if self.stack.last_is_index() {
+                ParseArrayComma
+            } else {
+                ParseObjectComma
+            };
+            self.bump();
+            ObjectEnd
+        } else if self.eof() {
+            self.error_event(EOFWhileParsingObject)
+        } else {
+            self.error_event(InvalidSyntax)
+        }
+    }
+
+    fn parse_value(&mut self) -> JsonEvent {
+        if self.eof() { return self.error_event(EOFWhileParsingValue); }
+        match self.ch_or_null() {
+            'n' => { self.parse_ident("ull", NullValue) }
+            't' => { self.parse_ident("rue", BooleanValue(true)) }
+            'f' => { self.parse_ident("alse", BooleanValue(false)) }
+            '0' ... '9' | '-' => self.parse_number(),
+            '"' => match self.parse_str() {
+                Ok(s) => StringValue(s),
+                Err(e) => Error(e),
+            },
+            '[' => {
+                self.bump();
+                ArrayStart
+            }
+            '{' => {
+                self.bump();
+                ObjectStart
+            }
+            _ => { self.error_event(InvalidSyntax) }
+        }
+    }
+
+    fn parse_ident(&mut self, ident: &str, value: JsonEvent) -> JsonEvent {
+        if ident.chars().all(|c| Some(c) == self.next_char()) {
+            self.bump();
+            value
+        } else {
+            Error(SyntaxError(InvalidSyntax, self.line, self.col))
+        }
+    }
+
+    fn error_event(&mut self, reason: ErrorCode) -> JsonEvent {
+        self.state = ParseFinished;
+        Error(SyntaxError(reason, self.line, self.col))
+    }
+}
+
+/// A Builder consumes a json::Parser to create a generic Json structure.
+pub struct Builder<T> {
+    parser: Parser<T>,
+    token: Option<JsonEvent>,
+}
+
+impl<T: Iterator<Item=char>> Builder<T> {
+    /// Create a JSON Builder.
+    pub fn new(src: T) -> Builder<T> {
+        Builder { parser: Parser::new(src), token: None, }
+    }
+
+    // Decode a Json value from a Parser.
+    pub fn build(&mut self) -> Result<Json, BuilderError> {
+        self.bump();
+        let result = self.build_value();
+        self.bump();
+        match self.token {
+            None => {}
+            Some(Error(e)) => { return Err(e); }
+            ref tok => { panic!("unexpected token {}", tok.clone()); }
+        }
+        result
+    }
+
+    fn bump(&mut self) {
+        self.token = self.parser.next();
+    }
+
+    fn build_value(&mut self) -> Result<Json, BuilderError> {
+        return match self.token {
+            Some(NullValue) => Ok(Json::Null),
+            Some(I64Value(n)) => Ok(Json::I64(n)),
+            Some(U64Value(n)) => Ok(Json::U64(n)),
+            Some(F64Value(n)) => Ok(Json::F64(n)),
+            Some(BooleanValue(b)) => Ok(Json::Boolean(b)),
+            Some(StringValue(ref mut s)) => {
+                let mut temp = string::String::new();
+                swap(s, &mut temp);
+                Ok(Json::String(temp))
+            }
+            Some(Error(e)) => Err(e),
+            Some(ArrayStart) => self.build_array(),
+            Some(ObjectStart) => self.build_object(),
+            Some(ObjectEnd) => self.parser.error(InvalidSyntax),
+            Some(ArrayEnd) => self.parser.error(InvalidSyntax),
+            None => self.parser.error(EOFWhileParsingValue),
+        }
+    }
+
+    fn build_array(&mut self) -> Result<Json, BuilderError> {
+        self.bump();
+        let mut values = Vec::new();
+
+        loop {
+            if self.token == Some(ArrayEnd) {
+                return Ok(Json::Array(values.into_iter().collect()));
+            }
+            match self.build_value() {
+                Ok(v) => values.push(v),
+                Err(e) => { return Err(e) }
+            }
+            self.bump();
+        }
+    }
+
+    fn build_object(&mut self) -> Result<Json, BuilderError> {
+        self.bump();
+
+        let mut values = BTreeMap::new();
+
+        loop {
+            match self.token {
+                Some(ObjectEnd) => { return Ok(Json::Object(values)); }
+                Some(Error(e)) => { return Err(e); }
+                None => { break; }
+                _ => {}
+            }
+            let key = match self.parser.stack().top() {
+                Some(Key(k)) => { k.to_string() }
+                _ => { panic!("invalid state"); }
+            };
+            match self.build_value() {
+                Ok(value) => { values.insert(key, value); }
+                Err(e) => { return Err(e); }
+            }
+            self.bump();
+        }
+        return self.parser.error(EOFWhileParsingObject);
+    }
+}
+
+/// Decodes a json value from an `&mut io::Reader`
+pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, BuilderError> {
+    let contents = match rdr.read_to_end() {
+        Ok(c)  => c,
+        Err(e) => return Err(io_error_to_error(e))
+    };
+    let s = match str::from_utf8(contents.as_slice()).ok() {
+        Some(s) => s,
+        _       => return Err(SyntaxError(NotUtf8, 0, 0))
+    };
+    let mut builder = Builder::new(s.chars());
+    builder.build()
+}
+
+/// Decodes a json value from a string
+pub fn from_str(s: &str) -> Result<Json, BuilderError> {
+    let mut builder = Builder::new(s.chars());
+    builder.build()
+}
+
+/// A structure to decode JSON to values in rust.
+pub struct Decoder {
+    stack: Vec<Json>,
+}
+
+impl Decoder {
+    /// Creates a new decoder instance for decoding the specified JSON value.
+    pub fn new(json: Json) -> Decoder {
+        Decoder { stack: vec![json] }
+    }
+}
+
+impl Decoder {
+    fn pop(&mut self) -> Json {
+        self.stack.pop().unwrap()
+    }
+}
+
+macro_rules! expect {
+    ($e:expr, Null) => ({
+        match $e {
+            Json::Null => Ok(()),
+            other => Err(ExpectedError("Null".to_string(),
+                                       format!("{}", other)))
+        }
+    });
+    ($e:expr, $t:ident) => ({
+        match $e {
+            Json::$t(v) => Ok(v),
+            other => {
+                Err(ExpectedError(stringify!($t).to_string(),
+                                  format!("{}", other)))
+            }
+        }
+    })
+}
+
+macro_rules! read_primitive {
+    ($name:ident, $ty:ty) => {
+        fn $name(&mut self) -> DecodeResult<$ty> {
+            match self.pop() {
+                Json::I64(f) => match num::cast(f) {
+                    Some(f) => Ok(f),
+                    None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
+                },
+                Json::U64(f) => match num::cast(f) {
+                    Some(f) => Ok(f),
+                    None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
+                },
+                Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
+                // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
+                // is going to have a string here, as per JSON spec.
+                Json::String(s) => match s.parse() {
+                    Some(f) => Ok(f),
+                    None => Err(ExpectedError("Number".to_string(), s)),
+                },
+                value => Err(ExpectedError("Number".to_string(), format!("{}", value))),
+            }
+        }
+    }
+}
+
+impl ::Decoder<DecoderError> for Decoder {
+    fn read_nil(&mut self) -> DecodeResult<()> {
+        expect!(self.pop(), Null)
+    }
+
+    read_primitive! { read_uint, uint }
+    read_primitive! { read_u8, u8 }
+    read_primitive! { read_u16, u16 }
+    read_primitive! { read_u32, u32 }
+    read_primitive! { read_u64, u64 }
+    read_primitive! { read_int, int }
+    read_primitive! { read_i8, i8 }
+    read_primitive! { read_i16, i16 }
+    read_primitive! { read_i32, i32 }
+    read_primitive! { read_i64, i64 }
+
+    fn read_f32(&mut self) -> DecodeResult<f32> { self.read_f64().map(|x| x as f32) }
+
+    fn read_f64(&mut self) -> DecodeResult<f64> {
+        match self.pop() {
+            Json::I64(f) => Ok(f as f64),
+            Json::U64(f) => Ok(f as f64),
+            Json::F64(f) => Ok(f),
+            Json::String(s) => {
+                // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
+                // is going to have a string here, as per JSON spec.
+                match s.parse() {
+                    Some(f) => Ok(f),
+                    None => Err(ExpectedError("Number".to_string(), s)),
+                }
+            },
+            Json::Null => Ok(f64::NAN),
+            value => Err(ExpectedError("Number".to_string(), format!("{}", value)))
+        }
+    }
+
+    fn read_bool(&mut self) -> DecodeResult<bool> {
+        expect!(self.pop(), Boolean)
+    }
+
+    fn read_char(&mut self) -> DecodeResult<char> {
+        let s = try!(self.read_str());
+        {
+            let mut it = s.chars();
+            match (it.next(), it.next()) {
+                // exactly one character
+                (Some(c), None) => return Ok(c),
+                _ => ()
+            }
+        }
+        Err(ExpectedError("single character string".to_string(), format!("{}", s)))
+    }
+
+    fn read_str(&mut self) -> DecodeResult<string::String> {
+        expect!(self.pop(), String)
+    }
+
+    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        f(self)
+    }
+
+    fn read_enum_variant<T, F>(&mut self, names: &[&str],
+                               mut f: F) -> DecodeResult<T>
+        where F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
+    {
+        let name = match self.pop() {
+            Json::String(s) => s,
+            Json::Object(mut o) => {
+                let n = match o.remove(&"variant".to_string()) {
+                    Some(Json::String(s)) => s,
+                    Some(val) => {
+                        return Err(ExpectedError("String".to_string(), format!("{}", val)))
+                    }
+                    None => {
+                        return Err(MissingFieldError("variant".to_string()))
+                    }
+                };
+                match o.remove(&"fields".to_string()) {
+                    Some(Json::Array(l)) => {
+                        for field in l.into_iter().rev() {
+                            self.stack.push(field);
+                        }
+                    },
+                    Some(val) => {
+                        return Err(ExpectedError("Array".to_string(), format!("{}", val)))
+                    }
+                    None => {
+                        return Err(MissingFieldError("fields".to_string()))
+                    }
+                }
+                n
+            }
+            json => {
+                return Err(ExpectedError("String or Object".to_string(), format!("{}", json)))
+            }
+        };
+        let idx = match names.iter().position(|n| *n == name[]) {
+            Some(idx) => idx,
+            None => return Err(UnknownVariantError(name))
+        };
+        f(self, idx)
+    }
+
+    fn read_enum_variant_arg<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        f(self)
+    }
+
+    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T> where
+        F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
+    {
+        self.read_enum_variant(names, f)
+    }
+
+
+    fn read_enum_struct_variant_field<T, F>(&mut self,
+                                         _name: &str,
+                                         idx: uint,
+                                         f: F)
+                                         -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        self.read_enum_variant_arg(idx, f)
+    }
+
+    fn read_struct<T, F>(&mut self, _name: &str, _len: uint, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        let value = try!(f(self));
+        self.pop();
+        Ok(value)
+    }
+
+    fn read_struct_field<T, F>(&mut self,
+                               name: &str,
+                               _idx: uint,
+                               f: F)
+                               -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        let mut obj = try!(expect!(self.pop(), Object));
+
+        let value = match obj.remove(&name.to_string()) {
+            None => {
+                // Add a Null and try to parse it as an Option<_>
+                // to get None as a default value.
+                self.stack.push(Json::Null);
+                match f(self) {
+                    Ok(x) => x,
+                    Err(_) => return Err(MissingFieldError(name.to_string())),
+                }
+            },
+            Some(json) => {
+                self.stack.push(json);
+                try!(f(self))
+            }
+        };
+        self.stack.push(Json::Object(obj));
+        Ok(value)
+    }
+
+    fn read_tuple<T, F>(&mut self, tuple_len: uint, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        self.read_seq(move |d, len| {
+            if len == tuple_len {
+                f(d)
+            } else {
+                Err(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len)))
+            }
+        })
+    }
+
+    fn read_tuple_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        self.read_seq_elt(idx, f)
+    }
+
+    fn read_tuple_struct<T, F>(&mut self,
+                               _name: &str,
+                               len: uint,
+                               f: F)
+                               -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        self.read_tuple(len, f)
+    }
+
+    fn read_tuple_struct_arg<T, F>(&mut self,
+                                   idx: uint,
+                                   f: F)
+                                   -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        self.read_tuple_arg(idx, f)
+    }
+
+    fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
+        F: FnMut(&mut Decoder, bool) -> DecodeResult<T>,
+    {
+        match self.pop() {
+            Json::Null => f(self, false),
+            value => { self.stack.push(value); f(self, true) }
+        }
+    }
+
+    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
+    {
+        let array = try!(expect!(self.pop(), Array));
+        let len = array.len();
+        for v in array.into_iter().rev() {
+            self.stack.push(v);
+        }
+        f(self, len)
+    }
+
+    fn read_seq_elt<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        f(self)
+    }
+
+    fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
+        F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
+    {
+        let obj = try!(expect!(self.pop(), Object));
+        let len = obj.len();
+        for (key, value) in obj.into_iter() {
+            self.stack.push(value);
+            self.stack.push(Json::String(key));
+        }
+        f(self, len)
+    }
+
+    fn read_map_elt_key<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
+       F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        f(self)
+    }
+
+    fn read_map_elt_val<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
+       F: FnOnce(&mut Decoder) -> DecodeResult<T>,
+    {
+        f(self)
+    }
+
+    fn error(&mut self, err: &str) -> DecoderError {
+        ApplicationError(err.to_string())
+    }
+}
+
+/// A trait for converting values to JSON
+pub trait ToJson for Sized? {
+    /// Converts the value of `self` to an instance of JSON
+    fn to_json(&self) -> Json;
+}
+
+macro_rules! to_json_impl_i64 {
+    ($($t:ty), +) => (
+        $(impl ToJson for $t {
+            fn to_json(&self) -> Json { Json::I64(*self as i64) }
+        })+
+    )
+}
+
+to_json_impl_i64! { int, i8, i16, i32, i64 }
+
+macro_rules! to_json_impl_u64 {
+    ($($t:ty), +) => (
+        $(impl ToJson for $t {
+            fn to_json(&self) -> Json { Json::U64(*self as u64) }
+        })+
+    )
+}
+
+to_json_impl_u64! { uint, u8, u16, u32, u64 }
+
+impl ToJson for Json {
+    fn to_json(&self) -> Json { self.clone() }
+}
+
+impl ToJson for f32 {
+    fn to_json(&self) -> Json { (*self as f64).to_json() }
+}
+
+impl ToJson for f64 {
+    fn to_json(&self) -> Json {
+        match self.classify() {
+            Fp::Nan | Fp::Infinite => Json::Null,
+            _                  => Json::F64(*self)
+        }
+    }
+}
+
+impl ToJson for () {
+    fn to_json(&self) -> Json { Json::Null }
+}
+
+impl ToJson for bool {
+    fn to_json(&self) -> Json { Json::Boolean(*self) }
+}
+
+impl ToJson for str {
+    fn to_json(&self) -> Json { Json::String(self.to_string()) }
+}
+
+impl ToJson for string::String {
+    fn to_json(&self) -> Json { Json::String((*self).clone()) }
+}
+
+macro_rules! tuple_impl {
+    // use variables to indicate the arity of the tuple
+    ($($tyvar:ident),* ) => {
+        // the trailing commas are for the 1 tuple
+        impl<
+            $( $tyvar : ToJson ),*
+            > ToJson for ( $( $tyvar ),* , ) {
+
+            #[inline]
+            #[allow(non_snake_case)]
+            fn to_json(&self) -> Json {
+                match *self {
+                    ($(ref $tyvar),*,) => Json::Array(vec![$($tyvar.to_json()),*])
+                }
+            }
+        }
+    }
+}
+
+tuple_impl!{A}
+tuple_impl!{A, B}
+tuple_impl!{A, B, C}
+tuple_impl!{A, B, C, D}
+tuple_impl!{A, B, C, D, E}
+tuple_impl!{A, B, C, D, E, F}
+tuple_impl!{A, B, C, D, E, F, G}
+tuple_impl!{A, B, C, D, E, F, G, H}
+tuple_impl!{A, B, C, D, E, F, G, H, I}
+tuple_impl!{A, B, C, D, E, F, G, H, I, J}
+tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
+tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
+
+impl<A: ToJson> ToJson for [A] {
+    fn to_json(&self) -> Json { Json::Array(self.iter().map(|elt| elt.to_json()).collect()) }
+}
+
+impl<A: ToJson> ToJson for Vec<A> {
+    fn to_json(&self) -> Json { Json::Array(self.iter().map(|elt| elt.to_json()).collect()) }
+}
+
+impl<A: ToJson> ToJson for BTreeMap<string::String, A> {
+    fn to_json(&self) -> Json {
+        let mut d = BTreeMap::new();
+        for (key, value) in self.iter() {
+            d.insert((*key).clone(), value.to_json());
+        }
+        Json::Object(d)
+    }
+}
+
+impl<A: ToJson> ToJson for HashMap<string::String, A> {
+    fn to_json(&self) -> Json {
+        let mut d = BTreeMap::new();
+        for (key, value) in self.iter() {
+            d.insert((*key).clone(), value.to_json());
+        }
+        Json::Object(d)
+    }
+}
+
+impl<A:ToJson> ToJson for Option<A> {
+    fn to_json(&self) -> Json {
+        match *self {
+            None => Json::Null,
+            Some(ref value) => value.to_json()
+        }
+    }
+}
+
+struct FormatShim<'a, 'b: 'a> {
+    inner: &'a mut fmt::Formatter<'b>,
+}
+
+impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.inner.write_str(s)
+    }
+}
+
+impl fmt::Show for Json {
+    /// Encodes a json value into a string
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut shim = FormatShim { inner: f };
+        let mut encoder = Encoder::new(&mut shim);
+        self.encode(&mut encoder)
+    }
+}
+
+impl<'a> fmt::Show for PrettyJson<'a> {
+    /// Encodes a json value into a string
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut shim = FormatShim { inner: f };
+        let mut encoder = PrettyEncoder::new(&mut shim);
+        self.inner.encode(&mut encoder)
+    }
+}
+
+impl<'a, T> fmt::Show for AsJson<'a, T>
+    where T: for<'b> Encodable<Encoder<'b>, fmt::Error>
+{
+    /// Encodes a json value into a string
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut shim = FormatShim { inner: f };
+        let mut encoder = Encoder::new(&mut shim);
+        self.inner.encode(&mut encoder)
+    }
+}
+
+impl<'a, T> AsPrettyJson<'a, T> {
+    /// Set the indentation level for the emitted JSON
+    pub fn indent(mut self, indent: uint) -> AsPrettyJson<'a, T> {
+        self.indent = Some(indent);
+        self
+    }
+}
+
+impl<'a, T> fmt::Show for AsPrettyJson<'a, T>
+    where T: for<'b> Encodable<PrettyEncoder<'b>, fmt::Error>
+{
+    /// Encodes a json value into a string
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut shim = FormatShim { inner: f };
+        let mut encoder = PrettyEncoder::new(&mut shim);
+        match self.indent {
+            Some(n) => encoder.set_indent(n),
+            None => {}
+        }
+        self.inner.encode(&mut encoder)
+    }
+}
+
+impl FromStr for Json {
+    fn from_str(s: &str) -> Option<Json> {
+        from_str(s).ok()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate test;
+    use self::Animal::*;
+    use self::DecodeEnum::*;
+    use self::test::Bencher;
+    use {Encodable, Decodable};
+    use super::Json::*;
+    use super::ErrorCode::*;
+    use super::ParserError::*;
+    use super::DecoderError::*;
+    use super::JsonEvent::*;
+    use super::StackElement::*;
+    use super::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser,
+                StackElement, Stack, Decoder};
+    use std::{i64, u64, f32, f64};
+    use std::collections::BTreeMap;
+    use std::num::Float;
+    use std::string;
+
+    #[derive(RustcDecodable, Eq, PartialEq, Show)]
+    struct OptionData {
+        opt: Option<uint>,
+    }
+
+    #[test]
+    fn test_decode_option_none() {
+        let s ="{}";
+        let obj: OptionData = super::decode(s).unwrap();
+        assert_eq!(obj, OptionData { opt: None });
+    }
+
+    #[test]
+    fn test_decode_option_some() {
+        let s = "{ \"opt\": 10 }";
+        let obj: OptionData = super::decode(s).unwrap();
+        assert_eq!(obj, OptionData { opt: Some(10u) });
+    }
+
+    #[test]
+    fn test_decode_option_malformed() {
+        check_err::<OptionData>("{ \"opt\": [] }",
+                                ExpectedError("Number".to_string(), "[]".to_string()));
+        check_err::<OptionData>("{ \"opt\": false }",
+                                ExpectedError("Number".to_string(), "false".to_string()));
+    }
+
+    #[derive(PartialEq, RustcEncodable, RustcDecodable, Show)]
+    enum Animal {
+        Dog,
+        Frog(string::String, int)
+    }
+
+    #[derive(PartialEq, RustcEncodable, RustcDecodable, Show)]
+    struct Inner {
+        a: (),
+        b: uint,
+        c: Vec<string::String>,
+    }
+
+    #[derive(PartialEq, RustcEncodable, RustcDecodable, Show)]
+    struct Outer {
+        inner: Vec<Inner>,
+    }
+
+    fn mk_object(items: &[(string::String, Json)]) -> Json {
+        let mut d = BTreeMap::new();
+
+        for item in items.iter() {
+            match *item {
+                (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); },
+            }
+        };
+
+        Object(d)
+    }
+
+    #[test]
+    fn test_from_str_trait() {
+        let s = "null";
+        assert!(s.parse::<Json>().unwrap() == s.parse().unwrap());
+    }
+
+    #[test]
+    fn test_write_null() {
+        assert_eq!(Null.to_string(), "null");
+        assert_eq!(Null.pretty().to_string(), "null");
+    }
+
+    #[test]
+    fn test_write_i64() {
+        assert_eq!(U64(0).to_string(), "0");
+        assert_eq!(U64(0).pretty().to_string(), "0");
+
+        assert_eq!(U64(1234).to_string(), "1234");
+        assert_eq!(U64(1234).pretty().to_string(), "1234");
+
+        assert_eq!(I64(-5678).to_string(), "-5678");
+        assert_eq!(I64(-5678).pretty().to_string(), "-5678");
+
+        assert_eq!(U64(7650007200025252000).to_string(), "7650007200025252000");
+        assert_eq!(U64(7650007200025252000).pretty().to_string(), "7650007200025252000");
+    }
+
+    #[test]
+    fn test_write_f64() {
+        assert_eq!(F64(3.0).to_string(), "3.0");
+        assert_eq!(F64(3.0).pretty().to_string(), "3.0");
+
+        assert_eq!(F64(3.1).to_string(), "3.1");
+        assert_eq!(F64(3.1).pretty().to_string(), "3.1");
+
+        assert_eq!(F64(-1.5).to_string(), "-1.5");
+        assert_eq!(F64(-1.5).pretty().to_string(), "-1.5");
+
+        assert_eq!(F64(0.5).to_string(), "0.5");
+        assert_eq!(F64(0.5).pretty().to_string(), "0.5");
+
+        assert_eq!(F64(f64::NAN).to_string(), "null");
+        assert_eq!(F64(f64::NAN).pretty().to_string(), "null");
+
+        assert_eq!(F64(f64::INFINITY).to_string(), "null");
+        assert_eq!(F64(f64::INFINITY).pretty().to_string(), "null");
+
+        assert_eq!(F64(f64::NEG_INFINITY).to_string(), "null");
+        assert_eq!(F64(f64::NEG_INFINITY).pretty().to_string(), "null");
+    }
+
+    #[test]
+    fn test_write_str() {
+        assert_eq!(String("".to_string()).to_string(), "\"\"");
+        assert_eq!(String("".to_string()).pretty().to_string(), "\"\"");
+
+        assert_eq!(String("homura".to_string()).to_string(), "\"homura\"");
+        assert_eq!(String("madoka".to_string()).pretty().to_string(), "\"madoka\"");
+    }
+
+    #[test]
+    fn test_write_bool() {
+        assert_eq!(Boolean(true).to_string(), "true");
+        assert_eq!(Boolean(true).pretty().to_string(), "true");
+
+        assert_eq!(Boolean(false).to_string(), "false");
+        assert_eq!(Boolean(false).pretty().to_string(), "false");
+    }
+
+    #[test]
+    fn test_write_array() {
+        assert_eq!(Array(vec![]).to_string(), "[]");
+        assert_eq!(Array(vec![]).pretty().to_string(), "[]");
+
+        assert_eq!(Array(vec![Boolean(true)]).to_string(), "[true]");
+        assert_eq!(
+            Array(vec![Boolean(true)]).pretty().to_string(),
+            "\
+            [\n  \
+                true\n\
+            ]"
+        );
+
+        let long_test_array = Array(vec![
+            Boolean(false),
+            Null,
+            Array(vec![String("foo\nbar".to_string()), F64(3.5)])]);
+
+        assert_eq!(long_test_array.to_string(),
+            "[false,null,[\"foo\\nbar\",3.5]]");
+        assert_eq!(
+            long_test_array.pretty().to_string(),
+            "\
+            [\n  \
+                false,\n  \
+                null,\n  \
+                [\n    \
+                    \"foo\\nbar\",\n    \
+                    3.5\n  \
+                ]\n\
+            ]"
+        );
+    }
+
+    #[test]
+    fn test_write_object() {
+        assert_eq!(mk_object(&[]).to_string(), "{}");
+        assert_eq!(mk_object(&[]).pretty().to_string(), "{}");
+
+        assert_eq!(
+            mk_object(&[
+                ("a".to_string(), Boolean(true))
+            ]).to_string(),
+            "{\"a\":true}"
+        );
+        assert_eq!(
+            mk_object(&[("a".to_string(), Boolean(true))]).pretty().to_string(),
+            "\
+            {\n  \
+                \"a\": true\n\
+            }"
+        );
+
+        let complex_obj = mk_object(&[
+                ("b".to_string(), Array(vec![
+                    mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]),
+                    mk_object(&[("d".to_string(), String("".to_string()))])
+                ]))
+            ]);
+
+        assert_eq!(
+            complex_obj.to_string(),
+            "{\
+                \"b\":[\
+                    {\"c\":\"\\f\\r\"},\
+                    {\"d\":\"\"}\
+                ]\
+            }"
+        );
+        assert_eq!(
+            complex_obj.pretty().to_string(),
+            "\
+            {\n  \
+                \"b\": [\n    \
+                    {\n      \
+                        \"c\": \"\\f\\r\"\n    \
+                    },\n    \
+                    {\n      \
+                        \"d\": \"\"\n    \
+                    }\n  \
+                ]\n\
+            }"
+        );
+
+        let a = mk_object(&[
+            ("a".to_string(), Boolean(true)),
+            ("b".to_string(), Array(vec![
+                mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]),
+                mk_object(&[("d".to_string(), String("".to_string()))])
+            ]))
+        ]);
+
+        // We can't compare the strings directly because the object fields be
+        // printed in a different order.
+        assert_eq!(a.clone(), a.to_string().parse().unwrap());
+        assert_eq!(a.clone(), a.pretty().to_string().parse().unwrap());
+    }
+
+    #[test]
+    fn test_write_enum() {
+        let animal = Dog;
+        assert_eq!(
+            format!("{}", super::as_json(&animal)),
+            "\"Dog\""
+        );
+        assert_eq!(
+            format!("{}", super::as_pretty_json(&animal)),
+            "\"Dog\""
+        );
+
+        let animal = Frog("Henry".to_string(), 349);
+        assert_eq!(
+            format!("{}", super::as_json(&animal)),
+            "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"
+        );
+        assert_eq!(
+            format!("{}", super::as_pretty_json(&animal)),
+            "{\n  \
+               \"variant\": \"Frog\",\n  \
+               \"fields\": [\n    \
+                 \"Henry\",\n    \
+                 349\n  \
+               ]\n\
+             }"
+        );
+    }
+
+    macro_rules! check_encoder_for_simple {
+        ($value:expr, $expected:expr) => ({
+            let s = format!("{}", super::as_json(&$value));
+            assert_eq!(s, $expected);
+
+            let s = format!("{}", super::as_pretty_json(&$value));
+            assert_eq!(s, $expected);
+        })
+    }
+
+    #[test]
+    fn test_write_some() {
+        check_encoder_for_simple!(Some("jodhpurs".to_string()), "\"jodhpurs\"");
+    }
+
+    #[test]
+    fn test_write_none() {
+        check_encoder_for_simple!(None::<string::String>, "null");
+    }
+
+    #[test]
+    fn test_write_char() {
+        check_encoder_for_simple!('a', "\"a\"");
+        check_encoder_for_simple!('\t', "\"\\t\"");
+        check_encoder_for_simple!('\u{0000}', "\"\\u0000\"");
+        check_encoder_for_simple!('\u{001b}', "\"\\u001b\"");
+        check_encoder_for_simple!('\u{007f}', "\"\\u007f\"");
+        check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\"");
+        check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\"");
+        check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\"");
+    }
+
+    #[test]
+    fn test_trailing_characters() {
+        assert_eq!(from_str("nulla"),  Err(SyntaxError(TrailingCharacters, 1, 5)));
+        assert_eq!(from_str("truea"),  Err(SyntaxError(TrailingCharacters, 1, 5)));
+        assert_eq!(from_str("falsea"), Err(SyntaxError(TrailingCharacters, 1, 6)));
+        assert_eq!(from_str("1a"),     Err(SyntaxError(TrailingCharacters, 1, 2)));
+        assert_eq!(from_str("[]a"),    Err(SyntaxError(TrailingCharacters, 1, 3)));
+        assert_eq!(from_str("{}a"),    Err(SyntaxError(TrailingCharacters, 1, 3)));
+    }
+
+    #[test]
+    fn test_read_identifiers() {
+        assert_eq!(from_str("n"),    Err(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(from_str("nul"),  Err(SyntaxError(InvalidSyntax, 1, 4)));
+        assert_eq!(from_str("t"),    Err(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(from_str("truz"), Err(SyntaxError(InvalidSyntax, 1, 4)));
+        assert_eq!(from_str("f"),    Err(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(from_str("faz"),  Err(SyntaxError(InvalidSyntax, 1, 3)));
+
+        assert_eq!(from_str("null"), Ok(Null));
+        assert_eq!(from_str("true"), Ok(Boolean(true)));
+        assert_eq!(from_str("false"), Ok(Boolean(false)));
+        assert_eq!(from_str(" null "), Ok(Null));
+        assert_eq!(from_str(" true "), Ok(Boolean(true)));
+        assert_eq!(from_str(" false "), Ok(Boolean(false)));
+    }
+
+    #[test]
+    fn test_decode_identifiers() {
+        let v: () = super::decode("null").unwrap();
+        assert_eq!(v, ());
+
+        let v: bool = super::decode("true").unwrap();
+        assert_eq!(v, true);
+
+        let v: bool = super::decode("false").unwrap();
+        assert_eq!(v, false);
+    }
+
+    #[test]
+    fn test_read_number() {
+        assert_eq!(from_str("+"),   Err(SyntaxError(InvalidSyntax, 1, 1)));
+        assert_eq!(from_str("."),   Err(SyntaxError(InvalidSyntax, 1, 1)));
+        assert_eq!(from_str("NaN"), Err(SyntaxError(InvalidSyntax, 1, 1)));
+        assert_eq!(from_str("-"),   Err(SyntaxError(InvalidNumber, 1, 2)));
+        assert_eq!(from_str("00"),  Err(SyntaxError(InvalidNumber, 1, 2)));
+        assert_eq!(from_str("1."),  Err(SyntaxError(InvalidNumber, 1, 3)));
+        assert_eq!(from_str("1e"),  Err(SyntaxError(InvalidNumber, 1, 3)));
+        assert_eq!(from_str("1e+"), Err(SyntaxError(InvalidNumber, 1, 4)));
+
+        assert_eq!(from_str("18446744073709551616"), Err(SyntaxError(InvalidNumber, 1, 20)));
+        assert_eq!(from_str("-9223372036854775809"), Err(SyntaxError(InvalidNumber, 1, 21)));
+
+        assert_eq!(from_str("3"), Ok(U64(3)));
+        assert_eq!(from_str("3.1"), Ok(F64(3.1)));
+        assert_eq!(from_str("-1.2"), Ok(F64(-1.2)));
+        assert_eq!(from_str("0.4"), Ok(F64(0.4)));
+        assert_eq!(from_str("0.4e5"), Ok(F64(0.4e5)));
+        assert_eq!(from_str("0.4e+15"), Ok(F64(0.4e15)));
+        assert_eq!(from_str("0.4e-01"), Ok(F64(0.4e-01)));
+        assert_eq!(from_str(" 3 "), Ok(U64(3)));
+
+        assert_eq!(from_str("-9223372036854775808"), Ok(I64(i64::MIN)));
+        assert_eq!(from_str("9223372036854775807"), Ok(U64(i64::MAX as u64)));
+        assert_eq!(from_str("18446744073709551615"), Ok(U64(u64::MAX)));
+    }
+
+    #[test]
+    fn test_decode_numbers() {
+        let v: f64 = super::decode("3").unwrap();
+        assert_eq!(v, 3.0);
+
+        let v: f64 = super::decode("3.1").unwrap();
+        assert_eq!(v, 3.1);
+
+        let v: f64 = super::decode("-1.2").unwrap();
+        assert_eq!(v, -1.2);
+
+        let v: f64 = super::decode("0.4").unwrap();
+        assert_eq!(v, 0.4);
+
+        let v: f64 = super::decode("0.4e5").unwrap();
+        assert_eq!(v, 0.4e5);
+
+        let v: f64 = super::decode("0.4e15").unwrap();
+        assert_eq!(v, 0.4e15);
+
+        let v: f64 = super::decode("0.4e-01").unwrap();
+        assert_eq!(v, 0.4e-01);
+
+        let v: u64 = super::decode("0").unwrap();
+        assert_eq!(v, 0);
+
+        let v: u64 = super::decode("18446744073709551615").unwrap();
+        assert_eq!(v, u64::MAX);
+
+        let v: i64 = super::decode("-9223372036854775808").unwrap();
+        assert_eq!(v, i64::MIN);
+
+        let v: i64 = super::decode("9223372036854775807").unwrap();
+        assert_eq!(v, i64::MAX);
+
+        let res: DecodeResult<i64> = super::decode("765.25252");
+        assert_eq!(res, Err(ExpectedError("Integer".to_string(), "765.25252".to_string())));
+    }
+
+    #[test]
+    fn test_read_str() {
+        assert_eq!(from_str("\""),    Err(SyntaxError(EOFWhileParsingString, 1, 2)));
+        assert_eq!(from_str("\"lol"), Err(SyntaxError(EOFWhileParsingString, 1, 5)));
+
+        assert_eq!(from_str("\"\""), Ok(String("".to_string())));
+        assert_eq!(from_str("\"foo\""), Ok(String("foo".to_string())));
+        assert_eq!(from_str("\"\\\"\""), Ok(String("\"".to_string())));
+        assert_eq!(from_str("\"\\b\""), Ok(String("\x08".to_string())));
+        assert_eq!(from_str("\"\\n\""), Ok(String("\n".to_string())));
+        assert_eq!(from_str("\"\\r\""), Ok(String("\r".to_string())));
+        assert_eq!(from_str("\"\\t\""), Ok(String("\t".to_string())));
+        assert_eq!(from_str(" \"foo\" "), Ok(String("foo".to_string())));
+        assert_eq!(from_str("\"\\u12ab\""), Ok(String("\u{12ab}".to_string())));
+        assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string())));
+    }
+
+    #[test]
+    fn test_decode_str() {
+        let s = [("\"\"", ""),
+                 ("\"foo\"", "foo"),
+                 ("\"\\\"\"", "\""),
+                 ("\"\\b\"", "\x08"),
+                 ("\"\\n\"", "\n"),
+                 ("\"\\r\"", "\r"),
+                 ("\"\\t\"", "\t"),
+                 ("\"\\u12ab\"", "\u{12ab}"),
+                 ("\"\\uAB12\"", "\u{AB12}")];
+
+        for &(i, o) in s.iter() {
+            let v: string::String = super::decode(i).unwrap();
+            assert_eq!(v, o);
+        }
+    }
+
+    #[test]
+    fn test_read_array() {
+        assert_eq!(from_str("["),     Err(SyntaxError(EOFWhileParsingValue, 1, 2)));
+        assert_eq!(from_str("[1"),    Err(SyntaxError(EOFWhileParsingArray, 1, 3)));
+        assert_eq!(from_str("[1,"),   Err(SyntaxError(EOFWhileParsingValue, 1, 4)));
+        assert_eq!(from_str("[1,]"),  Err(SyntaxError(InvalidSyntax,        1, 4)));
+        assert_eq!(from_str("[6 7]"), Err(SyntaxError(InvalidSyntax,        1, 4)));
+
+        assert_eq!(from_str("[]"), Ok(Array(vec![])));
+        assert_eq!(from_str("[ ]"), Ok(Array(vec![])));
+        assert_eq!(from_str("[true]"), Ok(Array(vec![Boolean(true)])));
+        assert_eq!(from_str("[ false ]"), Ok(Array(vec![Boolean(false)])));
+        assert_eq!(from_str("[null]"), Ok(Array(vec![Null])));
+        assert_eq!(from_str("[3, 1]"),
+                     Ok(Array(vec![U64(3), U64(1)])));
+        assert_eq!(from_str("\n[3, 2]\n"),
+                     Ok(Array(vec![U64(3), U64(2)])));
+        assert_eq!(from_str("[2, [4, 1]]"),
+               Ok(Array(vec![U64(2), Array(vec![U64(4), U64(1)])])));
+    }
+
+    #[test]
+    fn test_decode_array() {
+        let v: Vec<()> = super::decode("[]").unwrap();
+        assert_eq!(v, vec![]);
+
+        let v: Vec<()> = super::decode("[null]").unwrap();
+        assert_eq!(v, vec![()]);
+
+        let v: Vec<bool> = super::decode("[true]").unwrap();
+        assert_eq!(v, vec![true]);
+
+        let v: Vec<int> = super::decode("[3, 1]").unwrap();
+        assert_eq!(v, vec![3, 1]);
+
+        let v: Vec<Vec<uint>> = super::decode("[[3], [1, 2]]").unwrap();
+        assert_eq!(v, vec![vec![3], vec![1, 2]]);
+    }
+
+    #[test]
+    fn test_decode_tuple() {
+        let t: (uint, uint, uint) = super::decode("[1, 2, 3]").unwrap();
+        assert_eq!(t, (1u, 2, 3));
+
+        let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap();
+        assert_eq!(t, (1u, "two".to_string()));
+    }
+
+    #[test]
+    fn test_decode_tuple_malformed_types() {
+        assert!(super::decode::<(uint, string::String)>("[1, 2]").is_err());
+    }
+
+    #[test]
+    fn test_decode_tuple_malformed_length() {
+        assert!(super::decode::<(uint, uint)>("[1, 2, 3]").is_err());
+    }
+
+    #[test]
+    fn test_read_object() {
+        assert_eq!(from_str("{"),       Err(SyntaxError(EOFWhileParsingObject, 1, 2)));
+        assert_eq!(from_str("{ "),      Err(SyntaxError(EOFWhileParsingObject, 1, 3)));
+        assert_eq!(from_str("{1"),      Err(SyntaxError(KeyMustBeAString,      1, 2)));
+        assert_eq!(from_str("{ \"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 6)));
+        assert_eq!(from_str("{\"a\""),  Err(SyntaxError(EOFWhileParsingObject, 1, 5)));
+        assert_eq!(from_str("{\"a\" "), Err(SyntaxError(EOFWhileParsingObject, 1, 6)));
+
+        assert_eq!(from_str("{\"a\" 1"),   Err(SyntaxError(ExpectedColon,         1, 6)));
+        assert_eq!(from_str("{\"a\":"),    Err(SyntaxError(EOFWhileParsingValue,  1, 6)));
+        assert_eq!(from_str("{\"a\":1"),   Err(SyntaxError(EOFWhileParsingObject, 1, 7)));
+        assert_eq!(from_str("{\"a\":1 1"), Err(SyntaxError(InvalidSyntax,         1, 8)));
+        assert_eq!(from_str("{\"a\":1,"),  Err(SyntaxError(EOFWhileParsingObject, 1, 8)));
+
+        assert_eq!(from_str("{}").unwrap(), mk_object(&[]));
+        assert_eq!(from_str("{\"a\": 3}").unwrap(),
+                  mk_object(&[("a".to_string(), U64(3))]));
+
+        assert_eq!(from_str(
+                      "{ \"a\": null, \"b\" : true }").unwrap(),
+                  mk_object(&[
+                      ("a".to_string(), Null),
+                      ("b".to_string(), Boolean(true))]));
+        assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(),
+                  mk_object(&[
+                      ("a".to_string(), Null),
+                      ("b".to_string(), Boolean(true))]));
+        assert_eq!(from_str(
+                      "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(),
+                  mk_object(&[
+                      ("a".to_string(), F64(1.0)),
+                      ("b".to_string(), Array(vec![Boolean(true)]))
+                  ]));
+        assert_eq!(from_str(
+                      "{\
+                          \"a\": 1.0, \
+                          \"b\": [\
+                              true,\
+                              \"foo\\nbar\", \
+                              { \"c\": {\"d\": null} } \
+                          ]\
+                      }").unwrap(),
+                  mk_object(&[
+                      ("a".to_string(), F64(1.0)),
+                      ("b".to_string(), Array(vec![
+                          Boolean(true),
+                          String("foo\nbar".to_string()),
+                          mk_object(&[
+                              ("c".to_string(), mk_object(&[("d".to_string(), Null)]))
+                          ])
+                      ]))
+                  ]));
+    }
+
+    #[test]
+    fn test_decode_struct() {
+        let s = "{
+            \"inner\": [
+                { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
+            ]
+        }";
+
+        let v: Outer = super::decode(s).unwrap();
+        assert_eq!(
+            v,
+            Outer {
+                inner: vec![
+                    Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
+                ]
+            }
+        );
+    }
+
+    #[derive(RustcDecodable)]
+    struct FloatStruct {
+        f: f64,
+        a: Vec<f64>
+    }
+    #[test]
+    fn test_decode_struct_with_nan() {
+        let s = "{\"f\":null,\"a\":[null,123]}";
+        let obj: FloatStruct = super::decode(s).unwrap();
+        assert!(obj.f.is_nan());
+        assert!(obj.a[0].is_nan());
+        assert_eq!(obj.a[1], 123f64);
+    }
+
+    #[test]
+    fn test_decode_option() {
+        let value: Option<string::String> = super::decode("null").unwrap();
+        assert_eq!(value, None);
+
+        let value: Option<string::String> = super::decode("\"jodhpurs\"").unwrap();
+        assert_eq!(value, Some("jodhpurs".to_string()));
+    }
+
+    #[test]
+    fn test_decode_enum() {
+        let value: Animal = super::decode("\"Dog\"").unwrap();
+        assert_eq!(value, Dog);
+
+        let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}";
+        let value: Animal = super::decode(s).unwrap();
+        assert_eq!(value, Frog("Henry".to_string(), 349));
+    }
+
+    #[test]
+    fn test_decode_map() {
+        let s = "{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\
+                  \"fields\":[\"Henry\", 349]}}";
+        let mut map: BTreeMap<string::String, Animal> = super::decode(s).unwrap();
+
+        assert_eq!(map.remove(&"a".to_string()), Some(Dog));
+        assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349)));
+    }
+
+    #[test]
+    fn test_multiline_errors() {
+        assert_eq!(from_str("{\n  \"foo\":\n \"bar\""),
+            Err(SyntaxError(EOFWhileParsingObject, 3u, 8u)));
+    }
+
+    #[derive(RustcDecodable)]
+    #[allow(dead_code)]
+    struct DecodeStruct {
+        x: f64,
+        y: bool,
+        z: string::String,
+        w: Vec<DecodeStruct>
+    }
+    #[derive(RustcDecodable)]
+    enum DecodeEnum {
+        A(f64),
+        B(string::String)
+    }
+    fn check_err<T: Decodable<Decoder, DecoderError>>(to_parse: &'static str,
+                                                      expected: DecoderError) {
+        let res: DecodeResult<T> = match from_str(to_parse) {
+            Err(e) => Err(ParseError(e)),
+            Ok(json) => Decodable::decode(&mut Decoder::new(json))
+        };
+        match res {
+            Ok(_) => panic!("`{}` parsed & decoded ok, expecting error `{}`",
+                              to_parse, expected),
+            Err(ParseError(e)) => panic!("`{}` is not valid json: {}",
+                                           to_parse, e),
+            Err(e) => {
+                assert_eq!(e, expected);
+            }
+        }
+    }
+    #[test]
+    fn test_decode_errors_struct() {
+        check_err::<DecodeStruct>("[]", ExpectedError("Object".to_string(), "[]".to_string()));
+        check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
+                                  ExpectedError("Number".to_string(), "true".to_string()));
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}",
+                                  ExpectedError("Boolean".to_string(), "[]".to_string()));
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}",
+                                  ExpectedError("String".to_string(), "{}".to_string()));
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}",
+                                  ExpectedError("Array".to_string(), "null".to_string()));
+        check_err::<DecodeStruct>("{\"x\": 1, \"y\": true, \"z\": \"\"}",
+                                  MissingFieldError("w".to_string()));
+    }
+    #[test]
+    fn test_decode_errors_enum() {
+        check_err::<DecodeEnum>("{}",
+                                MissingFieldError("variant".to_string()));
+        check_err::<DecodeEnum>("{\"variant\": 1}",
+                                ExpectedError("String".to_string(), "1".to_string()));
+        check_err::<DecodeEnum>("{\"variant\": \"A\"}",
+                                MissingFieldError("fields".to_string()));
+        check_err::<DecodeEnum>("{\"variant\": \"A\", \"fields\": null}",
+                                ExpectedError("Array".to_string(), "null".to_string()));
+        check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
+                                UnknownVariantError("C".to_string()));
+    }
+
+    #[test]
+    fn test_find(){
+        let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
+        let found_str = json_value.find("dog");
+        assert!(found_str.unwrap().as_string().unwrap() == "cat");
+    }
+
+    #[test]
+    fn test_find_path(){
+        let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+        let found_str = json_value.find_path(&["dog", "cat", "mouse"]);
+        assert!(found_str.unwrap().as_string().unwrap() == "cheese");
+    }
+
+    #[test]
+    fn test_search(){
+        let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
+        let found_str = json_value.search("mouse").and_then(|j| j.as_string());
+        assert!(found_str.unwrap() == "cheese");
+    }
+
+    #[test]
+    fn test_index(){
+        let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap();
+        let ref array = json_value["animals"];
+        assert_eq!(array[0].as_string().unwrap(), "dog");
+        assert_eq!(array[1].as_string().unwrap(), "cat");
+        assert_eq!(array[2].as_string().unwrap(), "mouse");
+    }
+
+    #[test]
+    fn test_is_object(){
+        let json_value = from_str("{}").unwrap();
+        assert!(json_value.is_object());
+    }
+
+    #[test]
+    fn test_as_object(){
+        let json_value = from_str("{}").unwrap();
+        let json_object = json_value.as_object();
+        assert!(json_object.is_some());
+    }
+
+    #[test]
+    fn test_is_array(){
+        let json_value = from_str("[1, 2, 3]").unwrap();
+        assert!(json_value.is_array());
+    }
+
+    #[test]
+    fn test_as_array(){
+        let json_value = from_str("[1, 2, 3]").unwrap();
+        let json_array = json_value.as_array();
+        let expected_length = 3;
+        assert!(json_array.is_some() && json_array.unwrap().len() == expected_length);
+    }
+
+    #[test]
+    fn test_is_string(){
+        let json_value = from_str("\"dog\"").unwrap();
+        assert!(json_value.is_string());
+    }
+
+    #[test]
+    fn test_as_string(){
+        let json_value = from_str("\"dog\"").unwrap();
+        let json_str = json_value.as_string();
+        let expected_str = "dog";
+        assert_eq!(json_str, Some(expected_str));
+    }
+
+    #[test]
+    fn test_is_number(){
+        let json_value = from_str("12").unwrap();
+        assert!(json_value.is_number());
+    }
+
+    #[test]
+    fn test_is_i64(){
+        let json_value = from_str("-12").unwrap();
+        assert!(json_value.is_i64());
+
+        let json_value = from_str("12").unwrap();
+        assert!(!json_value.is_i64());
+
+        let json_value = from_str("12.0").unwrap();
+        assert!(!json_value.is_i64());
+    }
+
+    #[test]
+    fn test_is_u64(){
+        let json_value = from_str("12").unwrap();
+        assert!(json_value.is_u64());
+
+        let json_value = from_str("-12").unwrap();
+        assert!(!json_value.is_u64());
+
+        let json_value = from_str("12.0").unwrap();
+        assert!(!json_value.is_u64());
+    }
+
+    #[test]
+    fn test_is_f64(){
+        let json_value = from_str("12").unwrap();
+        assert!(!json_value.is_f64());
+
+        let json_value = from_str("-12").unwrap();
+        assert!(!json_value.is_f64());
+
+        let json_value = from_str("12.0").unwrap();
+        assert!(json_value.is_f64());
+
+        let json_value = from_str("-12.0").unwrap();
+        assert!(json_value.is_f64());
+    }
+
+    #[test]
+    fn test_as_i64(){
+        let json_value = from_str("-12").unwrap();
+        let json_num = json_value.as_i64();
+        assert_eq!(json_num, Some(-12));
+    }
+
+    #[test]
+    fn test_as_u64(){
+        let json_value = from_str("12").unwrap();
+        let json_num = json_value.as_u64();
+        assert_eq!(json_num, Some(12));
+    }
+
+    #[test]
+    fn test_as_f64(){
+        let json_value = from_str("12.0").unwrap();
+        let json_num = json_value.as_f64();
+        assert_eq!(json_num, Some(12f64));
+    }
+
+    #[test]
+    fn test_is_boolean(){
+        let json_value = from_str("false").unwrap();
+        assert!(json_value.is_boolean());
+    }
+
+    #[test]
+    fn test_as_boolean(){
+        let json_value = from_str("false").unwrap();
+        let json_bool = json_value.as_boolean();
+        let expected_bool = false;
+        assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
+    }
+
+    #[test]
+    fn test_is_null(){
+        let json_value = from_str("null").unwrap();
+        assert!(json_value.is_null());
+    }
+
+    #[test]
+    fn test_as_null(){
+        let json_value = from_str("null").unwrap();
+        let json_null = json_value.as_null();
+        let expected_null = ();
+        assert!(json_null.is_some() && json_null.unwrap() == expected_null);
+    }
+
+    #[test]
+    fn test_encode_hashmap_with_numeric_key() {
+        use std::str::from_utf8;
+        use std::io::Writer;
+        use std::collections::HashMap;
+        let mut hm: HashMap<uint, bool> = HashMap::new();
+        hm.insert(1, true);
+        let mut mem_buf = Vec::new();
+        write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap();
+        let json_str = from_utf8(mem_buf[]).unwrap();
+        match from_str(json_str) {
+            Err(_) => panic!("Unable to parse json_str: {}", json_str),
+            _ => {} // it parsed and we are good to go
+        }
+    }
+
+    #[test]
+    fn test_prettyencode_hashmap_with_numeric_key() {
+        use std::str::from_utf8;
+        use std::io::Writer;
+        use std::collections::HashMap;
+        let mut hm: HashMap<uint, bool> = HashMap::new();
+        hm.insert(1, true);
+        let mut mem_buf = Vec::new();
+        write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap();
+        let json_str = from_utf8(mem_buf[]).unwrap();
+        match from_str(json_str) {
+            Err(_) => panic!("Unable to parse json_str: {}", json_str),
+            _ => {} // it parsed and we are good to go
+        }
+    }
+
+    #[test]
+    fn test_prettyencoder_indent_level_param() {
+        use std::str::from_utf8;
+        use std::collections::BTreeMap;
+
+        let mut tree = BTreeMap::new();
+
+        tree.insert("hello".to_string(), String("guten tag".to_string()));
+        tree.insert("goodbye".to_string(), String("sayonara".to_string()));
+
+        let json = Array(
+            // The following layout below should look a lot like
+            // the pretty-printed JSON (indent * x)
+            vec!
+            ( // 0x
+                String("greetings".to_string()), // 1x
+                Object(tree), // 1x + 2x + 2x + 1x
+            ) // 0x
+            // End JSON array (7 lines)
+        );
+
+        // Helper function for counting indents
+        fn indents(source: &str) -> uint {
+            let trimmed = source.trim_left_matches(' ');
+            source.len() - trimmed.len()
+        }
+
+        // Test up to 4 spaces of indents (more?)
+        for i in range(0, 4u) {
+            let mut writer = Vec::new();
+            write!(&mut writer, "{}",
+                   super::as_pretty_json(&json).indent(i)).unwrap();
+
+            let printed = from_utf8(writer[]).unwrap();
+
+            // Check for indents at each line
+            let lines: Vec<&str> = printed.lines().collect();
+            assert_eq!(lines.len(), 7); // JSON should be 7 lines
+
+            assert_eq!(indents(lines[0]), 0 * i); // [
+            assert_eq!(indents(lines[1]), 1 * i); //   "greetings",
+            assert_eq!(indents(lines[2]), 1 * i); //   {
+            assert_eq!(indents(lines[3]), 2 * i); //     "hello": "guten tag",
+            assert_eq!(indents(lines[4]), 2 * i); //     "goodbye": "sayonara"
+            assert_eq!(indents(lines[5]), 1 * i); //   },
+            assert_eq!(indents(lines[6]), 0 * i); // ]
+
+            // Finally, test that the pretty-printed JSON is valid
+            from_str(printed).ok().expect("Pretty-printed JSON is invalid!");
+        }
+    }
+
+    #[test]
+    fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
+        use std::collections::HashMap;
+        use Decodable;
+        let json_str = "{\"1\":true}";
+        let json_obj = match from_str(json_str) {
+            Err(_) => panic!("Unable to parse json_str: {}", json_str),
+            Ok(o) => o
+        };
+        let mut decoder = Decoder::new(json_obj);
+        let _hm: HashMap<uint, bool> = Decodable::decode(&mut decoder).unwrap();
+    }
+
+    #[test]
+    fn test_hashmap_with_numeric_key_will_error_with_string_keys() {
+        use std::collections::HashMap;
+        use Decodable;
+        let json_str = "{\"a\":true}";
+        let json_obj = match from_str(json_str) {
+            Err(_) => panic!("Unable to parse json_str: {}", json_str),
+            Ok(o) => o
+        };
+        let mut decoder = Decoder::new(json_obj);
+        let result: Result<HashMap<uint, bool>, DecoderError> = Decodable::decode(&mut decoder);
+        assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string())));
+    }
+
+    fn assert_stream_equal(src: &str,
+                           expected: Vec<(JsonEvent, Vec<StackElement>)>) {
+        let mut parser = Parser::new(src.chars());
+        let mut i = 0;
+        loop {
+            let evt = match parser.next() {
+                Some(e) => e,
+                None => { break; }
+            };
+            let (ref expected_evt, ref expected_stack) = expected[i];
+            if !parser.stack().is_equal_to(expected_stack.as_slice()) {
+                panic!("Parser stack is not equal to {}", expected_stack);
+            }
+            assert_eq!(&evt, expected_evt);
+            i+=1;
+        }
+    }
+    #[test]
+    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    fn test_streaming_parser() {
+        assert_stream_equal(
+            r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#,
+            vec![
+                (ObjectStart,             vec![]),
+                  (StringValue("bar".to_string()),   vec![Key("foo")]),
+                  (ArrayStart,            vec![Key("array")]),
+                    (U64Value(0),         vec![Key("array"), Index(0)]),
+                    (U64Value(1),         vec![Key("array"), Index(1)]),
+                    (U64Value(2),         vec![Key("array"), Index(2)]),
+                    (U64Value(3),         vec![Key("array"), Index(3)]),
+                    (U64Value(4),         vec![Key("array"), Index(4)]),
+                    (U64Value(5),         vec![Key("array"), Index(5)]),
+                  (ArrayEnd,              vec![Key("array")]),
+                  (ArrayStart,            vec![Key("idents")]),
+                    (NullValue,           vec![Key("idents"), Index(0)]),
+                    (BooleanValue(true),  vec![Key("idents"), Index(1)]),
+                    (BooleanValue(false), vec![Key("idents"), Index(2)]),
+                  (ArrayEnd,              vec![Key("idents")]),
+                (ObjectEnd,               vec![]),
+            ]
+        );
+    }
+    fn last_event(src: &str) -> JsonEvent {
+        let mut parser = Parser::new(src.chars());
+        let mut evt = NullValue;
+        loop {
+            evt = match parser.next() {
+                Some(e) => e,
+                None => return evt,
+            }
+        }
+    }
+
+    #[test]
+    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    fn test_read_object_streaming() {
+        assert_eq!(last_event("{ "),      Error(SyntaxError(EOFWhileParsingObject, 1, 3)));
+        assert_eq!(last_event("{1"),      Error(SyntaxError(KeyMustBeAString,      1, 2)));
+        assert_eq!(last_event("{ \"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 6)));
+        assert_eq!(last_event("{\"a\""),  Error(SyntaxError(EOFWhileParsingObject, 1, 5)));
+        assert_eq!(last_event("{\"a\" "), Error(SyntaxError(EOFWhileParsingObject, 1, 6)));
+
+        assert_eq!(last_event("{\"a\" 1"),   Error(SyntaxError(ExpectedColon,         1, 6)));
+        assert_eq!(last_event("{\"a\":"),    Error(SyntaxError(EOFWhileParsingValue,  1, 6)));
+        assert_eq!(last_event("{\"a\":1"),   Error(SyntaxError(EOFWhileParsingObject, 1, 7)));
+        assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax,         1, 8)));
+        assert_eq!(last_event("{\"a\":1,"),  Error(SyntaxError(EOFWhileParsingObject, 1, 8)));
+        assert_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8)));
+
+        assert_stream_equal(
+            "{}",
+            vec![(ObjectStart, vec![]), (ObjectEnd, vec![])]
+        );
+        assert_stream_equal(
+            "{\"a\": 3}",
+            vec![
+                (ObjectStart,        vec![]),
+                  (U64Value(3),      vec![Key("a")]),
+                (ObjectEnd,          vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "{ \"a\": null, \"b\" : true }",
+            vec![
+                (ObjectStart,           vec![]),
+                  (NullValue,           vec![Key("a")]),
+                  (BooleanValue(true),  vec![Key("b")]),
+                (ObjectEnd,             vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "{\"a\" : 1.0 ,\"b\": [ true ]}",
+            vec![
+                (ObjectStart,           vec![]),
+                  (F64Value(1.0),       vec![Key("a")]),
+                  (ArrayStart,          vec![Key("b")]),
+                    (BooleanValue(true),vec![Key("b"), Index(0)]),
+                  (ArrayEnd,            vec![Key("b")]),
+                (ObjectEnd,             vec![]),
+            ]
+        );
+        assert_stream_equal(
+            r#"{
+                "a": 1.0,
+                "b": [
+                    true,
+                    "foo\nbar",
+                    { "c": {"d": null} }
+                ]
+            }"#,
+            vec![
+                (ObjectStart,                   vec![]),
+                  (F64Value(1.0),               vec![Key("a")]),
+                  (ArrayStart,                  vec![Key("b")]),
+                    (BooleanValue(true),        vec![Key("b"), Index(0)]),
+                    (StringValue("foo\nbar".to_string()),  vec![Key("b"), Index(1)]),
+                    (ObjectStart,               vec![Key("b"), Index(2)]),
+                      (ObjectStart,             vec![Key("b"), Index(2), Key("c")]),
+                        (NullValue,             vec![Key("b"), Index(2), Key("c"), Key("d")]),
+                      (ObjectEnd,               vec![Key("b"), Index(2), Key("c")]),
+                    (ObjectEnd,                 vec![Key("b"), Index(2)]),
+                  (ArrayEnd,                    vec![Key("b")]),
+                (ObjectEnd,                     vec![]),
+            ]
+        );
+    }
+    #[test]
+    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    fn test_read_array_streaming() {
+        assert_stream_equal(
+            "[]",
+            vec![
+                (ArrayStart, vec![]),
+                (ArrayEnd,   vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[ ]",
+            vec![
+                (ArrayStart, vec![]),
+                (ArrayEnd,   vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[true]",
+            vec![
+                (ArrayStart,             vec![]),
+                    (BooleanValue(true), vec![Index(0)]),
+                (ArrayEnd,               vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[ false ]",
+            vec![
+                (ArrayStart,              vec![]),
+                    (BooleanValue(false), vec![Index(0)]),
+                (ArrayEnd,                vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[null]",
+            vec![
+                (ArrayStart,    vec![]),
+                    (NullValue, vec![Index(0)]),
+                (ArrayEnd,      vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[3, 1]",
+            vec![
+                (ArrayStart,      vec![]),
+                    (U64Value(3), vec![Index(0)]),
+                    (U64Value(1), vec![Index(1)]),
+                (ArrayEnd,        vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "\n[3, 2]\n",
+            vec![
+                (ArrayStart,      vec![]),
+                    (U64Value(3), vec![Index(0)]),
+                    (U64Value(2), vec![Index(1)]),
+                (ArrayEnd,        vec![]),
+            ]
+        );
+        assert_stream_equal(
+            "[2, [4, 1]]",
+            vec![
+                (ArrayStart,           vec![]),
+                    (U64Value(2),      vec![Index(0)]),
+                    (ArrayStart,       vec![Index(1)]),
+                        (U64Value(4),  vec![Index(1), Index(0)]),
+                        (U64Value(1),  vec![Index(1), Index(1)]),
+                    (ArrayEnd,         vec![Index(1)]),
+                (ArrayEnd,             vec![]),
+            ]
+        );
+
+        assert_eq!(last_event("["), Error(SyntaxError(EOFWhileParsingValue, 1,  2)));
+
+        assert_eq!(from_str("["),     Err(SyntaxError(EOFWhileParsingValue, 1, 2)));
+        assert_eq!(from_str("[1"),    Err(SyntaxError(EOFWhileParsingArray, 1, 3)));
+        assert_eq!(from_str("[1,"),   Err(SyntaxError(EOFWhileParsingValue, 1, 4)));
+        assert_eq!(from_str("[1,]"),  Err(SyntaxError(InvalidSyntax,        1, 4)));
+        assert_eq!(from_str("[6 7]"), Err(SyntaxError(InvalidSyntax,        1, 4)));
+
+    }
+    #[test]
+    fn test_trailing_characters_streaming() {
+        assert_eq!(last_event("nulla"),  Error(SyntaxError(TrailingCharacters, 1, 5)));
+        assert_eq!(last_event("truea"),  Error(SyntaxError(TrailingCharacters, 1, 5)));
+        assert_eq!(last_event("falsea"), Error(SyntaxError(TrailingCharacters, 1, 6)));
+        assert_eq!(last_event("1a"),     Error(SyntaxError(TrailingCharacters, 1, 2)));
+        assert_eq!(last_event("[]a"),    Error(SyntaxError(TrailingCharacters, 1, 3)));
+        assert_eq!(last_event("{}a"),    Error(SyntaxError(TrailingCharacters, 1, 3)));
+    }
+    #[test]
+    fn test_read_identifiers_streaming() {
+        assert_eq!(Parser::new("null".chars()).next(), Some(NullValue));
+        assert_eq!(Parser::new("true".chars()).next(), Some(BooleanValue(true)));
+        assert_eq!(Parser::new("false".chars()).next(), Some(BooleanValue(false)));
+
+        assert_eq!(last_event("n"),    Error(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(last_event("nul"),  Error(SyntaxError(InvalidSyntax, 1, 4)));
+        assert_eq!(last_event("t"),    Error(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(last_event("truz"), Error(SyntaxError(InvalidSyntax, 1, 4)));
+        assert_eq!(last_event("f"),    Error(SyntaxError(InvalidSyntax, 1, 2)));
+        assert_eq!(last_event("faz"),  Error(SyntaxError(InvalidSyntax, 1, 3)));
+    }
+
+    #[test]
+    fn test_stack() {
+        let mut stack = Stack::new();
+
+        assert!(stack.is_empty());
+        assert!(stack.len() == 0);
+        assert!(!stack.last_is_index());
+
+        stack.push_index(0);
+        stack.bump_index();
+
+        assert!(stack.len() == 1);
+        assert!(stack.is_equal_to(&[Index(1)]));
+        assert!(stack.starts_with(&[Index(1)]));
+        assert!(stack.ends_with(&[Index(1)]));
+        assert!(stack.last_is_index());
+        assert!(stack.get(0) == Index(1));
+
+        stack.push_key("foo".to_string());
+
+        assert!(stack.len() == 2);
+        assert!(stack.is_equal_to(&[Index(1), Key("foo")]));
+        assert!(stack.starts_with(&[Index(1), Key("foo")]));
+        assert!(stack.starts_with(&[Index(1)]));
+        assert!(stack.ends_with(&[Index(1), Key("foo")]));
+        assert!(stack.ends_with(&[Key("foo")]));
+        assert!(!stack.last_is_index());
+        assert!(stack.get(0) == Index(1));
+        assert!(stack.get(1) == Key("foo"));
+
+        stack.push_key("bar".to_string());
+
+        assert!(stack.len() == 3);
+        assert!(stack.is_equal_to(&[Index(1), Key("foo"), Key("bar")]));
+        assert!(stack.starts_with(&[Index(1)]));
+        assert!(stack.starts_with(&[Index(1), Key("foo")]));
+        assert!(stack.starts_with(&[Index(1), Key("foo"), Key("bar")]));
+        assert!(stack.ends_with(&[Key("bar")]));
+        assert!(stack.ends_with(&[Key("foo"), Key("bar")]));
+        assert!(stack.ends_with(&[Index(1), Key("foo"), Key("bar")]));
+        assert!(!stack.last_is_index());
+        assert!(stack.get(0) == Index(1));
+        assert!(stack.get(1) == Key("foo"));
+        assert!(stack.get(2) == Key("bar"));
+
+        stack.pop();
+
+        assert!(stack.len() == 2);
+        assert!(stack.is_equal_to(&[Index(1), Key("foo")]));
+        assert!(stack.starts_with(&[Index(1), Key("foo")]));
+        assert!(stack.starts_with(&[Index(1)]));
+        assert!(stack.ends_with(&[Index(1), Key("foo")]));
+        assert!(stack.ends_with(&[Key("foo")]));
+        assert!(!stack.last_is_index());
+        assert!(stack.get(0) == Index(1));
+        assert!(stack.get(1) == Key("foo"));
+    }
+
+    #[test]
+    fn test_to_json() {
+        use std::collections::{HashMap,BTreeMap};
+        use super::ToJson;
+
+        let array2 = Array(vec!(U64(1), U64(2)));
+        let array3 = Array(vec!(U64(1), U64(2), U64(3)));
+        let object = {
+            let mut tree_map = BTreeMap::new();
+            tree_map.insert("a".to_string(), U64(1));
+            tree_map.insert("b".to_string(), U64(2));
+            Object(tree_map)
+        };
+
+        assert_eq!(array2.to_json(), array2);
+        assert_eq!(object.to_json(), object);
+        assert_eq!(3_i.to_json(), I64(3));
+        assert_eq!(4_i8.to_json(), I64(4));
+        assert_eq!(5_i16.to_json(), I64(5));
+        assert_eq!(6_i32.to_json(), I64(6));
+        assert_eq!(7_i64.to_json(), I64(7));
+        assert_eq!(8_u.to_json(), U64(8));
+        assert_eq!(9_u8.to_json(), U64(9));
+        assert_eq!(10_u16.to_json(), U64(10));
+        assert_eq!(11_u32.to_json(), U64(11));
+        assert_eq!(12_u64.to_json(), U64(12));
+        assert_eq!(13.0_f32.to_json(), F64(13.0_f64));
+        assert_eq!(14.0_f64.to_json(), F64(14.0_f64));
+        assert_eq!(().to_json(), Null);
+        assert_eq!(f32::INFINITY.to_json(), Null);
+        assert_eq!(f64::NAN.to_json(), Null);
+        assert_eq!(true.to_json(), Boolean(true));
+        assert_eq!(false.to_json(), Boolean(false));
+        assert_eq!("abc".to_json(), String("abc".to_string()));
+        assert_eq!("abc".to_string().to_json(), String("abc".to_string()));
+        assert_eq!((1u, 2u).to_json(), array2);
+        assert_eq!((1u, 2u, 3u).to_json(), array3);
+        assert_eq!([1u, 2].to_json(), array2);
+        assert_eq!((&[1u, 2, 3]).to_json(), array3);
+        assert_eq!((vec![1u, 2]).to_json(), array2);
+        assert_eq!(vec!(1u, 2, 3).to_json(), array3);
+        let mut tree_map = BTreeMap::new();
+        tree_map.insert("a".to_string(), 1u);
+        tree_map.insert("b".to_string(), 2);
+        assert_eq!(tree_map.to_json(), object);
+        let mut hash_map = HashMap::new();
+        hash_map.insert("a".to_string(), 1u);
+        hash_map.insert("b".to_string(), 2);
+        assert_eq!(hash_map.to_json(), object);
+        assert_eq!(Some(15i).to_json(), I64(15));
+        assert_eq!(Some(15u).to_json(), U64(15));
+        assert_eq!(None::<int>.to_json(), Null);
+    }
+
+    #[bench]
+    fn bench_streaming_small(b: &mut Bencher) {
+        b.iter( || {
+            let mut parser = Parser::new(
+                r#"{
+                    "a": 1.0,
+                    "b": [
+                        true,
+                        "foo\nbar",
+                        { "c": {"d": null} }
+                    ]
+                }"#.chars()
+            );
+            loop {
+                match parser.next() {
+                    None => return,
+                    _ => {}
+                }
+            }
+        });
+    }
+    #[bench]
+    fn bench_small(b: &mut Bencher) {
+        b.iter( || {
+            let _ = from_str(r#"{
+                "a": 1.0,
+                "b": [
+                    true,
+                    "foo\nbar",
+                    { "c": {"d": null} }
+                ]
+            }"#);
+        });
+    }
+
+    fn big_json() -> string::String {
+        let mut src = "[\n".to_string();
+        for _ in range(0i, 500) {
+            src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \
+                            [1,2,3]},"#);
+        }
+        src.push_str("{}]");
+        return src;
+    }
+
+    #[bench]
+    fn bench_streaming_large(b: &mut Bencher) {
+        let src = big_json();
+        b.iter( || {
+            let mut parser = Parser::new(src.chars());
+            loop {
+                match parser.next() {
+                    None => return,
+                    _ => {}
+                }
+            }
+        });
+    }
+    #[bench]
+    fn bench_large(b: &mut Bencher) {
+        let src = big_json();
+        b.iter( || { let _ = from_str(src.as_slice()); });
+    }
+}
index 1ec6a2af309a7eaa113c96f21ecedf363ccdac14..8ad2013f9368f256fe50f734ce8a59eaff30502c 100644 (file)
 pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
                           DecoderHelpers, EncoderHelpers};
 
+#[cfg(stage0)]
+#[path = "serialize_stage0.rs"]
 mod serialize;
+#[cfg(not(stage0))]
+mod serialize;
+
+#[cfg(stage0)]
+#[path = "collection_impls_stage0.rs"]
+mod collection_impls;
+#[cfg(not(stage0))]
 mod collection_impls;
 
 pub mod base64;
 pub mod hex;
+
+#[cfg(stage0)]
+#[path = "json_stage0.rs"]
+pub mod json;
+#[cfg(not(stage0))]
 pub mod json;
 
 mod rustc_serialize {
index 558f9e603e15989fd8ccbd1607761883ffe6d235..0646ee1758fc0f6b19af44260ab55a5479d14132 100644 (file)
 use std::cell::{Cell, RefCell};
 use std::sync::Arc;
 
-pub trait Encoder<E> {
+pub trait Encoder {
+    type Error;
+
     // Primitive types:
-    fn emit_nil(&mut self) -> Result<(), E>;
-    fn emit_uint(&mut self, v: uint) -> Result<(), E>;
-    fn emit_u64(&mut self, v: u64) -> Result<(), E>;
-    fn emit_u32(&mut self, v: u32) -> Result<(), E>;
-    fn emit_u16(&mut self, v: u16) -> Result<(), E>;
-    fn emit_u8(&mut self, v: u8) -> Result<(), E>;
-    fn emit_int(&mut self, v: int) -> Result<(), E>;
-    fn emit_i64(&mut self, v: i64) -> Result<(), E>;
-    fn emit_i32(&mut self, v: i32) -> Result<(), E>;
-    fn emit_i16(&mut self, v: i16) -> Result<(), E>;
-    fn emit_i8(&mut self, v: i8) -> Result<(), E>;
-    fn emit_bool(&mut self, v: bool) -> Result<(), E>;
-    fn emit_f64(&mut self, v: f64) -> Result<(), E>;
-    fn emit_f32(&mut self, v: f32) -> Result<(), E>;
-    fn emit_char(&mut self, v: char) -> Result<(), E>;
-    fn emit_str(&mut self, v: &str) -> Result<(), E>;
+    fn emit_nil(&mut self) -> Result<(), Self::Error>;
+    fn emit_uint(&mut self, v: uint) -> Result<(), Self::Error>;
+    fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
+    fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
+    fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
+    fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
+    fn emit_int(&mut self, v: int) -> Result<(), Self::Error>;
+    fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
+    fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
+    fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
+    fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>;
+    fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
+    fn emit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
+    fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>;
+    fn emit_char(&mut self, v: char) -> Result<(), Self::Error>;
+    fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>;
 
     // Compound types:
-    fn emit_enum<F>(&mut self, name: &str, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_enum<F>(&mut self, name: &str, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
 
     fn emit_enum_variant<F>(&mut self, v_name: &str,
                             v_id: uint,
                             len: uint,
-                            f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_enum_variant_arg<F>(&mut self, a_idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+                            f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_enum_variant_arg<F>(&mut self, a_idx: uint, f: F)
+                                -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
 
     fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
                                    v_id: uint,
                                    len: uint,
-                                   f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+                                   f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
     fn emit_enum_struct_variant_field<F>(&mut self,
                                          f_name: &str,
                                          f_idx: uint,
-                                         f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+                                         f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+
+    fn emit_struct<F>(&mut self, name: &str, len: uint, f: F)
+                      -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_struct_field<F>(&mut self, f_name: &str, f_idx: uint, f: F)
+                            -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+
+    fn emit_tuple<F>(&mut self, len: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+
+    fn emit_tuple_struct<F>(&mut self, name: &str, len: uint, f: F)
+                            -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_tuple_struct_arg<F>(&mut self, f_idx: uint, f: F)
+                                -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+
+    // Specialized types:
+    fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_option_none(&mut self) -> Result<(), Self::Error>;
+    fn emit_option_some<F>(&mut self, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
 
-    fn emit_struct<F>(&mut self, name: &str, len: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_struct_field<F>(&mut self, f_name: &str, f_idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_seq<F>(&mut self, len: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
 
-    fn emit_tuple<F>(&mut self, len: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_map<F>(&mut self, len: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+    fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
+        where F: FnMut(&mut Self) -> Result<(), Self::Error>;
+    fn emit_map_elt_val<F>(&mut self, idx: uint, f: F) -> Result<(), Self::Error>
+        where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
+}
 
-    fn emit_tuple_struct<F>(&mut self, name: &str, len: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_tuple_struct_arg<F>(&mut self, f_idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
+pub trait Decoder {
+    type Error;
 
-    // Specialized types:
-    fn emit_option<F>(&mut self, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_option_none(&mut self) -> Result<(), E>;
-    fn emit_option_some<F>(&mut self, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-
-    fn emit_seq<F>(&mut self, len: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-
-    fn emit_map<F>(&mut self, len: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-    fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
-        F: FnMut(&mut Self) -> Result<(), E>;
-    fn emit_map_elt_val<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
-        F: FnOnce(&mut Self) -> Result<(), E>;
-}
-
-pub trait Decoder<E> {
     // Primitive types:
-    fn read_nil(&mut self) -> Result<(), E>;
-    fn read_uint(&mut self) -> Result<uint, E>;
-    fn read_u64(&mut self) -> Result<u64, E>;
-    fn read_u32(&mut self) -> Result<u32, E>;
-    fn read_u16(&mut self) -> Result<u16, E>;
-    fn read_u8(&mut self) -> Result<u8, E>;
-    fn read_int(&mut self) -> Result<int, E>;
-    fn read_i64(&mut self) -> Result<i64, E>;
-    fn read_i32(&mut self) -> Result<i32, E>;
-    fn read_i16(&mut self) -> Result<i16, E>;
-    fn read_i8(&mut self) -> Result<i8, E>;
-    fn read_bool(&mut self) -> Result<bool, E>;
-    fn read_f64(&mut self) -> Result<f64, E>;
-    fn read_f32(&mut self) -> Result<f32, E>;
-    fn read_char(&mut self) -> Result<char, E>;
-    fn read_str(&mut self) -> Result<String, E>;
+    fn read_nil(&mut self) -> Result<(), Self::Error>;
+    fn read_uint(&mut self) -> Result<uint, Self::Error>;
+    fn read_u64(&mut self) -> Result<u64, Self::Error>;
+    fn read_u32(&mut self) -> Result<u32, Self::Error>;
+    fn read_u16(&mut self) -> Result<u16, Self::Error>;
+    fn read_u8(&mut self) -> Result<u8, Self::Error>;
+    fn read_int(&mut self) -> Result<int, Self::Error>;
+    fn read_i64(&mut self) -> Result<i64, Self::Error>;
+    fn read_i32(&mut self) -> Result<i32, Self::Error>;
+    fn read_i16(&mut self) -> Result<i16, Self::Error>;
+    fn read_i8(&mut self) -> Result<i8, Self::Error>;
+    fn read_bool(&mut self) -> Result<bool, Self::Error>;
+    fn read_f64(&mut self) -> Result<f64, Self::Error>;
+    fn read_f32(&mut self) -> Result<f32, Self::Error>;
+    fn read_char(&mut self) -> Result<char, Self::Error>;
+    fn read_str(&mut self) -> Result<String, Self::Error>;
 
     // Compound types:
-    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-
-    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
-        F: FnMut(&mut Self, uint) -> Result<T, E>;
-    fn read_enum_variant_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
-        F: FnMut(&mut Self, uint) -> Result<T, E>;
+    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+
+    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F)
+                               -> Result<T, Self::Error>
+        where F: FnMut(&mut Self, uint) -> Result<T, Self::Error>;
+    fn read_enum_variant_arg<T, F>(&mut self, a_idx: uint, f: F)
+                                   -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+
+    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F)
+                                      -> Result<T, Self::Error>
+        where F: FnMut(&mut Self, uint) -> Result<T, Self::Error>;
     fn read_enum_struct_variant_field<T, F>(&mut self,
                                             &f_name: &str,
                                             f_idx: uint,
                                             f: F)
-                                            -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
+                                            -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
 
-    fn read_struct<T, F>(&mut self, s_name: &str, len: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_struct<T, F>(&mut self, s_name: &str, len: uint, f: F)
+                         -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
     fn read_struct_field<T, F>(&mut self,
                                f_name: &str,
                                f_idx: uint,
                                f: F)
-                               -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-
-    fn read_tuple<T, F>(&mut self, len: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-    fn read_tuple_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-
-    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
+                               -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+
+    fn read_tuple<T, F>(&mut self, len: uint, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+    fn read_tuple_arg<T, F>(&mut self, a_idx: uint, f: F)
+                            -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+
+    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: uint, f: F)
+                               -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: uint, f: F)
+                                   -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
 
     // Specialized types:
-    fn read_option<T, F>(&mut self, f: F) -> Result<T, E> where
-        F: FnMut(&mut Self, bool) -> Result<T, E>;
-
-    fn read_seq<T, F>(&mut self, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self, uint) -> Result<T, E>;
-    fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-
-    fn read_map<T, F>(&mut self, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self, uint) -> Result<T, E>;
-    fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
-    fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_option<T, F>(&mut self, f: F) -> Result<T, Self::Error>
+        where F: FnMut(&mut Self, bool) -> Result<T, Self::Error>;
+
+    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self, uint) -> Result<T, Self::Error>;
+    fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+
+    fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self, uint) -> Result<T, Self::Error>;
+    fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F)
+                              -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+    fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F)
+                              -> Result<T, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
 
     // Failure
-    fn error(&mut self, err: &str) -> E;
+    fn error(&mut self, err: &str) -> Self::Error;
 }
 
-pub trait Encodable<S:Encoder<E>, E> for Sized? {
-    fn encode(&self, s: &mut S) -> Result<(), E>;
+pub trait Encodable for Sized? {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>;
 }
 
-pub trait Decodable<D:Decoder<E>, E> {
-    fn decode(d: &mut D) -> Result<Self, E>;
+pub trait Decodable {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for uint {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for uint {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_uint(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for uint {
-    fn decode(d: &mut D) -> Result<uint, E> {
+impl Decodable for uint {
+    fn decode<D: Decoder>(d: &mut D) -> Result<uint, D::Error> {
         d.read_uint()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for u8 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for u8 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u8(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for u8 {
-    fn decode(d: &mut D) -> Result<u8, E> {
+impl Decodable for u8 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<u8, D::Error> {
         d.read_u8()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for u16 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for u16 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u16(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for u16 {
-    fn decode(d: &mut D) -> Result<u16, E> {
+impl Decodable for u16 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<u16, D::Error> {
         d.read_u16()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for u32 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for u32 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u32(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for u32 {
-    fn decode(d: &mut D) -> Result<u32, E> {
+impl Decodable for u32 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<u32, D::Error> {
         d.read_u32()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for u64 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for u64 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u64(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for u64 {
-    fn decode(d: &mut D) -> Result<u64, E> {
+impl Decodable for u64 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<u64, D::Error> {
         d.read_u64()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for int {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for int {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_int(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for int {
-    fn decode(d: &mut D) -> Result<int, E> {
+impl Decodable for int {
+    fn decode<D: Decoder>(d: &mut D) -> Result<int, D::Error> {
         d.read_int()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for i8 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for i8 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_i8(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for i8 {
-    fn decode(d: &mut D) -> Result<i8, E> {
+impl Decodable for i8 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<i8, D::Error> {
         d.read_i8()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for i16 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for i16 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_i16(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for i16 {
-    fn decode(d: &mut D) -> Result<i16, E> {
+impl Decodable for i16 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<i16, D::Error> {
         d.read_i16()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for i32 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for i32 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_i32(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for i32 {
-    fn decode(d: &mut D) -> Result<i32, E> {
+impl Decodable for i32 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<i32, D::Error> {
         d.read_i32()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for i64 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for i64 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_i64(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for i64 {
-    fn decode(d: &mut D) -> Result<i64, E> {
+impl Decodable for i64 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<i64, D::Error> {
         d.read_i64()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for str {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for str {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_str(self)
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for String {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for String {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_str(self[])
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for String {
-    fn decode(d: &mut D) -> Result<String, E> {
+impl Decodable for String {
+    fn decode<D: Decoder>(d: &mut D) -> Result<String, D::Error> {
         d.read_str()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for f32 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for f32 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_f32(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for f32 {
-    fn decode(d: &mut D) -> Result<f32, E> {
+impl Decodable for f32 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<f32, D::Error> {
         d.read_f32()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for f64 {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for f64 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_f64(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for f64 {
-    fn decode(d: &mut D) -> Result<f64, E> {
+impl Decodable for f64 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<f64, D::Error> {
         d.read_f64()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for bool {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for bool {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_bool(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for bool {
-    fn decode(d: &mut D) -> Result<bool, E> {
+impl Decodable for bool {
+    fn decode<D: Decoder>(d: &mut D) -> Result<bool, D::Error> {
         d.read_bool()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for char {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for char {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_char(*self)
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for char {
-    fn decode(d: &mut D) -> Result<char, E> {
+impl Decodable for char {
+    fn decode<D: Decoder>(d: &mut D) -> Result<char, D::Error> {
         d.read_char()
     }
 }
 
-impl<E, S:Encoder<E>> Encodable<S, E> for () {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl Encodable for () {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_nil()
     }
 }
 
-impl<E, D:Decoder<E>> Decodable<D, E> for () {
-    fn decode(d: &mut D) -> Result<(), E> {
+impl Decodable for () {
+    fn decode<D: Decoder>(d: &mut D) -> Result<(), D::Error> {
         d.read_nil()
     }
 }
 
-impl<'a, E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for &'a T {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<'a, Sized? T: Encodable> Encodable for &'a T {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for Box<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<Sized? T: Encodable> Encodable for Box<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<E, D:Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for Box<T> {
-    fn decode(d: &mut D) -> Result<Box<T>, E> {
+impl< T: Decodable> Decodable for Box<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
         Ok(box try!(Decodable::decode(d)))
     }
 }
 
-impl<E, D:Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for Box<[T]> {
-    fn decode(d: &mut D) -> Result<Box<[T]>, E> {
+impl< T: Decodable> Decodable for Box<[T]> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
         let v: Vec<T> = try!(Decodable::decode(d));
         Ok(v.into_boxed_slice())
     }
 }
 
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Rc<T> {
+impl<T:Encodable> Encodable for Rc<T> {
     #[inline]
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
+impl<T:Decodable> Decodable for Rc<T> {
     #[inline]
-    fn decode(d: &mut D) -> Result<Rc<T>, E> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Rc<T>, D::Error> {
         Ok(Rc::new(try!(Decodable::decode(d))))
     }
 }
 
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for [T] {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T:Encodable> Encodable for [T] {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 try!(s.emit_seq_elt(i, |s| e.encode(s)))
@@ -428,8 +446,8 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Vec<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T:Encodable> Encodable for Vec<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 try!(s.emit_seq_elt(i, |s| e.encode(s)))
@@ -439,8 +457,8 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Vec<T> {
-    fn decode(d: &mut D) -> Result<Vec<T>, E> {
+impl<T:Decodable> Decodable for Vec<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Vec<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
             for i in range(0, len) {
@@ -451,8 +469,8 @@ fn decode(d: &mut D) -> Result<Vec<T>, E> {
     }
 }
 
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Option<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T:Encodable> Encodable for Option<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_option(|s| {
             match *self {
                 None => s.emit_option_none(),
@@ -462,8 +480,8 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Option<T> {
-    fn decode(d: &mut D) -> Result<Option<T>, E> {
+impl<T:Decodable> Decodable for Option<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Option<T>, D::Error> {
         d.read_option(|d, b| {
             if b {
                 Ok(Some(try!(Decodable::decode(d))))
@@ -487,22 +505,23 @@ macro_rules! count_idents {
 macro_rules! tuple {
     () => ();
     ( $($name:ident,)+ ) => (
-        impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
+        impl<$($name:Decodable),*> Decodable for ($($name,)*) {
             #[allow(non_snake_case)]
-            fn decode(d: &mut D) -> Result<($($name,)*), E> {
+            fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)*), D::Error> {
                 let len: uint = count_idents!($($name),*);
                 d.read_tuple(len, |d| {
                     let mut i = 0;
-                    let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,E> {
+                    let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 },
+                                                       |d| -> Result<$name,D::Error> {
                         Decodable::decode(d)
                     })),)*);
                     return Ok(ret);
                 })
             }
         }
-        impl<E, S:Encoder<E>,$($name:Encodable<S, E>),*> Encodable<S, E> for ($($name,)*) {
+        impl<$($name:Encodable),*> Encodable for ($($name,)*) {
             #[allow(non_snake_case)]
-            fn encode(&self, s: &mut S) -> Result<(), E> {
+            fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
                 let ($(ref $name,)*) = *self;
                 let mut n = 0;
                 $(let $name = $name; n += 1;)*
@@ -519,40 +538,40 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-impl<E, S: Encoder<E>> Encodable<S, E> for path::posix::Path {
-    fn encode(&self, e: &mut S) -> Result<(), E> {
+impl Encodable for path::posix::Path {
+    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         self.as_vec().encode(e)
     }
 }
 
-impl<E, D: Decoder<E>> Decodable<D, E> for path::posix::Path {
-    fn decode(d: &mut D) -> Result<path::posix::Path, E> {
+impl Decodable for path::posix::Path {
+    fn decode<D: Decoder>(d: &mut D) -> Result<path::posix::Path, D::Error> {
         let bytes: Vec<u8> = try!(Decodable::decode(d));
         Ok(path::posix::Path::new(bytes))
     }
 }
 
-impl<E, S: Encoder<E>> Encodable<S, E> for path::windows::Path {
-    fn encode(&self, e: &mut S) -> Result<(), E> {
+impl Encodable for path::windows::Path {
+    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         self.as_vec().encode(e)
     }
 }
 
-impl<E, D: Decoder<E>> Decodable<D, E> for path::windows::Path {
-    fn decode(d: &mut D) -> Result<path::windows::Path, E> {
+impl Decodable for path::windows::Path {
+    fn decode<D: Decoder>(d: &mut D) -> Result<path::windows::Path, D::Error> {
         let bytes: Vec<u8> = try!(Decodable::decode(d));
         Ok(path::windows::Path::new(bytes))
     }
 }
 
-impl<E, S: Encoder<E>, T: Encodable<S, E> + Copy> Encodable<S, E> for Cell<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T: Encodable + Copy> Encodable for Cell<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         self.get().encode(s)
     }
 }
 
-impl<E, D: Decoder<E>, T: Decodable<D, E> + Copy> Decodable<D, E> for Cell<T> {
-    fn decode(d: &mut D) -> Result<Cell<T>, E> {
+impl<T: Decodable + Copy> Decodable for Cell<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Cell<T>, D::Error> {
         Ok(Cell::new(try!(Decodable::decode(d))))
     }
 }
@@ -562,26 +581,26 @@ fn decode(d: &mut D) -> Result<Cell<T>, E> {
 // `encoder.error("attempting to Encode borrowed RefCell")`
 // from `encode` when `try_borrow` returns `None`.
 
-impl<E, S: Encoder<E>, T: Encodable<S, E>> Encodable<S, E> for RefCell<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T: Encodable> Encodable for RefCell<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         self.borrow().encode(s)
     }
 }
 
-impl<E, D: Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for RefCell<T> {
-    fn decode(d: &mut D) -> Result<RefCell<T>, E> {
+impl<T: Decodable> Decodable for RefCell<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<RefCell<T>, D::Error> {
         Ok(RefCell::new(try!(Decodable::decode(d))))
     }
 }
 
-impl<E, S:Encoder<E>, T:Encodable<S, E>> Encodable<S, E> for Arc<T> {
-    fn encode(&self, s: &mut S) -> Result<(), E> {
+impl<T:Encodable> Encodable for Arc<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<E, D:Decoder<E>,T:Decodable<D, E>+Send+Sync> Decodable<D, E> for Arc<T> {
-    fn decode(d: &mut D) -> Result<Arc<T>, E> {
+impl<T:Decodable+Send+Sync> Decodable for Arc<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Arc<T>, D::Error> {
         Ok(Arc::new(try!(Decodable::decode(d))))
     }
 }
@@ -589,14 +608,15 @@ fn decode(d: &mut D) -> Result<Arc<T>, E> {
 // ___________________________________________________________________________
 // Helper routines
 
-pub trait EncoderHelpers<E> {
-    fn emit_from_vec<T, F>(&mut self, v: &[T], f: F) -> Result<(), E> where
-        F: FnMut(&mut Self, &T) -> Result<(), E>;
+pub trait EncoderHelpers: Encoder {
+    fn emit_from_vec<T, F>(&mut self, v: &[T], f: F)
+                           -> Result<(), <Self as Encoder>::Error>
+        where F: FnMut(&mut Self, &T) -> Result<(), <Self as Encoder>::Error>;
 }
 
-impl<E, S:Encoder<E>> EncoderHelpers<E> for S {
-    fn emit_from_vec<T, F>(&mut self, v: &[T], mut f: F) -> Result<(), E> where
-        F: FnMut(&mut S, &T) -> Result<(), E>,
+impl<S:Encoder> EncoderHelpers for S {
+    fn emit_from_vec<T, F>(&mut self, v: &[T], mut f: F) -> Result<(), S::Error> where
+        F: FnMut(&mut S, &T) -> Result<(), S::Error>,
     {
         self.emit_seq(v.len(), |this| {
             for (i, e) in v.iter().enumerate() {
@@ -609,14 +629,15 @@ fn emit_from_vec<T, F>(&mut self, v: &[T], mut f: F) -> Result<(), E> where
     }
 }
 
-pub trait DecoderHelpers<E> {
-    fn read_to_vec<T, F>(&mut self, f: F) -> Result<Vec<T>, E> where
-        F: FnMut(&mut Self) -> Result<T, E>;
+pub trait DecoderHelpers: Decoder {
+    fn read_to_vec<T, F>(&mut self, f: F)
+                         -> Result<Vec<T>, <Self as Decoder>::Error> where
+        F: FnMut(&mut Self) -> Result<T, <Self as Decoder>::Error>;
 }
 
-impl<E, D:Decoder<E>> DecoderHelpers<E> for D {
-    fn read_to_vec<T, F>(&mut self, mut f: F) -> Result<Vec<T>, E> where F:
-        FnMut(&mut D) -> Result<T, E>,
+impl<D: Decoder> DecoderHelpers for D {
+    fn read_to_vec<T, F>(&mut self, mut f: F) -> Result<Vec<T>, D::Error> where F:
+        FnMut(&mut D) -> Result<T, D::Error>,
     {
         self.read_seq(|this, len| {
             let mut v = Vec::with_capacity(len);
diff --git a/src/libserialize/serialize_stage0.rs b/src/libserialize/serialize_stage0.rs
new file mode 100644 (file)
index 0000000..558f9e6
--- /dev/null
@@ -0,0 +1,629 @@
+// 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.
+
+//! Support code for encoding and decoding types.
+
+/*
+Core encoding and decoding interfaces.
+*/
+
+use std::path;
+use std::rc::Rc;
+use std::cell::{Cell, RefCell};
+use std::sync::Arc;
+
+pub trait Encoder<E> {
+    // Primitive types:
+    fn emit_nil(&mut self) -> Result<(), E>;
+    fn emit_uint(&mut self, v: uint) -> Result<(), E>;
+    fn emit_u64(&mut self, v: u64) -> Result<(), E>;
+    fn emit_u32(&mut self, v: u32) -> Result<(), E>;
+    fn emit_u16(&mut self, v: u16) -> Result<(), E>;
+    fn emit_u8(&mut self, v: u8) -> Result<(), E>;
+    fn emit_int(&mut self, v: int) -> Result<(), E>;
+    fn emit_i64(&mut self, v: i64) -> Result<(), E>;
+    fn emit_i32(&mut self, v: i32) -> Result<(), E>;
+    fn emit_i16(&mut self, v: i16) -> Result<(), E>;
+    fn emit_i8(&mut self, v: i8) -> Result<(), E>;
+    fn emit_bool(&mut self, v: bool) -> Result<(), E>;
+    fn emit_f64(&mut self, v: f64) -> Result<(), E>;
+    fn emit_f32(&mut self, v: f32) -> Result<(), E>;
+    fn emit_char(&mut self, v: char) -> Result<(), E>;
+    fn emit_str(&mut self, v: &str) -> Result<(), E>;
+
+    // Compound types:
+    fn emit_enum<F>(&mut self, name: &str, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_enum_variant<F>(&mut self, v_name: &str,
+                            v_id: uint,
+                            len: uint,
+                            f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_enum_variant_arg<F>(&mut self, a_idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
+                                   v_id: uint,
+                                   len: uint,
+                                   f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_enum_struct_variant_field<F>(&mut self,
+                                         f_name: &str,
+                                         f_idx: uint,
+                                         f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_struct<F>(&mut self, name: &str, len: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_struct_field<F>(&mut self, f_name: &str, f_idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_tuple<F>(&mut self, len: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_tuple_arg<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_tuple_struct<F>(&mut self, name: &str, len: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_tuple_struct_arg<F>(&mut self, f_idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    // Specialized types:
+    fn emit_option<F>(&mut self, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_option_none(&mut self) -> Result<(), E>;
+    fn emit_option_some<F>(&mut self, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_seq<F>(&mut self, len: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_seq_elt<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+
+    fn emit_map<F>(&mut self, len: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+    fn emit_map_elt_key<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
+        F: FnMut(&mut Self) -> Result<(), E>;
+    fn emit_map_elt_val<F>(&mut self, idx: uint, f: F) -> Result<(), E> where
+        F: FnOnce(&mut Self) -> Result<(), E>;
+}
+
+pub trait Decoder<E> {
+    // Primitive types:
+    fn read_nil(&mut self) -> Result<(), E>;
+    fn read_uint(&mut self) -> Result<uint, E>;
+    fn read_u64(&mut self) -> Result<u64, E>;
+    fn read_u32(&mut self) -> Result<u32, E>;
+    fn read_u16(&mut self) -> Result<u16, E>;
+    fn read_u8(&mut self) -> Result<u8, E>;
+    fn read_int(&mut self) -> Result<int, E>;
+    fn read_i64(&mut self) -> Result<i64, E>;
+    fn read_i32(&mut self) -> Result<i32, E>;
+    fn read_i16(&mut self) -> Result<i16, E>;
+    fn read_i8(&mut self) -> Result<i8, E>;
+    fn read_bool(&mut self) -> Result<bool, E>;
+    fn read_f64(&mut self) -> Result<f64, E>;
+    fn read_f32(&mut self) -> Result<f32, E>;
+    fn read_char(&mut self) -> Result<char, E>;
+    fn read_str(&mut self) -> Result<String, E>;
+
+    // Compound types:
+    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
+        F: FnMut(&mut Self, uint) -> Result<T, E>;
+    fn read_enum_variant_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
+        F: FnMut(&mut Self, uint) -> Result<T, E>;
+    fn read_enum_struct_variant_field<T, F>(&mut self,
+                                            &f_name: &str,
+                                            f_idx: uint,
+                                            f: F)
+                                            -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_struct<T, F>(&mut self, s_name: &str, len: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_struct_field<T, F>(&mut self,
+                               f_name: &str,
+                               f_idx: uint,
+                               f: F)
+                               -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_tuple<T, F>(&mut self, len: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_tuple_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    // Specialized types:
+    fn read_option<T, F>(&mut self, f: F) -> Result<T, E> where
+        F: FnMut(&mut Self, bool) -> Result<T, E>;
+
+    fn read_seq<T, F>(&mut self, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self, uint) -> Result<T, E>;
+    fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    fn read_map<T, F>(&mut self, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self, uint) -> Result<T, E>;
+    fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+    fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F) -> Result<T, E> where
+        F: FnOnce(&mut Self) -> Result<T, E>;
+
+    // Failure
+    fn error(&mut self, err: &str) -> E;
+}
+
+pub trait Encodable<S:Encoder<E>, E> for Sized? {
+    fn encode(&self, s: &mut S) -> Result<(), E>;
+}
+
+pub trait Decodable<D:Decoder<E>, E> {
+    fn decode(d: &mut D) -> Result<Self, E>;
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for uint {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_uint(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for uint {
+    fn decode(d: &mut D) -> Result<uint, E> {
+        d.read_uint()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for u8 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_u8(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for u8 {
+    fn decode(d: &mut D) -> Result<u8, E> {
+        d.read_u8()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for u16 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_u16(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for u16 {
+    fn decode(d: &mut D) -> Result<u16, E> {
+        d.read_u16()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for u32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_u32(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for u32 {
+    fn decode(d: &mut D) -> Result<u32, E> {
+        d.read_u32()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for u64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_u64(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for u64 {
+    fn decode(d: &mut D) -> Result<u64, E> {
+        d.read_u64()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for int {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_int(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for int {
+    fn decode(d: &mut D) -> Result<int, E> {
+        d.read_int()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for i8 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_i8(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for i8 {
+    fn decode(d: &mut D) -> Result<i8, E> {
+        d.read_i8()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for i16 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_i16(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for i16 {
+    fn decode(d: &mut D) -> Result<i16, E> {
+        d.read_i16()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for i32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_i32(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for i32 {
+    fn decode(d: &mut D) -> Result<i32, E> {
+        d.read_i32()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for i64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_i64(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for i64 {
+    fn decode(d: &mut D) -> Result<i64, E> {
+        d.read_i64()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for str {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_str(self)
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for String {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_str(self[])
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for String {
+    fn decode(d: &mut D) -> Result<String, E> {
+        d.read_str()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for f32 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_f32(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for f32 {
+    fn decode(d: &mut D) -> Result<f32, E> {
+        d.read_f32()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for f64 {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_f64(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for f64 {
+    fn decode(d: &mut D) -> Result<f64, E> {
+        d.read_f64()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for bool {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_bool(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for bool {
+    fn decode(d: &mut D) -> Result<bool, E> {
+        d.read_bool()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for char {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_char(*self)
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for char {
+    fn decode(d: &mut D) -> Result<char, E> {
+        d.read_char()
+    }
+}
+
+impl<E, S:Encoder<E>> Encodable<S, E> for () {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_nil()
+    }
+}
+
+impl<E, D:Decoder<E>> Decodable<D, E> for () {
+    fn decode(d: &mut D) -> Result<(), E> {
+        d.read_nil()
+    }
+}
+
+impl<'a, E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for &'a T {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        (**self).encode(s)
+    }
+}
+
+impl<E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for Box<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        (**self).encode(s)
+    }
+}
+
+impl<E, D:Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for Box<T> {
+    fn decode(d: &mut D) -> Result<Box<T>, E> {
+        Ok(box try!(Decodable::decode(d)))
+    }
+}
+
+impl<E, D:Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for Box<[T]> {
+    fn decode(d: &mut D) -> Result<Box<[T]>, E> {
+        let v: Vec<T> = try!(Decodable::decode(d));
+        Ok(v.into_boxed_slice())
+    }
+}
+
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Rc<T> {
+    #[inline]
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        (**self).encode(s)
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
+    #[inline]
+    fn decode(d: &mut D) -> Result<Rc<T>, E> {
+        Ok(Rc::new(try!(Decodable::decode(d))))
+    }
+}
+
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for [T] {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)))
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Vec<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_seq(self.len(), |s| {
+            for (i, e) in self.iter().enumerate() {
+                try!(s.emit_seq_elt(i, |s| e.encode(s)))
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Vec<T> {
+    fn decode(d: &mut D) -> Result<Vec<T>, E> {
+        d.read_seq(|d, len| {
+            let mut v = Vec::with_capacity(len);
+            for i in range(0, len) {
+                v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
+            }
+            Ok(v)
+        })
+    }
+}
+
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Option<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        s.emit_option(|s| {
+            match *self {
+                None => s.emit_option_none(),
+                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
+            }
+        })
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Option<T> {
+    fn decode(d: &mut D) -> Result<Option<T>, E> {
+        d.read_option(|d, b| {
+            if b {
+                Ok(Some(try!(Decodable::decode(d))))
+            } else {
+                Ok(None)
+            }
+        })
+    }
+}
+
+macro_rules! peel {
+    ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
+}
+
+/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3
+macro_rules! count_idents {
+    () => { 0u };
+    ($_i:ident $(, $rest:ident)*) => { 1 + count_idents!($($rest),*) }
+}
+
+macro_rules! tuple {
+    () => ();
+    ( $($name:ident,)+ ) => (
+        impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
+            #[allow(non_snake_case)]
+            fn decode(d: &mut D) -> Result<($($name,)*), E> {
+                let len: uint = count_idents!($($name),*);
+                d.read_tuple(len, |d| {
+                    let mut i = 0;
+                    let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,E> {
+                        Decodable::decode(d)
+                    })),)*);
+                    return Ok(ret);
+                })
+            }
+        }
+        impl<E, S:Encoder<E>,$($name:Encodable<S, E>),*> Encodable<S, E> for ($($name,)*) {
+            #[allow(non_snake_case)]
+            fn encode(&self, s: &mut S) -> Result<(), E> {
+                let ($(ref $name,)*) = *self;
+                let mut n = 0;
+                $(let $name = $name; n += 1;)*
+                s.emit_tuple(n, |s| {
+                    let mut i = 0;
+                    $(try!(s.emit_tuple_arg({ i+=1; i-1 }, |s| $name.encode(s)));)*
+                    Ok(())
+                })
+            }
+        }
+        peel! { $($name,)* }
+    )
+}
+
+tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
+
+impl<E, S: Encoder<E>> Encodable<S, E> for path::posix::Path {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
+        self.as_vec().encode(e)
+    }
+}
+
+impl<E, D: Decoder<E>> Decodable<D, E> for path::posix::Path {
+    fn decode(d: &mut D) -> Result<path::posix::Path, E> {
+        let bytes: Vec<u8> = try!(Decodable::decode(d));
+        Ok(path::posix::Path::new(bytes))
+    }
+}
+
+impl<E, S: Encoder<E>> Encodable<S, E> for path::windows::Path {
+    fn encode(&self, e: &mut S) -> Result<(), E> {
+        self.as_vec().encode(e)
+    }
+}
+
+impl<E, D: Decoder<E>> Decodable<D, E> for path::windows::Path {
+    fn decode(d: &mut D) -> Result<path::windows::Path, E> {
+        let bytes: Vec<u8> = try!(Decodable::decode(d));
+        Ok(path::windows::Path::new(bytes))
+    }
+}
+
+impl<E, S: Encoder<E>, T: Encodable<S, E> + Copy> Encodable<S, E> for Cell<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        self.get().encode(s)
+    }
+}
+
+impl<E, D: Decoder<E>, T: Decodable<D, E> + Copy> Decodable<D, E> for Cell<T> {
+    fn decode(d: &mut D) -> Result<Cell<T>, E> {
+        Ok(Cell::new(try!(Decodable::decode(d))))
+    }
+}
+
+// FIXME: #15036
+// Should use `try_borrow`, returning a
+// `encoder.error("attempting to Encode borrowed RefCell")`
+// from `encode` when `try_borrow` returns `None`.
+
+impl<E, S: Encoder<E>, T: Encodable<S, E>> Encodable<S, E> for RefCell<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        self.borrow().encode(s)
+    }
+}
+
+impl<E, D: Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for RefCell<T> {
+    fn decode(d: &mut D) -> Result<RefCell<T>, E> {
+        Ok(RefCell::new(try!(Decodable::decode(d))))
+    }
+}
+
+impl<E, S:Encoder<E>, T:Encodable<S, E>> Encodable<S, E> for Arc<T> {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        (**self).encode(s)
+    }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>+Send+Sync> Decodable<D, E> for Arc<T> {
+    fn decode(d: &mut D) -> Result<Arc<T>, E> {
+        Ok(Arc::new(try!(Decodable::decode(d))))
+    }
+}
+
+// ___________________________________________________________________________
+// Helper routines
+
+pub trait EncoderHelpers<E> {
+    fn emit_from_vec<T, F>(&mut self, v: &[T], f: F) -> Result<(), E> where
+        F: FnMut(&mut Self, &T) -> Result<(), E>;
+}
+
+impl<E, S:Encoder<E>> EncoderHelpers<E> for S {
+    fn emit_from_vec<T, F>(&mut self, v: &[T], mut f: F) -> Result<(), E> where
+        F: FnMut(&mut S, &T) -> Result<(), E>,
+    {
+        self.emit_seq(v.len(), |this| {
+            for (i, e) in v.iter().enumerate() {
+                try!(this.emit_seq_elt(i, |this| {
+                    f(this, e)
+                }));
+            }
+            Ok(())
+        })
+    }
+}
+
+pub trait DecoderHelpers<E> {
+    fn read_to_vec<T, F>(&mut self, f: F) -> Result<Vec<T>, E> where
+        F: FnMut(&mut Self) -> Result<T, E>;
+}
+
+impl<E, D:Decoder<E>> DecoderHelpers<E> for D {
+    fn read_to_vec<T, F>(&mut self, mut f: F) -> Result<Vec<T>, E> where F:
+        FnMut(&mut D) -> Result<T, E>,
+    {
+        self.read_seq(|this, len| {
+            let mut v = Vec::with_capacity(len);
+            for i in range(0, len) {
+                v.push(try!(this.read_seq_elt(i, |this| f(this))));
+            }
+            Ok(v)
+        })
+    }
+}
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
deleted file mode 100644 (file)
index 9c96a9c..0000000
+++ /dev/null
@@ -1,857 +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.
-
-//! C-string manipulation and management
-//!
-//! This modules provides the basic methods for creating and manipulating
-//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
-//! that the string being passed to them is null-terminated, and by default rust's
-//! string types are *not* null terminated.
-//!
-//! The other problem with translating Rust strings to C strings is that Rust
-//! strings can validly contain a null-byte in the middle of the string (0 is a
-//! valid Unicode codepoint). This means that not all Rust strings can actually be
-//! translated to C strings.
-//!
-//! # Creation of a C string
-//!
-//! A C string is managed through the `CString` type defined in this module. It
-//! "owns" the internal buffer of characters and will automatically deallocate the
-//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
-//! and `&[u8]`, but the conversions can fail due to some of the limitations
-//! explained above.
-//!
-//! This also means that currently whenever a C string is created, an allocation
-//! must be performed to place the data elsewhere (the lifetime of the C string is
-//! not tied to the lifetime of the original string/data buffer). If C strings are
-//! heavily used in applications, then caching may be advisable to prevent
-//! unnecessary amounts of allocations.
-//!
-//! Be carefull to remember that the memory is managed by C allocator API and not
-//! by Rust allocator API.
-//! That means that the CString pointers should be freed with C allocator API
-//! if you intend to do that on your own, as the behaviour if you free them with
-//! Rust's allocator API is not well defined
-//!
-//! An example of creating and using a C string would be:
-//!
-//! ```rust
-//! extern crate libc;
-//!
-//! use std::c_str::ToCStr;
-//!
-//! extern {
-//!     fn puts(s: *const libc::c_char);
-//! }
-//!
-//! fn main() {
-//!     let my_string = "Hello, world!";
-//!
-//!     // Allocate the C string with an explicit local that owns the string. The
-//!     // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
-//!     let my_c_string = my_string.to_c_str();
-//!     unsafe {
-//!         puts(my_c_string.as_ptr());
-//!     }
-//!
-//!     // Don't save/return the pointer to the C string, the `c_buffer` will be
-//!     // deallocated when this block returns!
-//!     my_string.with_c_str(|c_buffer| {
-//!         unsafe { puts(c_buffer); }
-//!     });
-//! }
-//! ```
-
-use core::prelude::*;
-use libc;
-
-use cmp::Ordering;
-use fmt;
-use hash;
-use mem;
-use ptr;
-use slice::{self, IntSliceExt};
-use str;
-use string::String;
-use core::kinds::marker;
-
-/// The representation of a C String.
-///
-/// This structure wraps a `*libc::c_char`, and will automatically free the
-/// memory it is pointing to when it goes out of scope.
-#[allow(missing_copy_implementations)]
-pub struct CString {
-    buf: *const libc::c_char,
-    owns_buffer_: bool,
-}
-
-unsafe impl Send for CString { }
-unsafe impl Sync for CString { }
-
-impl Clone for CString {
-    /// Clone this CString into a new, uniquely owned CString. For safety
-    /// reasons, this is always a deep clone with the memory allocated
-    /// with C's allocator API, rather than the usual shallow clone.
-    fn clone(&self) -> CString {
-        let len = self.len() + 1;
-        let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
-        if buf.is_null() { ::alloc::oom() }
-        unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
-        CString { buf: buf as *const libc::c_char, owns_buffer_: true }
-    }
-}
-
-impl PartialEq for CString {
-    fn eq(&self, other: &CString) -> bool {
-        // Check if the two strings share the same buffer
-        if self.buf as uint == other.buf as uint {
-            true
-        } else {
-            unsafe {
-                libc::strcmp(self.buf, other.buf) == 0
-            }
-        }
-    }
-}
-
-impl PartialOrd for CString {
-    #[inline]
-    fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
-        self.as_bytes().partial_cmp(other.as_bytes())
-    }
-}
-
-impl Eq for CString {}
-
-impl<S: hash::Writer> hash::Hash<S> for CString {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.as_bytes().hash(state)
-    }
-}
-
-impl CString {
-    /// Create a C String from a pointer, with memory managed by C's allocator
-    /// API, so avoid calling it with a pointer to memory managed by Rust's
-    /// allocator API, as the behaviour would not be well defined.
-    ///
-    ///# Panics
-    ///
-    /// Panics if `buf` is null
-    pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
-        assert!(!buf.is_null());
-        CString { buf: buf, owns_buffer_: owns_buffer }
-    }
-
-    /// Return a pointer to the NUL-terminated string data.
-    ///
-    /// `.as_ptr` returns an internal pointer into the `CString`, and
-    /// may be invalidated when the `CString` falls out of scope (the
-    /// destructor will run, freeing the allocation if there is
-    /// one).
-    ///
-    /// ```rust
-    /// use std::c_str::ToCStr;
-    ///
-    /// let foo = "some string";
-    ///
-    /// // right
-    /// let x = foo.to_c_str();
-    /// let p = x.as_ptr();
-    ///
-    /// // wrong (the CString will be freed, invalidating `p`)
-    /// let p = foo.to_c_str().as_ptr();
-    /// ```
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// extern crate libc;
-    ///
-    /// use std::c_str::ToCStr;
-    ///
-    /// fn main() {
-    ///     let c_str = "foo bar".to_c_str();
-    ///     unsafe {
-    ///         libc::puts(c_str.as_ptr());
-    ///     }
-    /// }
-    /// ```
-    pub fn as_ptr(&self) -> *const libc::c_char {
-        self.buf
-    }
-
-    /// Return a mutable pointer to the NUL-terminated string data.
-    ///
-    /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
-    /// may be invalidated when the `CString` falls out of scope (the
-    /// destructor will run, freeing the allocation if there is
-    /// one).
-    ///
-    /// ```rust
-    /// use std::c_str::ToCStr;
-    ///
-    /// let foo = "some string";
-    ///
-    /// // right
-    /// let mut x = foo.to_c_str();
-    /// let p = x.as_mut_ptr();
-    ///
-    /// // wrong (the CString will be freed, invalidating `p`)
-    /// let p = foo.to_c_str().as_mut_ptr();
-    /// ```
-    pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
-        self.buf as *mut _
-    }
-
-    /// Returns whether or not the `CString` owns the buffer.
-    pub fn owns_buffer(&self) -> bool {
-        self.owns_buffer_
-    }
-
-    /// Converts the CString into a `&[u8]` without copying.
-    /// Includes the terminating NUL byte.
-    #[inline]
-    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
-        unsafe {
-            slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
-        }
-    }
-
-    /// Converts the CString into a `&[u8]` without copying.
-    /// Does not include the terminating NUL byte.
-    #[inline]
-    pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
-        unsafe {
-            slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
-        }
-    }
-
-    /// Converts the CString into a `&str` without copying.
-    /// Returns None if the CString is not UTF-8.
-    #[inline]
-    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
-        let buf = self.as_bytes_no_nul();
-        str::from_utf8(buf).ok()
-    }
-
-    /// Return a CString iterator.
-    pub fn iter<'a>(&'a self) -> CChars<'a> {
-        CChars {
-            ptr: self.buf,
-            marker: marker::ContravariantLifetime,
-        }
-    }
-
-    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
-    ///
-    /// Any ownership of the buffer by the `CString` wrapper is
-    /// forgotten, meaning that the backing allocation of this
-    /// `CString` is not automatically freed if it owns the
-    /// allocation. In this case, a user of `.unwrap()` should ensure
-    /// the allocation is freed, to avoid leaking memory. You should
-    /// use libc's memory allocator in this case.
-    ///
-    /// Prefer `.as_ptr()` when just retrieving a pointer to the
-    /// string data, as that does not relinquish ownership.
-    pub unsafe fn into_inner(mut self) -> *const libc::c_char {
-        self.owns_buffer_ = false;
-        self.buf
-    }
-
-    /// Return the number of bytes in the CString (not including the NUL
-    /// terminator).
-    #[inline]
-    pub fn len(&self) -> uint {
-        unsafe { libc::strlen(self.buf) as uint }
-    }
-
-    /// Returns if there are no bytes in this string
-    #[inline]
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl Drop for CString {
-    fn drop(&mut self) {
-        if self.owns_buffer_ {
-            unsafe {
-                libc::free(self.buf as *mut libc::c_void)
-            }
-        }
-    }
-}
-
-impl fmt::Show for CString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
-    }
-}
-
-/// A generic trait for converting a value to a CString.
-pub trait ToCStr for Sized? {
-    /// Copy the receiver into a CString.
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the receiver has an interior null.
-    fn to_c_str(&self) -> CString;
-
-    /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
-    unsafe fn to_c_str_unchecked(&self) -> CString;
-
-    /// Work with a temporary CString constructed from the receiver.
-    /// The provided `*libc::c_char` will be freed immediately upon return.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// extern crate libc;
-    ///
-    /// use std::c_str::ToCStr;
-    ///
-    /// fn main() {
-    ///     let s = "PATH".with_c_str(|path| unsafe {
-    ///         libc::getenv(path)
-    ///     });
-    /// }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the receiver has an interior null.
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        let c_str = self.to_c_str();
-        f(c_str.as_ptr())
-    }
-
-    /// Unsafe variant of `with_c_str()` that doesn't check for nulls.
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        let c_str = self.to_c_str_unchecked();
-        f(c_str.as_ptr())
-    }
-}
-
-impl ToCStr for str {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        self.as_bytes().to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_bytes().to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str_unchecked(f)
-    }
-}
-
-impl ToCStr for String {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        self.as_bytes().to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_bytes().to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        self.as_bytes().with_c_str_unchecked(f)
-    }
-}
-
-// The length of the stack allocated buffer for `vec.with_c_str()`
-const BUF_LEN: uint = 128;
-
-impl ToCStr for [u8] {
-    fn to_c_str(&self) -> CString {
-        let mut cs = unsafe { self.to_c_str_unchecked() };
-        check_for_null(self, cs.as_mut_ptr());
-        cs
-    }
-
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        let self_len = self.len();
-        let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
-        if buf.is_null() { ::alloc::oom() }
-
-        ptr::copy_memory(buf, self.as_ptr(), self_len);
-        *buf.offset(self_len as int) = 0;
-
-        CString::new(buf as *const libc::c_char, true)
-    }
-
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        unsafe { with_c_str(self, true, f) }
-    }
-
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        with_c_str(self, false, f)
-    }
-}
-
-impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        (**self).to_c_str()
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        (**self).to_c_str_unchecked()
-    }
-
-    #[inline]
-    fn with_c_str<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        (**self).with_c_str(f)
-    }
-
-    #[inline]
-    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
-        F: FnOnce(*const libc::c_char) -> T,
-    {
-        (**self).with_c_str_unchecked(f)
-    }
-}
-
-// Unsafe function that handles possibly copying the &[u8] into a stack array.
-unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
-    F: FnOnce(*const libc::c_char) -> T,
-{
-    let c_str = if v.len() < BUF_LEN {
-        let mut buf: [u8; BUF_LEN] = mem::uninitialized();
-        slice::bytes::copy_memory(&mut buf, v);
-        buf[v.len()] = 0;
-
-        let buf = buf.as_mut_ptr();
-        if checked {
-            check_for_null(v, buf as *mut libc::c_char);
-        }
-
-        return f(buf as *const libc::c_char)
-    } else if checked {
-        v.to_c_str()
-    } else {
-        v.to_c_str_unchecked()
-    };
-
-    f(c_str.as_ptr())
-}
-
-#[inline]
-fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
-    for i in range(0, v.len()) {
-        unsafe {
-            let p = buf.offset(i as int);
-            assert!(*p != 0);
-        }
-    }
-}
-
-/// External iterator for a CString's bytes.
-///
-/// Use with the `std::iter` module.
-#[allow(raw_pointer_deriving)]
-#[derive(Clone)]
-pub struct CChars<'a> {
-    ptr: *const libc::c_char,
-    marker: marker::ContravariantLifetime<'a>,
-}
-
-impl<'a> Iterator for CChars<'a> {
-    type Item = libc::c_char;
-
-    fn next(&mut self) -> Option<libc::c_char> {
-        let ch = unsafe { *self.ptr };
-        if ch == 0 {
-            None
-        } else {
-            self.ptr = unsafe { self.ptr.offset(1) };
-            Some(ch)
-        }
-    }
-}
-
-/// Parses a C "multistring", eg windows env values or
-/// the req->ptr result in a uv_fs_readdir() call.
-///
-/// Optionally, a `count` can be passed in, limiting the
-/// parsing to only being done `count`-times.
-///
-/// The specified closure is invoked with each string that
-/// is found, and the number of strings found is returned.
-pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
-                                    count: Option<uint>,
-                                    mut f: F)
-                                    -> uint where
-    F: FnMut(&CString),
-{
-
-    let mut curr_ptr: uint = buf as uint;
-    let mut ctr = 0;
-    let (limited_count, limit) = match count {
-        Some(limit) => (true, limit),
-        None => (false, 0)
-    };
-    while ((limited_count && ctr < limit) || !limited_count)
-          && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
-        let cstr = CString::new(curr_ptr as *const libc::c_char, false);
-        f(&cstr);
-        curr_ptr += cstr.len() + 1;
-        ctr += 1;
-    }
-    return ctr;
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-    use super::*;
-    use ptr;
-    use thread::Thread;
-    use libc;
-
-    #[test]
-    fn test_str_multistring_parsing() {
-        unsafe {
-            let input = b"zero\0one\0\0";
-            let ptr = input.as_ptr();
-            let expected = ["zero", "one"];
-            let mut it = expected.iter();
-            let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
-                let cbytes = c.as_bytes_no_nul();
-                assert_eq!(cbytes, it.next().unwrap().as_bytes());
-            });
-            assert_eq!(result, 2);
-            assert!(it.next().is_none());
-        }
-    }
-
-    #[test]
-    fn test_str_to_c_str() {
-        let c_str = "".to_c_str();
-        unsafe {
-            assert_eq!(*c_str.as_ptr().offset(0), 0);
-        }
-
-        let c_str = "hello".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(5), 0);
-        }
-    }
-
-    #[test]
-    fn test_vec_to_c_str() {
-        let b: &[u8] = &[];
-        let c_str = b.to_c_str();
-        unsafe {
-            assert_eq!(*c_str.as_ptr().offset(0), 0);
-        }
-
-        let c_str = b"hello".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(5), 0);
-        }
-
-        let c_str = b"foo\xFF".to_c_str();
-        let buf = c_str.as_ptr();
-        unsafe {
-            assert_eq!(*buf.offset(0), 'f' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(2), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char);
-            assert_eq!(*buf.offset(4), 0);
-        }
-    }
-
-    #[test]
-    fn test_unwrap() {
-        let c_str = "hello".to_c_str();
-        unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
-    }
-
-    #[test]
-    fn test_as_ptr() {
-        let c_str = "hello".to_c_str();
-        let len = unsafe { libc::strlen(c_str.as_ptr()) };
-        assert_eq!(len, 5);
-    }
-
-    #[test]
-    fn test_iterator() {
-        let c_str = "".to_c_str();
-        let mut iter = c_str.iter();
-        assert_eq!(iter.next(), None);
-
-        let c_str = "hello".to_c_str();
-        let mut iter = c_str.iter();
-        assert_eq!(iter.next(), Some('h' as libc::c_char));
-        assert_eq!(iter.next(), Some('e' as libc::c_char));
-        assert_eq!(iter.next(), Some('l' as libc::c_char));
-        assert_eq!(iter.next(), Some('l' as libc::c_char));
-        assert_eq!(iter.next(), Some('o' as libc::c_char));
-        assert_eq!(iter.next(), None);
-    }
-
-    #[test]
-    fn test_to_c_str_fail() {
-        assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
-    }
-
-    #[test]
-    fn test_to_c_str_unchecked() {
-        unsafe {
-            let c_string = "he\x00llo".to_c_str_unchecked();
-            let buf = c_string.as_ptr();
-            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
-            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
-            assert_eq!(*buf.offset(2), 0);
-            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(4), 'l' as libc::c_char);
-            assert_eq!(*buf.offset(5), 'o' as libc::c_char);
-            assert_eq!(*buf.offset(6), 0);
-        }
-    }
-
-    #[test]
-    fn test_as_bytes() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"hello\0");
-        let c_str = "".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"\0");
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
-    }
-
-    #[test]
-    fn test_as_bytes_no_nul() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_bytes_no_nul(), b"hello");
-        let c_str = "".to_c_str();
-        let exp: &[u8] = &[];
-        assert_eq!(c_str.as_bytes_no_nul(), exp);
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
-    }
-
-    #[test]
-    fn test_as_str() {
-        let c_str = "hello".to_c_str();
-        assert_eq!(c_str.as_str(), Some("hello"));
-        let c_str = "".to_c_str();
-        assert_eq!(c_str.as_str(), Some(""));
-        let c_str = b"foo\xFF".to_c_str();
-        assert_eq!(c_str.as_str(), None);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_new_fail() {
-        let _c_str = unsafe { CString::new(ptr::null(), false) };
-    }
-
-    #[test]
-    fn test_clone() {
-        let a = "hello".to_c_str();
-        let b = a.clone();
-        assert!(a == b);
-    }
-
-    #[test]
-    fn test_clone_noleak() {
-        fn foo<F>(f: F) where F: FnOnce(&CString) {
-            let s = "test".to_string();
-            let c = s.to_c_str();
-            // give the closure a non-owned CString
-            let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
-            f(&c_);
-            // muck with the buffer for later printing
-            unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
-        }
-
-        let mut c_: Option<CString> = None;
-        foo(|c| {
-            c_ = Some(c.clone());
-            c.clone();
-            // force a copy, reading the memory
-            c.as_bytes().to_vec();
-        });
-        let c_ = c_.unwrap();
-        // force a copy, reading the memory
-        c_.as_bytes().to_vec();
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-
-    use prelude::v1::*;
-    use self::test::Bencher;
-    use libc;
-    use c_str::ToCStr;
-
-    #[inline]
-    fn check(s: &str, c_str: *const libc::c_char) {
-        let s_buf = s.as_ptr();
-        for i in range(0, s.len()) {
-            unsafe {
-                assert_eq!(
-                    *s_buf.offset(i as int) as libc::c_char,
-                    *c_str.offset(i as int));
-            }
-        }
-    }
-
-    static S_SHORT: &'static str = "Mary";
-    static S_MEDIUM: &'static str = "Mary had a little lamb";
-    static S_LONG: &'static str = "\
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb
-        Mary had a little lamb, Little lamb";
-
-    fn bench_to_string(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            let c_str = s.to_c_str();
-            check(s, c_str.as_ptr());
-        })
-    }
-
-    #[bench]
-    fn bench_to_c_str_short(b: &mut Bencher) {
-        bench_to_string(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_to_c_str_medium(b: &mut Bencher) {
-        bench_to_string(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_to_c_str_long(b: &mut Bencher) {
-        bench_to_string(b, S_LONG)
-    }
-
-    fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            let c_str = unsafe { s.to_c_str_unchecked() };
-            check(s, c_str.as_ptr())
-        })
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
-        bench_to_c_str_unchecked(b, S_LONG)
-    }
-
-    fn bench_with_c_str(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            s.with_c_str(|c_str_buf| check(s, c_str_buf))
-        })
-    }
-
-    #[bench]
-    fn bench_with_c_str_short(b: &mut Bencher) {
-        bench_with_c_str(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_with_c_str_medium(b: &mut Bencher) {
-        bench_with_c_str(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_with_c_str_long(b: &mut Bencher) {
-        bench_with_c_str(b, S_LONG)
-    }
-
-    fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
-        b.iter(|| {
-            unsafe {
-                s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
-            }
-        })
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_SHORT)
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_MEDIUM)
-    }
-
-    #[bench]
-    fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
-        bench_with_c_str_unchecked(b, S_LONG)
-    }
-}
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
deleted file mode 100644 (file)
index 4a20208..0000000
+++ /dev/null
@@ -1,232 +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.
-
-//! Library to interface with chunks of memory allocated in C.
-//!
-//! It is often desirable to safely interface with memory allocated from C,
-//! encapsulating the unsafety into allocation and destruction time.  Indeed,
-//! allocating memory externally is currently the only way to give Rust shared
-//! mut state with C programs that keep their own references; vectors are
-//! unsuitable because they could be reallocated or moved at any time, and
-//! importing C memory into a vector takes a one-time snapshot of the memory.
-//!
-//! This module simplifies the usage of such external blocks of memory.  Memory
-//! is encapsulated into an opaque object after creation; the lifecycle of the
-//! memory can be optionally managed by Rust, if an appropriate destructor
-//! closure is provided.  Safety is ensured by bounds-checking accesses, which
-//! are marshalled through get and set functions.
-//!
-//! There are three unsafe functions: the two constructors, and the
-//! unwrap method. The constructors are unsafe for the
-//! obvious reason (they act on a pointer that cannot be checked inside the
-//! method), but `unwrap()` is somewhat more subtle in its unsafety.
-//! It returns the contained pointer, but at the same time destroys the CVec
-//! without running its destructor. This can be used to pass memory back to
-//! C, but care must be taken that the ownership of underlying resources are
-//! handled correctly, i.e. that allocated memory is eventually freed
-//! if necessary.
-
-#![experimental]
-
-use kinds::Send;
-use mem;
-use ops::{Drop, FnOnce};
-use option::Option;
-use option::Option::{Some, None};
-use ptr::PtrExt;
-use ptr;
-use raw;
-use slice::AsSlice;
-use thunk::{Thunk};
-
-/// The type representing a foreign chunk of memory
-pub struct CVec<T> {
-    base: *mut T,
-    len: uint,
-    dtor: Option<Thunk>,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for CVec<T> {
-    fn drop(&mut self) {
-        match self.dtor.take() {
-            None => (),
-            Some(f) => f.invoke(())
-        }
-    }
-}
-
-impl<T> CVec<T> {
-    /// Create a `CVec` from a raw pointer to a buffer with a given length.
-    ///
-    /// Panics if the given pointer is null. The returned vector will not attempt
-    /// to deallocate the vector when dropped.
-    ///
-    /// # Arguments
-    ///
-    /// * base - A raw pointer to a buffer
-    /// * len - The number of elements in the buffer
-    pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
-        assert!(base != ptr::null_mut());
-        CVec {
-            base: base,
-            len: len,
-            dtor: None,
-        }
-    }
-
-    /// Create a `CVec` from a foreign buffer, with a given length,
-    /// and a function to run upon destruction.
-    ///
-    /// Panics if the given pointer is null.
-    ///
-    /// # Arguments
-    ///
-    /// * base - A foreign pointer to a buffer
-    /// * len - The number of elements in the buffer
-    /// * dtor - A fn to run when the value is destructed, useful
-    ///          for freeing the buffer, etc.
-    pub unsafe fn new_with_dtor<F>(base: *mut T,
-                                   len: uint,
-                                   dtor: F)
-                                   -> CVec<T>
-        where F : FnOnce(), F : Send
-    {
-        assert!(base != ptr::null_mut());
-        let dtor: Thunk = Thunk::new(dtor);
-        CVec {
-            base: base,
-            len: len,
-            dtor: Some(dtor)
-        }
-    }
-
-    /// View the stored data as a mutable slice.
-    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
-        unsafe {
-            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
-        }
-    }
-
-    /// Retrieves an element at a given index, returning `None` if the requested
-    /// index is greater than the length of the vector.
-    pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> {
-        if ofs < self.len {
-            Some(unsafe { &*self.base.offset(ofs as int) })
-        } else {
-            None
-        }
-    }
-
-    /// Retrieves a mutable element at a given index, returning `None` if the
-    /// requested index is greater than the length of the vector.
-    pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> {
-        if ofs < self.len {
-            Some(unsafe { &mut *self.base.offset(ofs as int) })
-        } else {
-            None
-        }
-    }
-
-    /// Unwrap the pointer without running the destructor
-    ///
-    /// This method retrieves the underlying pointer, and in the process
-    /// destroys the CVec but without running the destructor. A use case
-    /// would be transferring ownership of the buffer to a C function, as
-    /// in this case you would not want to run the destructor.
-    ///
-    /// Note that if you want to access the underlying pointer without
-    /// cancelling the destructor, you can simply call `transmute` on the return
-    /// value of `get(0)`.
-    pub unsafe fn into_inner(mut self) -> *mut T {
-        self.dtor = None;
-        self.base
-    }
-
-    /// Returns the number of items in this vector.
-    pub fn len(&self) -> uint { self.len }
-
-    /// Returns whether this vector is empty.
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl<T> AsSlice<T> for CVec<T> {
-    /// View the stored data as a slice.
-    fn as_slice<'a>(&'a self) -> &'a [T] {
-        unsafe {
-            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-
-    use super::CVec;
-    use libc;
-    use ptr;
-
-    fn malloc(n: uint) -> CVec<u8> {
-        unsafe {
-            let mem = ptr::Unique(libc::malloc(n as libc::size_t));
-            if mem.0.is_null() { ::alloc::oom() }
-
-            CVec::new_with_dtor(mem.0 as *mut u8,
-                                n,
-                                move|| { libc::free(mem.0 as *mut libc::c_void); })
-        }
-    }
-
-    #[test]
-    fn test_basic() {
-        let mut cv = malloc(16);
-
-        *cv.get_mut(3).unwrap() = 8;
-        *cv.get_mut(4).unwrap() = 9;
-        assert_eq!(*cv.get(3).unwrap(), 8);
-        assert_eq!(*cv.get(4).unwrap(), 9);
-        assert_eq!(cv.len(), 16);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_panic_at_null() {
-        unsafe {
-            CVec::new(ptr::null_mut::<u8>(), 9);
-        }
-    }
-
-    #[test]
-    fn test_overrun_get() {
-        let cv = malloc(16);
-
-        assert!(cv.get(17).is_none());
-    }
-
-    #[test]
-    fn test_overrun_set() {
-        let mut cv = malloc(16);
-
-        assert!(cv.get_mut(17).is_none());
-    }
-
-    #[test]
-    fn test_unwrap() {
-        unsafe {
-            let cv = CVec::new_with_dtor(1 as *mut int,
-                                         0,
-                                         move|:| panic!("Don't run this destructor!"));
-            let p = cv.into_inner();
-            assert_eq!(p, 1 as *mut int);
-        }
-    }
-
-}
index 651f31b205da8170b28f15ab78ba6d51d3eb03e9..c35be86420de87e1ca2849e1309195904190346f 100644 (file)
@@ -14,7 +14,7 @@
 use self::SearchResult::*;
 use self::VacantEntryState::*;
 
-use borrow::BorrowFrom;
+use borrow::{BorrowFrom, ToOwned};
 use clone::Clone;
 use cmp::{max, Eq, PartialEq};
 use default::Default;
@@ -920,12 +920,16 @@ fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
         }
     }
 
-    /// Gets the given key's corresponding entry in the map for in-place manipulation
-    pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> {
+    #[stable]
+    /// Gets the given key's corresponding entry in the map for in-place manipulation.
+    /// Regardless of whether or not `to_owned()` has been called, the key must hash the same way.
+    pub fn entry<'a, Sized? Q>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V>
+        where Q: Eq + Hash<S> + ToOwned<K>
+    {
         // Gotta resize now.
         self.reserve(1);
 
-        let hash = self.make_hash(&key);
+        let hash = self.make_hash(key);
         search_entry_hashed(&mut self.table, hash, key)
     }
 
@@ -1138,8 +1142,10 @@ pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
     }
 }
 
-fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K)
-        -> Entry<'a, K, V> {
+fn search_entry_hashed<'a, K, V, Sized? Q>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q)
+        -> Entry<'a, Q, K, V>
+    where Q: Eq + ToOwned<K>
+{
     // Worst case, we'll find one empty bucket among `size + 1` buckets.
     let size = table.size();
     let mut probe = Bucket::new(table, hash);
@@ -1161,7 +1167,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
         // hash matches?
         if bucket.hash() == hash {
             // key matches?
-            if k == *bucket.read().0 {
+            if *k == *BorrowFrom::borrow_from(bucket.read().0) {
                 return Occupied(OccupiedEntry{
                     elem: bucket,
                 });
@@ -1220,19 +1226,6 @@ fn default() -> HashMap<K, V, H> {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V, H>
-    where Q: BorrowFrom<K> + Hash<S> + Eq
-{
-    #[inline]
-    fn index<'a>(&'a self, index: &Q) -> &'a V {
-        self.get(index).expect("no entry found for key")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H>
     where Q: BorrowFrom<K> + Hash<S> + Eq
@@ -1245,19 +1238,6 @@ fn index<'a>(&'a self, index: &Q) -> &'a V {
     }
 }
 
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-#[stable]
-impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K, V, H>
-    where Q: BorrowFrom<K> + Hash<S> + Eq
-{
-    #[inline]
-    fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
-        self.get_mut(index).expect("no entry found for key")
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): remove cfg after a snapshot
 #[stable]
 impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H>
     where Q: BorrowFrom<K> + Hash<S> + Eq
@@ -1343,24 +1323,27 @@ pub struct Drain<'a, K: 'a, V: 'a> {
     >
 }
 
+#[stable]
 /// A view into a single occupied location in a HashMap
-pub struct OccupiedEntry<'a, K:'a, V:'a> {
+pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
 }
 
+#[stable]
 /// A view into a single empty location in a HashMap
-pub struct VacantEntry<'a, K:'a, V:'a> {
+pub struct VacantEntry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
     hash: SafeHash,
-    key: K,
-    elem: VacantEntryState<K,V, &'a mut RawTable<K, V>>,
+    key: &'a Q,
+    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
 }
 
+#[stable]
 /// A view into a single location in a map, which may be vacant or occupied
-pub enum Entry<'a, K:'a, V:'a> {
+pub enum Entry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
     /// An occupied Entry
     Occupied(OccupiedEntry<'a, K, V>),
     /// A vacant Entry
-    Vacant(VacantEntry<'a, K, V>),
+    Vacant(VacantEntry<'a, Q, K, V>),
 }
 
 /// Possible states of a VacantEntry
@@ -1426,46 +1409,63 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+impl<'a, Sized? Q, K, V> Entry<'a, Q, K, V> {
+    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
+    pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
+        match self {
+            Occupied(entry) => Ok(entry.into_mut()),
+            Vacant(entry) => Err(entry),
+        }
+    }
+}
+
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
+    #[stable]
     /// Gets a reference to the value in the entry
     pub fn get(&self) -> &V {
         self.elem.read().1
     }
 
+    #[stable]
     /// Gets a mutable reference to the value in the entry
     pub fn get_mut(&mut self) -> &mut V {
         self.elem.read_mut().1
     }
 
+    #[stable]
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
     /// with a lifetime bound to the map itself
     pub fn into_mut(self) -> &'a mut V {
         self.elem.into_mut_refs().1
     }
 
+    #[stable]
     /// Sets the value of the entry, and returns the entry's old value
-    pub fn set(&mut self, mut value: V) -> V {
+    pub fn insert(&mut self, mut value: V) -> V {
         let old_value = self.get_mut();
         mem::swap(&mut value, old_value);
         value
     }
 
+    #[stable]
     /// Takes the value out of the entry, and returns it
-    pub fn take(self) -> V {
+    pub fn remove(self) -> V {
         pop_internal(self.elem).1
     }
 }
 
-impl<'a, K, V> VacantEntry<'a, K, V> {
+impl<'a, Sized? Q: 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> {
+    #[stable]
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it
-    pub fn set(self, value: V) -> &'a mut V {
+    pub fn insert(self, value: V) -> &'a mut V {
         match self.elem {
             NeqElem(bucket, ib) => {
-                robin_hood(bucket, ib, self.hash, self.key, value)
+                robin_hood(bucket, ib, self.hash, self.key.to_owned(), value)
             }
             NoElem(bucket) => {
-                bucket.put(self.hash, self.key, value).into_mut_refs().1
+                bucket.put(self.hash, self.key.to_owned(), value).into_mut_refs().1
             }
         }
     }
@@ -1497,6 +1497,8 @@ mod test_map {
     use super::HashMap;
     use super::Entry::{Occupied, Vacant};
     use iter::{range_inclusive, range_step_inclusive, repeat};
+    use borrow::ToOwned;
+    use hash;
     use cell::RefCell;
     use rand::{weak_rng, Rng};
 
@@ -2090,11 +2092,11 @@ fn test_entry(){
         let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
 
         // Existing key (insert)
-        match map.entry(1) {
+        match map.entry(&1) {
             Vacant(_) => unreachable!(),
             Occupied(mut view) => {
                 assert_eq!(view.get(), &10);
-                assert_eq!(view.set(100), 10);
+                assert_eq!(view.insert(100), 10);
             }
         }
         assert_eq!(map.get(&1).unwrap(), &100);
@@ -2102,7 +2104,7 @@ fn test_entry(){
 
 
         // Existing key (update)
-        match map.entry(2) {
+        match map.entry(&2) {
             Vacant(_) => unreachable!(),
             Occupied(mut view) => {
                 let v = view.get_mut();
@@ -2114,10 +2116,10 @@ fn test_entry(){
         assert_eq!(map.len(), 6);
 
         // Existing key (take)
-        match map.entry(3) {
+        match map.entry(&3) {
             Vacant(_) => unreachable!(),
             Occupied(view) => {
-                assert_eq!(view.take(), 30);
+                assert_eq!(view.remove(), 30);
             }
         }
         assert_eq!(map.get(&3), None);
@@ -2125,10 +2127,10 @@ fn test_entry(){
 
 
         // Inexistent key (insert)
-        match map.entry(10) {
+        match map.entry(&10) {
             Occupied(_) => unreachable!(),
             Vacant(view) => {
-                assert_eq!(*view.set(1000), 1000);
+                assert_eq!(*view.insert(1000), 1000);
             }
         }
         assert_eq!(map.get(&10).unwrap(), &1000);
@@ -2156,11 +2158,11 @@ fn check(m: &HashMap<int, ()>) {
 
         for i in range(0u, 1000) {
             let x = rng.gen_range(-10, 10);
-            match m.entry(x) {
+            match m.entry(&x) {
                 Vacant(_) => {},
                 Occupied(e) => {
                     println!("{}: remove {}", i, x);
-                    e.take();
+                    e.remove();
                 },
             }
 
index b1824db93aad120faec507751c130125ad431919..7877e783ed699f622a3b206c55f9a49c2f1165ca 100644 (file)
@@ -164,7 +164,7 @@ pub fn with_hasher(hasher: H) -> HashSet<T, H> {
     ///
     /// let h = SipHasher::new();
     /// let mut set = HashSet::with_capacity_and_hasher(10u, h);
-    /// set.insert(1i);
+    /// set.insert(1);
     /// ```
     #[inline]
     #[unstable = "hasher stuff is unclear"]
@@ -283,8 +283,8 @@ fn first<A, B>((a, _): (A, B)) -> A { a }
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
+    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
     ///
     /// // Can be seen as `a - b`.
     /// for x in a.difference(&b) {
@@ -292,12 +292,12 @@ fn first<A, B>((a, _): (A, B)) -> A { a }
     /// }
     ///
     /// let diff: HashSet<int> = a.difference(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [1i].iter().map(|&x| x).collect());
+    /// assert_eq!(diff, [1].iter().map(|&x| x).collect());
     ///
     /// // Note that difference is not symmetric,
     /// // and `b - a` means something else:
     /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect();
-    /// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
+    /// assert_eq!(diff, [4].iter().map(|&x| x).collect());
     /// ```
     #[stable]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> {
@@ -313,8 +313,8 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
+    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
     ///
     /// // Print 1, 4 in arbitrary order.
     /// for x in a.symmetric_difference(&b) {
@@ -325,7 +325,7 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H
     /// let diff2: HashSet<int> = b.symmetric_difference(&a).map(|&x| x).collect();
     ///
     /// assert_eq!(diff1, diff2);
-    /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect());
+    /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect());
     /// ```
     #[stable]
     pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
@@ -339,8 +339,8 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
+    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
     ///
     /// // Print 2, 3 in arbitrary order.
     /// for x in a.intersection(&b) {
@@ -348,7 +348,7 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
     /// }
     ///
     /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
+    /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect());
     /// ```
     #[stable]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> {
@@ -364,8 +364,8 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a,
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
+    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order.
     /// for x in a.union(&b) {
@@ -373,7 +373,7 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a,
     /// }
     ///
     /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
+    /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
     #[stable]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> {
index 7c87094805deec7b08a281da3c4ac2e7c7283626..ab91beb4f9be1bb450e2bc192953178f33b90350 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.
 //
@@ -139,13 +139,11 @@ pub fn inspect(&self) -> u64 { self.hash }
 /// This function wraps up `hash_keyed` to be the only way outside this
 /// module to generate a SafeHash.
 pub fn make_hash<Sized? T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
-    match hasher.hash(t) {
-        // This constant is exceedingly likely to hash to the same
-        // bucket, but it won't be counted as empty! Just so we can maintain
-        // our precious uniform distribution of initial indexes.
-        EMPTY_BUCKET => SafeHash { hash: 0x8000_0000_0000_0000 },
-        h            => SafeHash { hash: h },
-    }
+    // We need to avoid 0u64 in order to prevent collisions with
+    // EMPTY_HASH. We can maintain our precious uniform distribution
+    // of initial indexes by unconditionally setting the MSB,
+    // effectively reducing 64-bits hashes to 63 bits.
+    SafeHash { hash: 0x8000_0000_0000_0000 | hasher.hash(t) }
 }
 
 // `replace` casts a `*u64` to a `*SafeHash`. Since we statically
index 4be83bfc6646d3ac7fa2becd36c7454964e34330..c0445fb5aea97babd873ca904f8678e4c6dcd93e 100644 (file)
 //! the key has been seen or not. Normally, this would require a `find` followed by an
 //! `insert`, effectively duplicating the search effort on each insertion.
 //!
-//! When a user calls `map.entry(key)`, the map will search for the key and then yield
+//! When a user calls `map.entry(&key)`, the map will search for the key and then yield
 //! a variant of the `Entry` enum.
 //!
 //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case the
 //! let message = "she sells sea shells by the sea shore";
 //!
 //! for c in message.chars() {
-//!     match count.entry(c) {
-//!         Vacant(entry) => { entry.set(1u); },
+//!     match count.entry(&c) {
+//!         Vacant(entry) => { entry.insert(1u); },
 //!         Occupied(mut entry) => *entry.get_mut() += 1,
 //!     }
 //! }
 //! for id in orders.into_iter() {
 //!     // If this is the first time we've seen this customer, initialize them
 //!     // with no blood alcohol. Otherwise, just retrieve them.
-//!     let person = match blood_alcohol.entry(id) {
-//!         Vacant(entry) => entry.set(Person{id: id, blood_alcohol: 0.0}),
+//!     let person = match blood_alcohol.entry(&id) {
+//!         Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}),
 //!         Occupied(entry) => entry.into_mut(),
 //!     };
 //!
index de3d75ffb324202c49001b202a2eee40b852c4a1..66cb1f2c948d9ff28dc0c2fca7cf9c88f2daf13b 100644 (file)
@@ -17,7 +17,7 @@
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
+use ffi::CString;
 use mem;
 use os;
 use str;
@@ -51,13 +51,11 @@ impl DynamicLibrary {
 
     /// Lazily open a dynamic library. When passed None it gives a
     /// handle to the calling process
-    pub fn open<T: ToCStr>(filename: Option<T>)
-                        -> Result<DynamicLibrary, String> {
+    pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
         unsafe {
-            let mut filename = filename;
             let maybe_library = dl::check_for_errors_in(|| {
-                match filename.take() {
-                    Some(name) => dl::open_external(name),
+                match filename {
+                    Some(name) => dl::open_external(name.as_vec()),
                     None => dl::open_internal()
                 }
             });
@@ -131,9 +129,8 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
         // T but that feature is still unimplemented
 
         let maybe_symbol_value = dl::check_for_errors_in(|| {
-            symbol.with_c_str(|raw_string| {
-                dl::symbol(self.handle, raw_string)
-            })
+            let raw_string = CString::from_slice(symbol.as_bytes());
+            dl::symbol(self.handle, raw_string.as_ptr())
         });
 
         // The value must not be constructed if there is an error so
@@ -157,7 +154,7 @@ mod test {
     fn test_loading_cosine() {
         // The math library does not need to be loaded since it is already
         // statically linked in
-        let none: Option<Path> = None; // appease the typechecker
+        let none: Option<&Path> = None; // appease the typechecker
         let libm = match DynamicLibrary::open(none) {
             Err(error) => panic!("Could not load self as module: {}", error),
             Ok(libm) => libm
@@ -202,17 +199,17 @@ fn test_errors_do_not_crash() {
           target_os = "freebsd",
           target_os = "dragonfly"))]
 pub mod dl {
-    use self::Rtld::*;
-
+    pub use self::Rtld::*;
     use prelude::v1::*;
-    use c_str::{CString, ToCStr};
+
+    use ffi::{self, CString};
+    use str;
     use libc;
     use ptr;
 
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
-        filename.with_c_str(|raw_name| {
-            dlopen(raw_name, Lazy as libc::c_int) as *mut u8
-        })
+    pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
+        let s = CString::from_slice(filename);
+        dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8
     }
 
     pub unsafe fn open_internal() -> *mut u8 {
@@ -236,8 +233,8 @@ pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
             let ret = if ptr::null() == last_error {
                 Ok(result)
             } else {
-                Err(String::from_str(CString::new(last_error, false).as_str()
-                    .unwrap()))
+                let s = ffi::c_str_to_bytes(&last_error);
+                Err(str::from_utf8(s).unwrap().to_string())
             };
 
             ret
@@ -273,7 +270,6 @@ fn dlsym(handle: *mut libc::c_void,
 
 #[cfg(target_os = "windows")]
 pub mod dl {
-    use c_str::ToCStr;
     use iter::IteratorExt;
     use libc;
     use ops::FnOnce;
@@ -287,10 +283,9 @@ pub mod dl {
     use string::String;
     use vec::Vec;
 
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
+    pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
         // Windows expects Unicode data
-        let filename_cstr = filename.to_c_str();
-        let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+        let filename_str = str::from_utf8(filename).unwrap();
         let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
         filename_str.push(0);
         LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8
index d3bcdbf1a53e792c84bcff22662555c2efa32622..e48137047b0a95a81265a3264f776124f9db76de 100644 (file)
@@ -12,7 +12,7 @@
 
 use prelude::v1::*;
 
-use any::{Any, AnyRefExt};
+use any::Any;
 use cell::RefCell;
 use io::IoResult;
 use rt::{backtrace, unwind};
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
new file mode 100644 (file)
index 0000000..bef2344
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fmt;
+use iter::IteratorExt;
+use libc;
+use mem;
+use ops::Deref;
+use slice::{self, SliceExt, AsSlice};
+use string::String;
+use vec::Vec;
+
+/// A type representing a C-compatible string
+///
+/// This type serves the primary purpose of being able to generate a
+/// C-compatible string from a Rust byte slice or vector. An instance of this
+/// type is a static guarantee that the underlying bytes contain no interior 0
+/// bytes and the final byte is 0.
+///
+/// A `CString` is created from either a byte slice or a byte vector. After
+/// being created, a `CString` predominately inherits all of its methods from
+/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
+/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
+/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
+/// a `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi::CString;
+/// use libc;
+///
+/// extern {
+///     fn my_printer(s: *const libc::c_char);
+/// }
+///
+/// let to_print = "Hello, world!";
+/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// unsafe {
+///     my_printer(c_to_print.as_ptr());
+/// }
+/// # }
+/// ```
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+pub struct CString {
+    inner: Vec<libc::c_char>,
+}
+
+impl CString {
+    /// Create a new C-compatible string from a byte slice.
+    ///
+    /// This method will copy the data of the slice provided into a new
+    /// allocation, ensuring that there is a trailing 0 byte.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if there are any 0 bytes already in the slice
+    /// provided.
+    pub fn from_slice(v: &[u8]) -> CString {
+        CString::from_vec(v.to_vec())
+    }
+
+    /// Create a C-compatible string from a byte vector.
+    ///
+    /// This method will consume ownership of the provided vector, appending a 0
+    /// byte to the end after verifying that there are no interior 0 bytes.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if there are any 0 bytes already in the vector
+    /// provided.
+    pub fn from_vec(v: Vec<u8>) -> CString {
+        assert!(!v.iter().any(|&x| x == 0));
+        unsafe { CString::from_vec_unchecked(v) }
+    }
+
+    /// Create a C-compatibel string from a byte vector without checking for
+    /// interior 0 bytes.
+    ///
+    /// This method is equivalent to `from_vec` except that no runtime assertion
+    /// is made that `v` contains no 0 bytes.
+    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+        v.push(0);
+        CString { inner: mem::transmute(v) }
+    }
+
+    /// Create a view into this C string which includes the trailing nul
+    /// terminator at the end of the string.
+    pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }
+
+    /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
+    /// `libc::c_char` slice.
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe { mem::transmute(self.as_slice()) }
+    }
+
+    /// Equivalend to `as_slice_with_nul` except that the type returned is a
+    /// `u8` slice instead of a `libc::c_char` slice.
+    pub fn as_bytes_with_nul(&self) -> &[u8] {
+        unsafe { mem::transmute(self.as_slice_with_nul()) }
+    }
+}
+
+impl Deref for CString {
+    type Target = [libc::c_char];
+
+    fn deref(&self) -> &[libc::c_char] {
+        self.inner.slice_to(self.inner.len() - 1)
+    }
+}
+
+impl fmt::Show for CString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        String::from_utf8_lossy(self.as_bytes()).fmt(f)
+    }
+}
+
+/// Interpret a C string as a byte slice.
+///
+/// This function will calculate the length of the C string provided, and it
+/// will then return a corresponding slice for the contents of the C string not
+/// including the nul terminator.
+///
+/// This function will tie the lifetime of the returned slice to the lifetime of
+/// the pointer provided. This is done to help prevent the slice from escaping
+/// the lifetime of the pointer itself. If a longer lifetime is needed, then
+/// `mem::copy_lifetime` should be used.
+///
+/// This function is unsafe because there is no guarantee of the validity of the
+/// pointer `raw` or a guarantee that a nul terminator will be found.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi;
+/// use std::str;
+/// use libc;
+///
+/// extern {
+///     fn my_string() -> *const libc::c_char;
+/// }
+///
+/// unsafe {
+///     let to_print = my_string();
+///     let slice = ffi::c_str_to_bytes(&to_print);
+///     println!("string returned: {}", str::from_utf8(slice).unwrap());
+/// }
+/// # }
+/// ```
+pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+    let len = libc::strlen(*raw);
+    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+/// Interpret a C string as a byte slice with the nul terminator.
+///
+/// This function is identical to `from_raw_buf` except that the returned slice
+/// will include the nul terminator of the string.
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+    let len = libc::strlen(*raw) + 1;
+    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::v1::*;
+    use super::*;
+    use libc;
+    use mem;
+
+    #[test]
+    fn c_to_rust() {
+        let data = b"123\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+        unsafe {
+            assert_eq!(c_str_to_bytes(&ptr), b"123");
+            assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
+        }
+    }
+
+    #[test]
+    fn simple() {
+        let s = CString::from_slice(b"1234");
+        assert_eq!(s.as_bytes(), b"1234");
+        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
+        unsafe {
+            assert_eq!(s.as_slice(),
+                       mem::transmute::<_, &[libc::c_char]>(b"1234"));
+            assert_eq!(s.as_slice_with_nul(),
+                       mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
+        }
+    }
+
+    #[should_fail] #[test]
+    fn build_with_zero1() { CString::from_slice(b"\0"); }
+    #[should_fail] #[test]
+    fn build_with_zero2() { CString::from_vec(vec![0]); }
+
+    #[test]
+    fn build_with_zero3() {
+        unsafe {
+            let s = CString::from_vec_unchecked(vec![0]);
+            assert_eq!(s.as_bytes(), b"\0");
+        }
+    }
+}
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
new file mode 100644 (file)
index 0000000..cc86f80
--- /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.
+
+//! Utilities related to FFI bindings.
+
+#![unstable = "module just underwent fairly large reorganization and the dust \
+               still needs to settle"]
+
+pub use self::c_str::CString;
+pub use self::c_str::c_str_to_bytes;
+pub use self::c_str::c_str_to_bytes_with_nul;
+
+mod c_str;
index 5cb79d41db940a9ceb2b6325af1cd0c17aab5beb..4691c06c1de16abfa62f6da9b9e815cd43c9aafc 100644 (file)
@@ -518,14 +518,16 @@ pub fn rmdir(path: &Path) -> IoResult<()> {
 /// use std::io;
 ///
 /// // one possible implementation of fs::walk_dir only visiting files
-/// fn visit_dirs(dir: &Path, cb: |&Path|) -> io::IoResult<()> {
+/// fn visit_dirs<F>(dir: &Path, cb: &mut F) -> io::IoResult<()> where
+///     F: FnMut(&Path),
+/// {
 ///     if dir.is_dir() {
 ///         let contents = try!(fs::readdir(dir));
 ///         for entry in contents.iter() {
 ///             if entry.is_dir() {
-///                 try!(visit_dirs(entry, |p| cb(p)));
+///                 try!(visit_dirs(entry, cb));
 ///             } else {
-///                 cb(entry);
+///                 (*cb)(entry);
 ///             }
 ///         }
 ///         Ok(())
index ae401a04a96f0a23db4d662ee0fd5658a755745a..3fa0b5645c5288fba7b0ccc61a802ac7b20e88d8 100644 (file)
 pub use self::FileAccess::*;
 pub use self::IoErrorKind::*;
 
-use char::Char;
+use char::CharExt;
 use clone::Clone;
 use default::Default;
 use error::{FromError, Error};
 use string::String;
 use uint;
 use unicode;
-use unicode::char::UnicodeChar;
 use vec::Vec;
 
 // Reexports
index 52b589b5f24a7f50762895dfcfa5d5eb724cf1fc..d398b61fe64cf8596d7926626ffd1eca5c03ac22 100644 (file)
 
 pub use self::IpAddr::*;
 
+use boxed::Box;
 use fmt;
 use io::{self, IoResult, IoError};
 use io::net;
 use iter::{Iterator, IteratorExt};
-use ops::FnOnce;
+use ops::{FnOnce, FnMut};
 use option::Option;
 use option::Option::{None, Some};
 use result::Result::{Ok, Err};
@@ -120,10 +121,10 @@ fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
     }
 
     // Return result of first successful parser
-    fn read_or<T>(&mut self, parsers: &mut [|&mut Parser| -> Option<T>])
+    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T>>])
                -> Option<T> {
         for pf in parsers.iter_mut() {
-            match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
+            match self.read_atomically(|p: &mut Parser| pf.call_mut((p,))) {
                 Some(r) => return Some(r),
                 None => {}
             }
@@ -320,22 +321,22 @@ fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
     }
 
     fn read_ip_addr(&mut self) -> Option<IpAddr> {
-        let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
-        let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
-        self.read_or(&mut [ipv4_addr, ipv6_addr])
+        let ipv4_addr = |&mut: p: &mut Parser| p.read_ipv4_addr();
+        let ipv6_addr = |&mut: p: &mut Parser| p.read_ipv6_addr();
+        self.read_or(&mut [box ipv4_addr, box ipv6_addr])
     }
 
     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
         let ip_addr = |&: p: &mut Parser| {
-            let ipv4_p = |p: &mut Parser| p.read_ip_addr();
-            let ipv6_p = |p: &mut Parser| {
+            let ipv4_p = |&mut: p: &mut Parser| p.read_ip_addr();
+            let ipv6_p = |&mut: p: &mut Parser| {
                 let open_br = |&: p: &mut Parser| p.read_given_char('[');
                 let ip_addr = |&: p: &mut Parser| p.read_ipv6_addr();
                 let clos_br = |&: p: &mut Parser| p.read_given_char(']');
                 p.read_seq_3::<char, IpAddr, char, _, _, _>(open_br, ip_addr, clos_br)
                         .map(|t| match t { (_, ip, _) => ip })
             };
-            p.read_or(&mut [ipv4_p, ipv6_p])
+            p.read_or(&mut [box ipv4_p, box ipv6_p])
         };
         let colon = |&: p: &mut Parser| p.read_given_char(':');
         let port  = |&: p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
index daefdd28b306a5c7264154e567ea18ee28e6fccd..738c70412f78a0aa3def5993a313879ecdeed747 100644 (file)
@@ -22,7 +22,8 @@
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
+use ffi::CString;
+use path::BytesContainer;
 use io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 use sys::pipe::UnixListener as UnixListenerImp;
@@ -53,8 +54,9 @@ impl UnixStream {
     /// let mut stream = UnixStream::connect(&server);
     /// stream.write(&[1, 2, 3]);
     /// ```
-    pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
-        UnixStreamImp::connect(&path.to_c_str(), None)
+    pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixStreamImp::connect(&path, None)
             .map(|inner| UnixStream { inner: inner })
     }
 
@@ -67,13 +69,15 @@ pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
     /// If a `timeout` with zero or negative duration is specified then
     /// the function returns `Err`, with the error kind set to `TimedOut`.
     #[experimental = "the timeout argument is likely to change types"]
-    pub fn connect_timeout<P: ToCStr>(path: &P,
-                                      timeout: Duration) -> IoResult<UnixStream> {
+    pub fn connect_timeout<P>(path: P, timeout: Duration)
+                              -> IoResult<UnixStream>
+                              where P: BytesContainer {
         if timeout <= Duration::milliseconds(0) {
             return Err(standard_error(TimedOut));
         }
 
-        UnixStreamImp::connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64))
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
             .map(|inner| UnixStream { inner: inner })
     }
 
@@ -177,8 +181,9 @@ impl UnixListener {
     /// }
     /// # }
     /// ```
-    pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
-        UnixListenerImp::bind(&path.to_c_str())
+    pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
+        let path = CString::from_slice(path.container_as_bytes());
+        UnixListenerImp::bind(&path)
             .map(|inner| UnixListener { inner: inner })
     }
 }
index 5886c9cc3e287cce773223efc80ef48546860fb6..ea232ad0c3f1b0876b1d860fb1dd1447397b7d1f 100644 (file)
@@ -18,8 +18,8 @@
 
 use prelude::v1::*;
 
-use c_str::{CString, ToCStr};
 use collections::HashMap;
+use ffi::CString;
 use fmt;
 use hash::Hash;
 use io::pipe::{PipeStream, PipePair};
@@ -35,6 +35,7 @@
 use thread::Thread;
 
 #[cfg(windows)] use std::hash::sip::SipState;
+#[cfg(windows)] use str;
 
 /// Signal a process to exit, without forcibly killing it. Corresponds to
 /// SIGTERM on unix platforms.
@@ -109,11 +110,11 @@ pub struct Process {
 impl Hash for EnvKey {
     fn hash(&self, state: &mut SipState) {
         let &EnvKey(ref x) = self;
-        match x.as_str() {
-            Some(s) => for ch in s.chars() {
+        match str::from_utf8(x.as_bytes()) {
+            Ok(s) => for ch in s.chars() {
                 (ch as u8 as char).to_lowercase().hash(state);
             },
-            None => x.hash(state)
+            Err(..) => x.hash(state)
         }
     }
 }
@@ -123,8 +124,8 @@ impl PartialEq for EnvKey {
     fn eq(&self, other: &EnvKey) -> bool {
         let &EnvKey(ref x) = self;
         let &EnvKey(ref y) = other;
-        match (x.as_str(), y.as_str()) {
-            (Some(xs), Some(ys)) => {
+        match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
+            (Ok(xs), Ok(ys)) => {
                 if xs.len() != ys.len() {
                     return false
                 } else {
@@ -185,10 +186,10 @@ pub struct Command {
 }
 
 // FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
+// we cannot usefully take BytesContainer arguments by reference (without forcing an
 // additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
+// for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path
+// instance should be removed, and arguments bound by BytesContainer should be passed by
 // reference. (Here: {new, arg, args, env}.)
 
 impl Command {
@@ -203,9 +204,9 @@ impl Command {
     ///
     /// Builder methods are provided to change these defaults and
     /// otherwise configure the process.
-    pub fn new<T:ToCStr>(program: T) -> Command {
+    pub fn new<T: BytesContainer>(program: T) -> Command {
         Command {
-            program: program.to_c_str(),
+            program: CString::from_slice(program.container_as_bytes()),
             args: Vec::new(),
             env: None,
             cwd: None,
@@ -219,27 +220,29 @@ pub fn new<T:ToCStr>(program: T) -> Command {
     }
 
     /// Add an argument to pass to the program.
-    pub fn arg<'a, T: ToCStr>(&'a mut self, arg: T) -> &'a mut Command {
-        self.args.push(arg.to_c_str());
+    pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
+        self.args.push(CString::from_slice(arg.container_as_bytes()));
         self
     }
 
     /// Add multiple arguments to pass to the program.
-    pub fn args<'a, T: ToCStr>(&'a mut self, args: &[T]) -> &'a mut Command {
-        self.args.extend(args.iter().map(|arg| arg.to_c_str()));;
+    pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
+        self.args.extend(args.iter().map(|arg| {
+            CString::from_slice(arg.container_as_bytes())
+        }));
         self
     }
     // Get a mutable borrow of the environment variable map for this `Command`.
-    fn get_env_map<'a>(&'a mut self) -> &'a mut  EnvMap {
+    fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
         match self.env {
             Some(ref mut map) => map,
             None => {
                 // if the env is currently just inheriting from the parent's,
                 // materialize the parent's env into a hashtable.
-                self.env = Some(os::env_as_bytes().into_iter()
-                                   .map(|(k, v)| (EnvKey(k.to_c_str()),
-                                                  v.to_c_str()))
-                                   .collect());
+                self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
+                    (EnvKey(CString::from_slice(k.as_slice())),
+                     CString::from_slice(v.as_slice()))
+                }).collect());
                 self.env.as_mut().unwrap()
             }
         }
@@ -249,15 +252,20 @@ fn get_env_map<'a>(&'a mut self) -> &'a mut  EnvMap {
     ///
     /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
     /// and case-sensitive on all other platforms.
-    pub fn env<'a, T: ToCStr, U: ToCStr>(&'a mut self, key: T, val: U)
-                                         -> &'a mut Command {
-        self.get_env_map().insert(EnvKey(key.to_c_str()), val.to_c_str());
+    pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
+                         -> &'a mut Command
+                         where T: BytesContainer, U: BytesContainer {
+        let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+        let val = CString::from_slice(val.container_as_bytes());
+        self.get_env_map().insert(key, val);
         self
     }
 
     /// Removes an environment variable mapping.
-    pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
-        self.get_env_map().remove(&EnvKey(key.to_c_str()));
+    pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
+                             where T: BytesContainer {
+        let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+        self.get_env_map().remove(&key);
         self
     }
 
@@ -265,16 +273,19 @@ pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
     ///
     /// If the given slice contains multiple instances of an environment
     /// variable, the *rightmost* instance will determine the value.
-    pub fn env_set_all<'a, T: ToCStr, U: ToCStr>(&'a mut self, env: &[(T,U)])
-                                                 -> &'a mut Command {
-        self.env = Some(env.iter().map(|&(ref k, ref v)| (EnvKey(k.to_c_str()), v.to_c_str()))
-                                  .collect());
+    pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)])
+                                 -> &'a mut Command
+                                 where T: BytesContainer, U: BytesContainer {
+        self.env = Some(env.iter().map(|&(ref k, ref v)| {
+            (EnvKey(CString::from_slice(k.container_as_bytes())),
+             CString::from_slice(v.container_as_bytes()))
+        }).collect());
         self
     }
 
     /// Set the working directory for the child process.
     pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
-        self.cwd = Some(dir.to_c_str());
+        self.cwd = Some(CString::from_slice(dir.as_vec()));
         self
     }
 
@@ -389,9 +400,9 @@ impl fmt::Show for Command {
     /// non-utf8 data is lossily converted using the utf8 replacement
     /// character.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes_no_nul())));
+        try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes())));
         for arg in self.args.iter() {
-            try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes_no_nul())));
+            try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes())));
         }
         Ok(())
     }
@@ -1208,13 +1219,13 @@ fn dont_close_fd_on_command_spawn() {
     #[test]
     #[cfg(windows)]
     fn env_map_keys_ci() {
-        use c_str::ToCStr;
+        use ffi::CString;
         use super::EnvKey;
         let mut cmd = Command::new("");
         cmd.env("path", "foo");
         cmd.env("Path", "bar");
         let env = &cmd.env.unwrap();
-        let val = env.get(&EnvKey("PATH".to_c_str()));
-        assert!(val.unwrap() == &"bar".to_c_str());
+        let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
+        assert!(val.unwrap() == &CString::from_slice(b"bar"));
     }
 }
index 45e0dd4e8e5dfd7fa5871871a59e21dd89c39f85..394686be814f24c593ce5c72080c6164c1fbc6be 100644 (file)
 
 //! Temporary files and directories
 
-use io::{fs, IoResult};
+use io::{fs, IoError, IoErrorKind, IoResult};
 use io;
-use libc;
+use iter::{IteratorExt, range};
 use ops::Drop;
 use option::Option;
 use option::Option::{None, Some};
 use os;
 use path::{Path, GenericPath};
+use rand::{Rng, thread_rng};
 use result::Result::{Ok, Err};
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use str::StrExt;
+use string::String;
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-based deletion.
@@ -31,7 +33,7 @@
 ///
 /// {
 ///     // create a temporary directory
-///     let tmpdir = match TempDir::new("mysuffix") {
+///     let tmpdir = match TempDir::new("myprefix") {
 ///         Ok(dir) => dir,
 ///         Err(e) => panic!("couldn't create temporary directory: {}", e)
 ///     };
@@ -46,7 +48,7 @@
 /// }
 /// {
 ///     // create a temporary directory, this time using a custom path
-///     let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "mysuffix") {
+///     let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "myprefix") {
 ///         Ok(dir) => dir,
 ///         Err(e) => panic!("couldn't create temporary directory: {}", e)
 ///     };
@@ -61,7 +63,7 @@
 /// }
 /// {
 ///     // create a temporary directory
-///     let tmpdir = match TempDir::new("mysuffix") {
+///     let tmpdir = match TempDir::new("myprefix") {
 ///         Ok(dir) => dir,
 ///         Err(e) => panic!("couldn't create temporary directory: {}", e)
 ///     };
@@ -78,47 +80,59 @@ pub struct TempDir {
     disarmed: bool
 }
 
+// How many times should we (re)try finding an unused random name? It should be
+// enough that an attacker will run out of luck before we run out of patience.
+const NUM_RETRIES: u32 = 1 << 31;
+// How many characters should we include in a random file name? It needs to
+// be enough to dissuade an attacker from trying to preemptively create names
+// of that length, but not so huge that we unnecessarily drain the random number
+// generator of entropy.
+const NUM_RAND_CHARS: uint = 12;
+
 impl TempDir {
     /// Attempts to make a temporary directory inside of `tmpdir` whose name
-    /// will have the suffix `suffix`. The directory will be automatically
+    /// will have the prefix `prefix`. The directory will be automatically
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
-    pub fn new_in(tmpdir: &Path, suffix: &str) -> IoResult<TempDir> {
+    pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
         if !tmpdir.is_absolute() {
             let abs_tmpdir = try!(os::make_absolute(tmpdir));
-            return TempDir::new_in(&abs_tmpdir, suffix);
+            return TempDir::new_in(&abs_tmpdir, prefix);
         }
 
-        static CNT: AtomicUint = ATOMIC_UINT_INIT;
-
-        let mut attempts = 0u;
-        loop {
-            let filename =
-                format!("rs-{}-{}-{}",
-                        unsafe { libc::getpid() },
-                        CNT.fetch_add(1, Ordering::SeqCst),
-                        suffix);
-            let p = tmpdir.join(filename);
-            match fs::mkdir(&p, io::USER_RWX) {
-                Err(error) => {
-                    if attempts >= 1000 {
-                        return Err(error)
-                    }
-                    attempts += 1;
-                }
-                Ok(()) => return Ok(TempDir { path: Some(p), disarmed: false })
+        let mut rng = thread_rng();
+        for _ in range(0, NUM_RETRIES) {
+            let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
+            let leaf = if prefix.len() > 0 {
+                format!("{}.{}", prefix, suffix)
+            } else {
+                // If we're given an empty string for a prefix, then creating a
+                // directory starting with "." would lead to it being
+                // semi-invisible on some systems.
+                suffix
+            };
+            let path = tmpdir.join(leaf);
+            match fs::mkdir(&path, io::USER_RWX) {
+                Ok(_) => return Ok(TempDir { path: Some(path), disarmed: false }),
+                Err(IoError{kind:IoErrorKind::PathAlreadyExists,..}) => (),
+                Err(e) => return Err(e)
             }
         }
+
+        return Err(IoError{
+                       kind: IoErrorKind::PathAlreadyExists,
+                       desc:"Exhausted",
+                       detail: None});
     }
 
     /// Attempts to make a temporary directory inside of `os::tmpdir()` whose
-    /// name will have the suffix `suffix`. The directory will be automatically
+    /// name will have the prefix `prefix`. The directory will be automatically
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
-    pub fn new(suffix: &str) -> IoResult<TempDir> {
-        TempDir::new_in(&os::tmpdir(), suffix)
+    pub fn new(prefix: &str) -> IoResult<TempDir> {
+        TempDir::new_in(&os::tmpdir(), prefix)
     }
 
     /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
index 608ad9882b97719fe487fdcd08b510d49fb82c73..2d3a4639379cfe36276b2e6505c1f611fe4e2d09 100644 (file)
 
 /* Runtime and platform support */
 
-pub mod thread_local;
-pub mod c_str;
-pub mod c_vec;
+pub mod thread_local; // first for macros
+
 pub mod dynamic_lib;
+pub mod ffi;
 pub mod fmt;
 pub mod io;
 pub mod os;
index 63fd3209cc0193b619f811373be8f97886f57781..fb2d23b01b4644c990baaa0d4fa6e481bc198586 100644 (file)
@@ -33,7 +33,7 @@
 /// # #![allow(unreachable_code)]
 /// panic!();
 /// panic!("this is a terrible mistake!");
-/// panic!(4i); // panic with the value of 4 to be collected elsewhere
+/// panic!(4); // panic with the value of 4 to be collected elsewhere
 /// panic!("this is a {} {message}", "fancy", message = "message");
 /// ```
 #[macro_export]
@@ -74,7 +74,7 @@ macro_rules! panic {
 /// // assert with a custom message
 /// # let x = true;
 /// assert!(x, "x wasn't true!");
-/// # let a = 3i; let b = 27i;
+/// # let a = 3; let b = 27;
 /// assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
@@ -99,8 +99,8 @@ macro_rules! assert {
 /// # Example
 ///
 /// ```
-/// let a = 3i;
-/// let b = 1i + 2i;
+/// let a = 3;
+/// let b = 1 + 2;
 /// assert_eq!(a, b);
 /// ```
 #[macro_export]
@@ -141,7 +141,7 @@ macro_rules! assert_eq {
 /// // assert with a custom message
 /// # let x = true;
 /// debug_assert!(x, "x wasn't true!");
-/// # let a = 3i; let b = 27i;
+/// # let a = 3; let b = 27;
 /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
@@ -162,8 +162,8 @@ macro_rules! debug_assert {
 /// # Example
 ///
 /// ```
-/// let a = 3i;
-/// let b = 1i + 2i;
+/// let a = 3;
+/// let b = 1 + 2;
 /// debug_assert_eq!(a, b);
 /// ```
 #[macro_export]
@@ -238,7 +238,7 @@ macro_rules! unimplemented {
 /// ```
 /// format!("test");
 /// format!("hello {}", "world!");
-/// format!("x = {}, y = {y}", 10i, y = 30i);
+/// format!("x = {}, y = {y}", 10, y = 30);
 /// ```
 #[macro_export]
 #[stable]
@@ -338,7 +338,7 @@ macro_rules! vec {
 /// let (tx1, rx1) = channel();
 /// let (tx2, rx2) = channel();
 /// # fn long_running_task() {}
-/// # fn calculate_the_answer() -> int { 42i }
+/// # fn calculate_the_answer() -> int { 42 }
 ///
 /// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach();
 /// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach();
@@ -507,7 +507,7 @@ macro_rules! concat_idents {
     /// # Example
     ///
     /// ```
-    /// let s = concat!("test", 10i, 'b', true);
+    /// let s = concat!("test", 10, 'b', true);
     /// assert_eq!(s, "test10btrue");
     /// ```
     #[macro_export]
index 20dd70f0faab2ff756a6a3c8c757731ab77cdc9d..67fe599ecd6bfcbfe588a06620d64748fa16bd8a 100644 (file)
@@ -16,7 +16,7 @@
 use self::SignificantDigits::*;
 use self::SignFormat::*;
 
-use char::{self, Char};
+use char::{self, CharExt};
 use num::{self, Int, Float, ToPrimitive};
 use num::FpCategory as Fp;
 use ops::FnMut;
index be8f82349c2224496729c0adb2060dc888ff5a35..300ceec4b45bf3a047a54a0947a29395cd8accc3 100644 (file)
 use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
 use vec::Vec;
 
-#[cfg(unix)] use c_str::ToCStr;
+#[cfg(unix)] use ffi::{self, CString};
 
-#[cfg(unix)]
-pub use sys::ext as unix;
-#[cfg(windows)]
-pub use sys::ext as windows;
+#[cfg(unix)] pub use sys::ext as unix;
+#[cfg(windows)] pub use sys::ext as windows;
 
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
@@ -196,15 +194,14 @@ pub fn getenv(n: &str) -> Option<String> {
 ///
 /// Panics if `n` has any interior NULs.
 pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
-    use c_str::CString;
-
     unsafe {
         with_env_lock(|| {
-            let s = n.with_c_str(|buf| libc::getenv(buf));
+            let s = CString::from_slice(n.as_bytes());
+            let s = libc::getenv(s.as_ptr()) as *const _;
             if s.is_null() {
                 None
             } else {
-                Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec())
+                Some(ffi::c_str_to_bytes(&s).to_vec())
             }
         })
     }
@@ -253,13 +250,12 @@ pub fn setenv<T: BytesContainer>(n: &str, v: T) {
     fn _setenv(n: &str, v: &[u8]) {
         unsafe {
             with_env_lock(|| {
-                n.with_c_str(|nbuf| {
-                    v.with_c_str(|vbuf| {
-                        if libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1) != 0 {
-                            panic!(IoError::last_error());
-                        }
-                    })
-                })
+                let k = CString::from_slice(n.as_bytes());
+                let v = CString::from_slice(v);
+                if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
+                                                        v.as_ptr(), 1) != 0 {
+                    panic!(IoError::last_error());
+                }
             })
         }
     }
@@ -289,11 +285,10 @@ pub fn unsetenv(n: &str) {
     fn _unsetenv(n: &str) {
         unsafe {
             with_env_lock(|| {
-                n.with_c_str(|nbuf| {
-                    if libc::funcs::posix01::unistd::unsetenv(nbuf) != 0 {
-                        panic!(IoError::last_error());
-                    }
-                })
+                let nbuf = CString::from_slice(n.as_bytes());
+                if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
+                    panic!(IoError::last_error());
+                }
             })
         }
     }
@@ -618,11 +613,10 @@ pub fn get_exit_status() -> int {
 #[cfg(target_os = "macos")]
 unsafe fn load_argc_and_argv(argc: int,
                              argv: *const *const c_char) -> Vec<Vec<u8>> {
-    use c_str::CString;
     use iter::range;
 
     range(0, argc as uint).map(|i| {
-        CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec()
+        ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
     }).collect()
 }
 
@@ -652,7 +646,6 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
 // res
 #[cfg(target_os = "ios")]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use c_str::CString;
     use iter::range;
     use mem;
 
index bf9ffbffe7d508b1f26bd331875b71493222943c..2f014872402cf2d794d145342130e58eb9a072d0 100644 (file)
@@ -62,7 +62,7 @@
 #![experimental]
 
 use core::kinds::Sized;
-use c_str::CString;
+use ffi::CString;
 use clone::Clone;
 use fmt;
 use iter::IteratorExt;
@@ -892,7 +892,7 @@ fn container_as_bytes(&self) -> &[u8] {
 impl BytesContainer for CString {
     #[inline]
     fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_bytes_no_nul()
+        self.as_bytes()
     }
 }
 
@@ -913,21 +913,3 @@ fn is_str(_: Option<& &'a T>) -> bool { BytesContainer::is_str(None::<&T>) }
 fn contains_nul<T: BytesContainer>(v: &T) -> bool {
     v.container_as_bytes().iter().any(|&x| x == 0)
 }
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-    use c_str::ToCStr;
-    use path::{WindowsPath, PosixPath};
-
-    #[test]
-    fn test_cstring() {
-        let input = "/foo/bar/baz";
-        let path: PosixPath = PosixPath::new(input.to_c_str());
-        assert_eq!(path.as_vec(), input.as_bytes());
-
-        let input = r"\foo\bar\baz";
-        let path: WindowsPath = WindowsPath::new(input.to_c_str());
-        assert_eq!(path.as_str().unwrap(), input);
-    }
-}
index ae82e201cb8555793b4f33efd2366c98fecfad5e..013212b27058c3d0168175de08643680141b46c7 100644 (file)
 
 //! POSIX file path handling
 
-use c_str::{CString, ToCStr};
 use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
 use hash;
 use io::Writer;
 use iter::{AdditiveIterator, Extend};
 use iter::{Iterator, IteratorExt, Map};
-use option::Option;
-use option::Option::{None, Some};
 use kinds::Sized;
-use str::{FromStr, Str};
-use str;
-use slice::{Split, AsSlice, SliceConcatExt, SliceExt};
+use option::Option::{self, Some, None};
+use slice::{AsSlice, Split, SliceExt, SliceConcatExt};
+use str::{self, FromStr, StrExt};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
@@ -86,26 +83,6 @@ fn from_str(s: &str) -> Option<Path> {
     }
 }
 
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        // The Path impl guarantees no internal NUL
-        unsafe { self.to_c_str_unchecked() }
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_vec().to_c_str_unchecked()
-    }
-}
-
 impl<S: hash::Writer> hash::Hash<S> for Path {
     #[inline]
     fn hash(&self, state: &mut S) {
index aae8d6cadefb22935ae2e876548392cf11593b7e..05129a7ab9da3988c352337e8980c836caec8521 100644 (file)
 use self::PathPrefix::*;
 
 use ascii::AsciiExt;
-use c_str::{CString, ToCStr};
+use char::CharExt;
 use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
 use hash;
 use io::Writer;
 use iter::{AdditiveIterator, Extend};
 use iter::{Iterator, IteratorExt, Map, repeat};
 use mem;
-use option::Option;
-use option::Option::{Some, None};
+use option::Option::{self, Some, None};
 use slice::{SliceExt, SliceConcatExt};
 use str::{SplitTerminator, FromStr, StrExt};
 use string::{String, ToString};
-use unicode::char::UnicodeChar;
 use vec::Vec;
 
 use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
@@ -112,26 +110,6 @@ fn from_str(s: &str) -> Option<Path> {
     }
 }
 
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
-    #[inline]
-    fn to_c_str(&self) -> CString {
-        // The Path impl guarantees no internal NUL
-        unsafe { self.to_c_str_unchecked() }
-    }
-
-    #[inline]
-    unsafe fn to_c_str_unchecked(&self) -> CString {
-        self.as_vec().to_c_str_unchecked()
-    }
-}
-
 impl<S: hash::Writer> hash::Hash<S> for Path {
     #[cfg(not(test))]
     #[inline]
index a122cb81b8c423ed169d9259079b490ed3668f82..f6bdcd53dff24c29dd68528d1f45ebbb427e051f 100644 (file)
@@ -22,7 +22,7 @@
 // Reexported types and traits
 
 #[stable] #[doc(no_inline)] pub use boxed::Box;
-#[stable] #[doc(no_inline)] pub use char::{Char, UnicodeChar};
+#[stable] #[doc(no_inline)] pub use char::CharExt;
 #[stable] #[doc(no_inline)] pub use clone::Clone;
 #[stable] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable] #[doc(no_inline)] pub use iter::CloneIteratorExt;
index aa28c8266d193ff059562f9c7509b933ee454c92..cadaae5de5c206a4e0b60d0e7a0e23df70aa87ca 100644 (file)
 
 /// The standard RNG. This is designed to be efficient on the current
 /// platform.
-#[derive(Copy)]
+#[deriving(Copy, Clone)]
 pub struct StdRng {
     rng: IsaacWordRng,
 }
@@ -322,6 +322,7 @@ fn reseed(&mut self, rng: &mut StdRng) {
 type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
 
 /// The thread-local RNG.
+#[deriving(Clone)]
 pub struct ThreadRng {
     rng: Rc<RefCell<ThreadRngInner>>,
 }
index 4734a39c8354257a6fa21ed236160c8f42b964e5..86abacb936501f63124755cd6baeef981c9c7474 100644 (file)
@@ -46,8 +46,9 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
 mod imp {
     use prelude::v1::*;
 
+    use libc;
     use mem;
-    use slice;
+    use ffi;
 
     use sync::{StaticMutex, MUTEX_INIT};
 
@@ -95,13 +96,9 @@ fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
     }
 
     unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+        let argv = argv as *const *const libc::c_char;
         range(0, argc as uint).map(|i| {
-            let arg = *argv.offset(i as int);
-            let mut len = 0u;
-            while *arg.offset(len as int) != 0 {
-                len += 1u;
-            }
-            slice::from_raw_buf(&arg, len).to_vec()
+            ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
         }).collect()
     }
 
index 578239c9cc42ee7237980ca00a840d6888e28414..bb0b6fe804bea4e676c0520cee80d4539c8b95e6 100644 (file)
@@ -15,7 +15,7 @@
 use prelude::v1::*;
 
 use os;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 
 pub use sys::backtrace::write;
 
index a48a8edd82f60224e86a8cb53e14976c1ca069ae..71169386c186aee9400b363232787cf25c4a64af 100644 (file)
@@ -67,7 +67,7 @@
 use intrinsics;
 use libc::c_void;
 use mem;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 use sync::{Once, ONCE_INIT};
 
 use rt::libunwind as uw;
index 883a01fa31801bebb237d1c6de79b64a6c32ff13..bc01ce926f8bc4306c43732cfdc51f8a546506af 100644 (file)
@@ -19,7 +19,7 @@
 use os;
 use slice;
 use str;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 
 /// Dynamically inquire about whether we're running under V.
 /// You should usually not use this unless your test definitely
index de1724cbc4e89fbaf3f3c2255d1c0cdb9c950537..338cadafff724e2de23b7832cf8d69535d1e7f5b 100644 (file)
@@ -8,7 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Multi-producer, single-consumer communication primitives threads
+//! Communication primitives for concurrent tasks
+//!
+//! Rust makes it very difficult to share data among tasks to prevent race
+//! conditions and to improve parallelism, but there is often a need for
+//! communication between concurrent tasks. The primitives defined in this
+//! module are the building blocks for synchronization in rust.
 //!
 //! This module provides message-based communication over channels, concretely
 //! defined among three types:
 //! * `Receiver`
 //!
 //! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
-//! senders are clone-able (multi-producer) such that many threads can send
-//! simultaneously to one receiver (single-consumer).  These channels are
+//! senders are clone-able such that many tasks can send simultaneously to one
+//! receiver.  These channels are *task blocking*, not *thread blocking*. This
+//! means that if one task is blocked on a channel, other tasks can continue to
+//! make progress.
 //!
-//! These channels come in two flavors:
+//! Rust channels come in one of two flavors:
 //!
 //! 1. An asynchronous, infinitely buffered channel. The `channel()` function
 //!    will return a `(Sender, Receiver)` tuple where all sends will be
 //!    "rendezvous" channel where each sender atomically hands off a message to
 //!    a receiver.
 //!
-//! ## Disconnection
+//! ## Panic Propagation
 //!
-//! The send and receive operations on channels will all return a `Result`
-//! indicating whether the operation succeeded or not. An unsuccessful operation
-//! is normally indicative of the other half of a channel having "hung up" by
-//! being dropped in its corresponding thread.
+//! In addition to being a core primitive for communicating in rust, channels
+//! are the points at which panics are propagated among tasks.  Whenever the one
+//! half of channel is closed, the other half will have its next operation
+//! `panic!`. The purpose of this is to allow propagation of panics among tasks
+//! that are linked to one another via channels.
 //!
-//! Once half of a channel has been deallocated, most operations can no longer
-//! continue to make progress, so `Err` will be returned. Many applications will
-//! continue to `unwrap()` the results returned from this module, instigating a
-//! propagation of failure among threads if one unexpectedly dies.
+//! There are methods on both of senders and receivers to perform their
+//! respective operations without panicking, however.
 //!
-//! # Examples
+//! # Example
 //!
 //! Simple usage:
 //!
 //! ```
 //! use std::thread::Thread;
-//! use std::sync::mpsc::channel;
 //!
 //! // Create a simple streaming channel
 //! let (tx, rx) = channel();
 //! Thread::spawn(move|| {
-//!     tx.send(10i).unwrap();
+//!     tx.send(10);
 //! }).detach();
-//! assert_eq!(rx.recv().unwrap(), 10i);
+//! assert_eq!(rx.recv(), 10);
 //! ```
 //!
 //! Shared usage:
 //!
 //! ```
 //! use std::thread::Thread;
-//! use std::sync::mpsc::channel;
 //!
 //! // Create a shared channel that can be sent along from many threads
 //! // where tx is the sending half (tx for transmission), and rx is the receiving
 //! for i in range(0i, 10i) {
 //!     let tx = tx.clone();
 //!     Thread::spawn(move|| {
-//!         tx.send(i).unwrap();
+//!         tx.send(i);
 //!     }).detach()
 //! }
 //!
 //! for _ in range(0i, 10i) {
-//!     let j = rx.recv().unwrap();
+//!     let j = rx.recv();
 //!     assert!(0 <= j && j < 10);
 //! }
 //! ```
 //!
 //! Propagating panics:
 //!
-//! ```
-//! use std::sync::mpsc::channel;
-//!
-//! // The call to recv() will return an error because the channel has already
-//! // hung up (or been deallocated)
+//! ```should_fail
+//! // The call to recv() will panic!() because the channel has already hung
+//! // up (or been deallocated)
 //! let (tx, rx) = channel::<int>();
 //! drop(tx);
-//! assert!(rx.recv().is_err());
+//! rx.recv();
 //! ```
 //!
 //! Synchronous channels:
 //!
 //! ```
 //! use std::thread::Thread;
-//! use std::sync::mpsc::sync_channel;
 //!
 //! let (tx, rx) = sync_channel::<int>(0);
 //! Thread::spawn(move|| {
 //!     // This will wait for the parent task to start receiving
-//!     tx.send(53).unwrap();
+//!     tx.send(53);
 //! }).detach();
-//! rx.recv().unwrap();
+//! rx.recv();
 //! ```
 //!
 //! Reading from a channel with a timeout requires to use a Timer together
 //! after 10 seconds no matter what:
 //!
 //! ```no_run
-//! use std::sync::mpsc::channel;
 //! use std::io::timer::Timer;
 //! use std::time::Duration;
 //!
 //!
 //! loop {
 //!     select! {
-//!         val = rx.recv() => println!("Received {}", val.unwrap()),
-//!         _ = timeout.recv() => {
+//!         val = rx.recv() => println!("Received {}", val),
+//!         () = timeout.recv() => {
 //!             println!("timed out, total time was more than 10 seconds");
 //!             break;
 //!         }
 //! has been inactive for 5 seconds:
 //!
 //! ```no_run
-//! use std::sync::mpsc::channel;
 //! use std::io::timer::Timer;
 //! use std::time::Duration;
 //!
 //!     let timeout = timer.oneshot(Duration::seconds(5));
 //!
 //!     select! {
-//!         val = rx.recv() => println!("Received {}", val.unwrap()),
-//!         _ = timeout.recv() => {
+//!         val = rx.recv() => println!("Received {}", val),
+//!         () = timeout.recv() => {
 //!             println!("timed out, no message received in 5 seconds");
 //!             break;
 //!         }
 // And now that you've seen all the races that I found and attempted to fix,
 // here's the code for you to find some more!
 
-use prelude::v1::*;
+use core::prelude::*;
 
-use sync::Arc;
-use fmt;
-use kinds::marker;
-use mem;
-use cell::UnsafeCell;
+pub use self::TryRecvError::*;
+pub use self::TrySendError::*;
+
+use alloc::arc::Arc;
+use core::kinds;
+use core::kinds::marker;
+use core::mem;
+use core::cell::UnsafeCell;
 
 pub use self::select::{Select, Handle};
 use self::select::StartResult;
 use self::select::StartResult::*;
 use self::blocking::SignalToken;
 
+macro_rules! test {
+    { fn $name:ident() $b:block $(#[$a:meta])*} => (
+        mod $name {
+            #![allow(unused_imports)]
+
+            use super::*;
+            use comm::*;
+            use thread::Thread;
+            use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option};
+            use prelude::{Vec, Buffer, from_str, Clone};
+
+            $(#[$a])* #[test] fn f() { $b }
+        }
+    )
+}
+
 mod blocking;
 mod oneshot;
 mod select;
 
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
-#[stable]
+#[unstable]
 pub struct Receiver<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
@@ -349,14 +367,14 @@ unsafe impl<T:Send> Send for Receiver<T> { }
 /// An iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
-#[stable]
-pub struct Iter<'a, T:'a> {
+#[unstable]
+pub struct Messages<'a, T:'a> {
     rx: &'a Receiver<T>
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
-#[stable]
+#[unstable]
 pub struct Sender<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
@@ -367,50 +385,30 @@ unsafe impl<T:Send> Send for Sender<T> { }
 
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
-#[stable]
+#[unstable = "this type may be renamed, but it will always exist"]
 pub struct SyncSender<T> {
     inner: Arc<RacyCell<sync::Packet<T>>>,
     // can't share in an arc
     _marker: marker::NoSync,
 }
 
-/// An error returned from the `send` function on channels.
-///
-/// A `send` operation can only fail if the receiving end of a channel is
-/// disconnected, implying that the data could never be received. The error
-/// contains the data being sent as a payload so it can be recovered.
-#[derive(PartialEq, Eq)]
-#[stable]
-pub struct SendError<T>(pub T);
-
-/// An error returned from the `recv` function on a `Receiver`.
-///
-/// The `recv` operation can only fail if the sending half of a channel is
-/// disconnected, implying that no further messages will ever be received.
-#[derive(PartialEq, Eq, Clone, Copy)]
-#[stable]
-pub struct RecvError;
-
 /// This enumeration is the list of the possible reasons that try_recv could not
 /// return data when called.
-#[derive(PartialEq, Clone, Copy)]
-#[stable]
+#[deriving(PartialEq, Clone, Copy, Show)]
+#[experimental = "this is likely to be removed in changing try_recv()"]
 pub enum TryRecvError {
     /// This channel is currently empty, but the sender(s) have not yet
     /// disconnected, so data may yet become available.
-    #[stable]
     Empty,
-
     /// This channel's sending half has become disconnected, and there will
     /// never be any more data received on this channel
-    #[stable]
     Disconnected,
 }
 
 /// This enumeration is the list of the possible error outcomes for the
 /// `SyncSender::try_send` method.
-#[derive(PartialEq, Clone)]
-#[stable]
+#[deriving(PartialEq, Clone, Show)]
+#[experimental = "this is likely to be removed in changing try_send()"]
 pub enum TrySendError<T> {
     /// The data could not be sent on the channel because it would require that
     /// the callee block to send the data.
@@ -418,13 +416,10 @@ pub enum TrySendError<T> {
     /// If this is a buffered channel, then the buffer is full at this time. If
     /// this is not a buffered channel, then there is no receiver available to
     /// acquire the data.
-    #[stable]
     Full(T),
-
     /// This channel's receiving half has disconnected, so the data could not be
     /// sent. The data is returned back to the callee in this case.
-    #[stable]
-    Disconnected(T),
+    RecvDisconnected(T),
 }
 
 enum Flavor<T> {
@@ -463,7 +458,6 @@ fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
 /// # Example
 ///
 /// ```
-/// use std::sync::mpsc::channel;
 /// use std::thread::Thread;
 ///
 /// // tx is is the sending half (tx for transmission), and rx is the receiving
@@ -473,15 +467,15 @@ fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
 /// // Spawn off an expensive computation
 /// Thread::spawn(move|| {
 /// #   fn expensive_computation() {}
-///     tx.send(expensive_computation()).unwrap();
+///     tx.send(expensive_computation());
 /// }).detach();
 ///
 /// // Do some useful work for awhile
 ///
 /// // Let's see what that answer was
-/// println!("{}", rx.recv().unwrap());
+/// println!("{}", rx.recv());
 /// ```
-#[stable]
+#[unstable]
 pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
@@ -505,23 +499,23 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 /// # Example
 ///
 /// ```
-/// use std::sync::mpsc::sync_channel;
 /// use std::thread::Thread;
 ///
 /// let (tx, rx) = sync_channel(1);
 ///
 /// // this returns immediately
-/// tx.send(1i).unwrap();
+/// tx.send(1);
 ///
 /// Thread::spawn(move|| {
 ///     // this will block until the previous message has been received
-///     tx.send(2i).unwrap();
+///     tx.send(2);
 /// }).detach();
 ///
-/// assert_eq!(rx.recv().unwrap(), 1i);
-/// assert_eq!(rx.recv().unwrap(), 2i);
+/// assert_eq!(rx.recv(), 1);
+/// assert_eq!(rx.recv(), 2);
 /// ```
-#[stable]
+#[unstable = "this function may be renamed to more accurately reflect the type \
+              of channel that is is creating"]
 pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
     let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
     (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
@@ -538,6 +532,33 @@ fn new(inner: Flavor<T>) -> Sender<T> {
         }
     }
 
+    /// Sends a value along this channel to be received by the corresponding
+    /// receiver.
+    ///
+    /// Rust channels are infinitely buffered so this method will never block.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the other end of the channel has hung up.
+    /// This means that if the corresponding receiver has fallen out of scope,
+    /// this function will trigger a panic message saying that a message is
+    /// being sent on a closed channel.
+    ///
+    /// Note that if this function does *not* panic, it does not mean that the
+    /// data will be successfully received. All sends are placed into a queue,
+    /// so it is possible for a send to succeed (the other end is alive), but
+    /// then the other end could immediately disconnect.
+    ///
+    /// The purpose of this functionality is to propagate panics among tasks.
+    /// If a panic is not desired, then consider using the `send_opt` method
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn send(&self, t: T) {
+        if self.send_opt(t).is_err() {
+            panic!("sending on a closed channel");
+        }
+    }
+
     /// Attempts to send a value on this channel, returning it back if it could
     /// not be sent.
     ///
@@ -549,34 +570,37 @@ fn new(inner: Flavor<T>) -> Sender<T> {
     /// will be received.  It is possible for the corresponding receiver to
     /// hang up immediately after this function returns `Ok`.
     ///
-    /// This method will never block the current thread.
+    /// Like `send`, this method will never block.
+    ///
+    /// # Panics
+    ///
+    /// This method will never panic, it will return the message back to the
+    /// caller if the other end is disconnected
     ///
     /// # Example
     ///
     /// ```
-    /// use std::sync::mpsc::channel;
-    ///
     /// let (tx, rx) = channel();
     ///
     /// // This send is always successful
-    /// tx.send(1i).unwrap();
+    /// assert_eq!(tx.send_opt(1), Ok(()));
     ///
     /// // This send will fail because the receiver is gone
     /// drop(rx);
-    /// assert_eq!(tx.send(1i).err().unwrap().0, 1);
+    /// assert_eq!(tx.send_opt(1), Err(1));
     /// ```
-    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
+    #[unstable = "this function may be renamed to send() in the future"]
+    pub fn send_opt(&self, t: T) -> Result<(), T> {
         let (new_inner, ret) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
                 unsafe {
                     let p = p.get();
                     if !(*p).sent() {
-                        return (*p).send(t).map_err(SendError);
+                        return (*p).send(t);
                     } else {
                         let a =
                             Arc::new(RacyCell::new(stream::Packet::new()));
-                        let rx = Receiver::new(Flavor::Stream(a.clone()));
-                        match (*p).upgrade(rx) {
+                        match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) {
                             oneshot::UpSuccess => {
                                 let ret = (*a.get()).send(t);
                                 (a, ret)
@@ -594,12 +618,8 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
                     }
                 }
             }
-            Flavor::Stream(ref p) => return unsafe {
-                (*p.get()).send(t).map_err(SendError)
-            },
-            Flavor::Shared(ref p) => return unsafe {
-                (*p.get()).send(t).map_err(SendError)
-            },
+            Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) },
+            Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) },
             Flavor::Sync(..) => unreachable!(),
         };
 
@@ -607,7 +627,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
             let tmp = Sender::new(Flavor::Stream(new_inner));
             mem::swap(self.inner_mut(), tmp.inner_mut());
         }
-        ret.map_err(SendError)
+        return ret;
     }
 }
 
@@ -619,8 +639,7 @@ fn clone(&self) -> Sender<T> {
                 let a = Arc::new(RacyCell::new(shared::Packet::new()));
                 unsafe {
                     let guard = (*a.get()).postinit_lock();
-                    let rx = Receiver::new(Flavor::Shared(a.clone()));
-                    match (*p.get()).upgrade(rx) {
+                    match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) {
                         oneshot::UpSuccess |
                         oneshot::UpDisconnected => (a, None, guard),
                         oneshot::UpWoke(task) => (a, Some(task), guard)
@@ -631,8 +650,7 @@ fn clone(&self) -> Sender<T> {
                 let a = Arc::new(RacyCell::new(shared::Packet::new()));
                 unsafe {
                     let guard = (*a.get()).postinit_lock();
-                    let rx = Receiver::new(Flavor::Shared(a.clone()));
-                    match (*p.get()).upgrade(rx) {
+                    match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) {
                         stream::UpSuccess |
                         stream::UpDisconnected => (a, None, guard),
                         stream::UpWoke(task) => (a, Some(task), guard),
@@ -683,29 +701,59 @@ fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
     /// available or a receiver is available to hand off the message to.
     ///
     /// Note that a successful send does *not* guarantee that the receiver will
-    /// ever see the data if there is a buffer on this channel. Items may be
+    /// ever see the data if there is a buffer on this channel. Messages may be
     /// enqueued in the internal buffer for the receiver to receive at a later
     /// time. If the buffer size is 0, however, it can be guaranteed that the
     /// receiver has indeed received the data if this function returns success.
     ///
-    /// This function will never panic, but it may return `Err` if the
-    /// `Receiver` has disconnected and is no longer able to receive
-    /// information.
-    #[stable]
-    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
-        unsafe { (*self.inner.get()).send(t).map_err(SendError) }
+    /// # Panics
+    ///
+    /// Similarly to `Sender::send`, this function will panic if the
+    /// corresponding `Receiver` for this channel has disconnected. This
+    /// behavior is used to propagate panics among tasks.
+    ///
+    /// If a panic is not desired, you can achieve the same semantics with the
+    /// `SyncSender::send_opt` method which will not panic if the receiver
+    /// disconnects.
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn send(&self, t: T) {
+        if self.send_opt(t).is_err() {
+            panic!("sending on a closed channel");
+        }
+    }
+
+    /// Send a value on a channel, returning it back if the receiver
+    /// disconnected
+    ///
+    /// This method will *block* to send the value `t` on the channel, but if
+    /// the value could not be sent due to the receiver disconnecting, the value
+    /// is returned back to the callee. This function is similar to `try_send`,
+    /// except that it will block if the channel is currently full.
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic.
+    #[unstable = "this function may be renamed to send() in the future"]
+    pub fn send_opt(&self, t: T) -> Result<(), T> {
+        unsafe { (*self.inner.get()).send(t) }
     }
 
     /// Attempts to send a value on this channel without blocking.
     ///
-    /// This method differs from `send` by returning immediately if the
+    /// This method differs from `send_opt` by returning immediately if the
     /// channel's buffer is full or no receiver is waiting to acquire some
-    /// data. Compared with `send`, this function has two failure cases
+    /// data. Compared with `send_opt`, this function has two failure cases
     /// instead of one (one for disconnection, one for a full buffer).
     ///
     /// See `SyncSender::send` for notes about guarantees of whether the
     /// receiver has received the data or not if this function is successful.
-    #[stable]
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic
+    #[unstable = "the return type of this function is candidate for \
+                  modification"]
     pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
         unsafe { (*self.inner.get()).try_send(t) }
     }
@@ -735,6 +783,34 @@ fn new(inner: Flavor<T>) -> Receiver<T> {
         Receiver { inner: UnsafeCell::new(inner) }
     }
 
+    /// Blocks waiting for a value on this receiver
+    ///
+    /// This function will block if necessary to wait for a corresponding send
+    /// on the channel from its paired `Sender` structure. This receiver will
+    /// be woken up when data is ready, and the data will be returned.
+    ///
+    /// # Panics
+    ///
+    /// Similar to channels, this method will trigger a task panic if the
+    /// other end of the channel has hung up (been deallocated). The purpose of
+    /// this is to propagate panics among tasks.
+    ///
+    /// If a panic is not desired, then there are two options:
+    ///
+    /// * If blocking is still desired, the `recv_opt` method will return `None`
+    ///   when the other end hangs up
+    ///
+    /// * If blocking is not desired, then the `try_recv` method will attempt to
+    ///   peek at a value on this receiver.
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn recv(&self) -> T {
+        match self.recv_opt() {
+            Ok(t) => t,
+            Err(()) => panic!("receiving on a closed channel"),
+        }
+    }
+
     /// Attempts to return a pending value on this receiver without blocking
     ///
     /// This method will never block the caller in order to wait for data to
@@ -743,46 +819,42 @@ fn new(inner: Flavor<T>) -> Receiver<T> {
     ///
     /// This is useful for a flavor of "optimistic check" before deciding to
     /// block on a receiver.
-    #[stable]
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic.
+    #[unstable = "the return type of this function may be altered"]
     pub fn try_recv(&self) -> Result<T, TryRecvError> {
         loop {
             let new_port = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
                     match unsafe { (*p.get()).try_recv() } {
                         Ok(t) => return Ok(t),
-                        Err(oneshot::Empty) => return Err(TryRecvError::Empty),
-                        Err(oneshot::Disconnected) => {
-                            return Err(TryRecvError::Disconnected)
-                        }
+                        Err(oneshot::Empty) => return Err(Empty),
+                        Err(oneshot::Disconnected) => return Err(Disconnected),
                         Err(oneshot::Upgraded(rx)) => rx,
                     }
                 }
                 Flavor::Stream(ref p) => {
                     match unsafe { (*p.get()).try_recv() } {
                         Ok(t) => return Ok(t),
-                        Err(stream::Empty) => return Err(TryRecvError::Empty),
-                        Err(stream::Disconnected) => {
-                            return Err(TryRecvError::Disconnected)
-                        }
+                        Err(stream::Empty) => return Err(Empty),
+                        Err(stream::Disconnected) => return Err(Disconnected),
                         Err(stream::Upgraded(rx)) => rx,
                     }
                 }
                 Flavor::Shared(ref p) => {
                     match unsafe { (*p.get()).try_recv() } {
                         Ok(t) => return Ok(t),
-                        Err(shared::Empty) => return Err(TryRecvError::Empty),
-                        Err(shared::Disconnected) => {
-                            return Err(TryRecvError::Disconnected)
-                        }
+                        Err(shared::Empty) => return Err(Empty),
+                        Err(shared::Disconnected) => return Err(Disconnected),
                     }
                 }
                 Flavor::Sync(ref p) => {
                     match unsafe { (*p.get()).try_recv() } {
                         Ok(t) => return Ok(t),
-                        Err(sync::Empty) => return Err(TryRecvError::Empty),
-                        Err(sync::Disconnected) => {
-                            return Err(TryRecvError::Disconnected)
-                        }
+                        Err(sync::Empty) => return Err(Empty),
+                        Err(sync::Disconnected) => return Err(Disconnected),
                     }
                 }
             };
@@ -793,26 +865,27 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
         }
     }
 
-    /// Attempt to wait for a value on this receiver, returning an error if the
+    /// Attempt to wait for a value on this receiver, but does not panic if the
     /// corresponding channel has hung up.
     ///
-    /// This function will always block the current thread if there is no data
-    /// available and it's possible for more data to be sent. Once a message is
-    /// sent to the corresponding `Sender`, then this receiver will wake up and
-    /// return that message.
+    /// This implementation of iterators for ports will always block if there is
+    /// not data available on the receiver, but it will not panic in the case
+    /// that the channel has been deallocated.
     ///
-    /// If the corresponding `Sender` has disconnected, or it disconnects while
-    /// this call is blocking, this call will wake up and return `Err` to
-    /// indicate that no more messages can ever be received on this channel.
-    #[stable]
-    pub fn recv(&self) -> Result<T, RecvError> {
+    /// In other words, this function has the same semantics as the `recv`
+    /// method except for the panic aspect.
+    ///
+    /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of
+    /// the value found on the receiver is returned.
+    #[unstable = "this function may be renamed to recv()"]
+    pub fn recv_opt(&self) -> Result<T, ()> {
         loop {
             let new_port = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
                     match unsafe { (*p.get()).recv() } {
                         Ok(t) => return Ok(t),
                         Err(oneshot::Empty) => return unreachable!(),
-                        Err(oneshot::Disconnected) => return Err(RecvError),
+                        Err(oneshot::Disconnected) => return Err(()),
                         Err(oneshot::Upgraded(rx)) => rx,
                     }
                 }
@@ -820,7 +893,7 @@ pub fn recv(&self) -> Result<T, RecvError> {
                     match unsafe { (*p.get()).recv() } {
                         Ok(t) => return Ok(t),
                         Err(stream::Empty) => return unreachable!(),
-                        Err(stream::Disconnected) => return Err(RecvError),
+                        Err(stream::Disconnected) => return Err(()),
                         Err(stream::Upgraded(rx)) => rx,
                     }
                 }
@@ -828,12 +901,10 @@ pub fn recv(&self) -> Result<T, RecvError> {
                     match unsafe { (*p.get()).recv() } {
                         Ok(t) => return Ok(t),
                         Err(shared::Empty) => return unreachable!(),
-                        Err(shared::Disconnected) => return Err(RecvError),
+                        Err(shared::Disconnected) => return Err(()),
                     }
                 }
-                Flavor::Sync(ref p) => return unsafe {
-                    (*p.get()).recv().map_err(|()| RecvError)
-                }
+                Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() }
             };
             unsafe {
                 mem::swap(self.inner_mut(), new_port.inner_mut());
@@ -843,9 +914,9 @@ pub fn recv(&self) -> Result<T, RecvError> {
 
     /// Returns an iterator that will block waiting for messages, but never
     /// `panic!`. It will return `None` when the channel has hung up.
-    #[stable]
-    pub fn iter(&self) -> Iter<T> {
-        Iter { rx: self }
+    #[unstable]
+    pub fn iter<'a>(&'a self) -> Messages<'a, T> {
+        Messages { rx: self }
     }
 }
 
@@ -936,10 +1007,8 @@ fn abort_selection(&self) -> bool {
 }
 
 #[unstable]
-impl<'a, T: Send> Iterator for Iter<'a, T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
+impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
+    fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
 }
 
 #[unsafe_destructor]
@@ -972,425 +1041,368 @@ unsafe fn get(&self) -> *mut T {
 
 unsafe impl<T:Send> Send for RacyCell<T> { }
 
-unsafe impl<T> Sync for RacyCell<T> { } // Oh dear
-
-impl<T> fmt::Show for SendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        "sending on a closed channel".fmt(f)
-    }
-}
-
-impl<T> fmt::Show for TrySendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            TrySendError::Full(..) => {
-                "sending on a full channel".fmt(f)
-            }
-            TrySendError::Disconnected(..) => {
-                "sending on a closed channel".fmt(f)
-            }
-        }
-    }
-}
-
-impl fmt::Show for RecvError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        "receiving on a closed channel".fmt(f)
-    }
-}
+unsafe impl<T> kinds::Sync for RacyCell<T> { } // Oh dear
 
-impl fmt::Show for TryRecvError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            TryRecvError::Empty => {
-                "receiving on an empty channel".fmt(f)
-            }
-            TryRecvError::Disconnected => {
-                "receiving on a closed channel".fmt(f)
-            }
-        }
-    }
-}
 
 #[cfg(test)]
 mod test {
-    use prelude::v1::*;
-
-    use os;
     use super::*;
-    use thread::Thread;
+    use prelude::{spawn, range, Some, None, from_str, Clone, Str};
+    use os;
 
     pub fn stress_factor() -> uint {
         match os::getenv("RUST_TEST_STRESS") {
-            Some(val) => val.parse().unwrap(),
+            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
             None => 1,
         }
     }
 
-    #[test]
-    fn smoke() {
+    test! { fn smoke() {
         let (tx, rx) = channel::<int>();
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn drop_full() {
+    test! { fn drop_full() {
         let (tx, _rx) = channel();
-        tx.send(box 1i).unwrap();
-    }
+        tx.send(box 1i);
+    } }
 
-    #[test]
-    fn drop_full_shared() {
+    test! { fn drop_full_shared() {
         let (tx, _rx) = channel();
         drop(tx.clone());
         drop(tx.clone());
-        tx.send(box 1i).unwrap();
-    }
+        tx.send(box 1i);
+    } }
 
-    #[test]
-    fn smoke_shared() {
+    test! { fn smoke_shared() {
         let (tx, rx) = channel::<int>();
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
         let tx = tx.clone();
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn smoke_threads() {
+    test! { fn smoke_threads() {
         let (tx, rx) = channel::<int>();
-        let _t = Thread::spawn(move|| {
-            tx.send(1).unwrap();
+        spawn(move|| {
+            tx.send(1);
         });
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn smoke_port_gone() {
+    test! { fn smoke_port_gone() {
         let (tx, rx) = channel::<int>();
         drop(rx);
-        assert!(tx.send(1).is_err());
-    }
+        tx.send(1);
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_shared_port_gone() {
+    test! { fn smoke_shared_port_gone() {
         let (tx, rx) = channel::<int>();
         drop(rx);
-        assert!(tx.send(1).is_err())
-    }
+        tx.send(1);
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_shared_port_gone2() {
+    test! { fn smoke_shared_port_gone2() {
         let (tx, rx) = channel::<int>();
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
-        assert!(tx2.send(1).is_err());
-    }
+        tx2.send(1);
+    } #[should_fail] }
 
-    #[test]
-    fn port_gone_concurrent() {
+    test! { fn port_gone_concurrent() {
         let (tx, rx) = channel::<int>();
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap();
+        spawn(move|| {
+            rx.recv();
         });
-        while tx.send(1).is_ok() {}
-    }
+        loop { tx.send(1) }
+    } #[should_fail] }
 
-    #[test]
-    fn port_gone_concurrent_shared() {
+    test! { fn port_gone_concurrent_shared() {
         let (tx, rx) = channel::<int>();
         let tx2 = tx.clone();
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap();
+        spawn(move|| {
+            rx.recv();
         });
-        while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
-    }
+        loop {
+            tx.send(1);
+            tx2.send(1);
+        }
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_chan_gone() {
+    test! { fn smoke_chan_gone() {
         let (tx, rx) = channel::<int>();
         drop(tx);
-        assert!(rx.recv().is_err());
-    }
+        rx.recv();
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_chan_gone_shared() {
+    test! { fn smoke_chan_gone_shared() {
         let (tx, rx) = channel::<()>();
         let tx2 = tx.clone();
         drop(tx);
         drop(tx2);
-        assert!(rx.recv().is_err());
-    }
+        rx.recv();
+    } #[should_fail] }
 
-    #[test]
-    fn chan_gone_concurrent() {
+    test! { fn chan_gone_concurrent() {
         let (tx, rx) = channel::<int>();
-        let _t = Thread::spawn(move|| {
-            tx.send(1).unwrap();
-            tx.send(1).unwrap();
+        spawn(move|| {
+            tx.send(1);
+            tx.send(1);
         });
-        while rx.recv().is_ok() {}
-    }
+        loop { rx.recv(); }
+    } #[should_fail] }
 
-    #[test]
-    fn stress() {
+    test! { fn stress() {
         let (tx, rx) = channel::<int>();
-        let t = Thread::spawn(move|| {
-            for _ in range(0u, 10000) { tx.send(1i).unwrap(); }
+        spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1i); }
         });
         for _ in range(0u, 10000) {
-            assert_eq!(rx.recv().unwrap(), 1);
+            assert_eq!(rx.recv(), 1);
         }
-        t.join().ok().unwrap();
-    }
+    } }
 
-    #[test]
-    fn stress_shared() {
+    test! { fn stress_shared() {
         static AMT: uint = 10000;
         static NTHREADS: uint = 8;
         let (tx, rx) = channel::<int>();
+        let (dtx, drx) = channel::<()>();
 
-        let t = Thread::spawn(move|| {
+        spawn(move|| {
             for _ in range(0, AMT * NTHREADS) {
-                assert_eq!(rx.recv().unwrap(), 1);
+                assert_eq!(rx.recv(), 1);
             }
             match rx.try_recv() {
                 Ok(..) => panic!(),
                 _ => {}
             }
+            dtx.send(());
         });
 
         for _ in range(0, NTHREADS) {
             let tx = tx.clone();
-            Thread::spawn(move|| {
-                for _ in range(0, AMT) { tx.send(1).unwrap(); }
-            }).detach();
+            spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1); }
+            });
         }
         drop(tx);
-        t.join().ok().unwrap();
-    }
+        drx.recv();
+    } }
 
     #[test]
     fn send_from_outside_runtime() {
         let (tx1, rx1) = channel::<()>();
         let (tx2, rx2) = channel::<int>();
-        let t1 = Thread::spawn(move|| {
-            tx1.send(()).unwrap();
+        let (tx3, rx3) = channel::<()>();
+        let tx4 = tx3.clone();
+        spawn(move|| {
+            tx1.send(());
             for _ in range(0i, 40) {
-                assert_eq!(rx2.recv().unwrap(), 1);
+                assert_eq!(rx2.recv(), 1);
             }
+            tx3.send(());
         });
-        rx1.recv().unwrap();
-        let t2 = Thread::spawn(move|| {
+        rx1.recv();
+        spawn(move|| {
             for _ in range(0i, 40) {
-                tx2.send(1).unwrap();
+                tx2.send(1);
             }
+            tx4.send(());
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        rx3.recv();
+        rx3.recv();
     }
 
     #[test]
     fn recv_from_outside_runtime() {
         let (tx, rx) = channel::<int>();
-        let t = Thread::spawn(move|| {
+        let (dtx, drx) = channel();
+        spawn(move|| {
             for _ in range(0i, 40) {
-                assert_eq!(rx.recv().unwrap(), 1);
+                assert_eq!(rx.recv(), 1);
             }
+            dtx.send(());
         });
         for _ in range(0u, 40) {
-            tx.send(1).unwrap();
+            tx.send(1);
         }
-        t.join().ok().unwrap();
+        drx.recv();
     }
 
     #[test]
     fn no_runtime() {
         let (tx1, rx1) = channel::<int>();
         let (tx2, rx2) = channel::<int>();
-        let t1 = Thread::spawn(move|| {
-            assert_eq!(rx1.recv().unwrap(), 1);
-            tx2.send(2).unwrap();
+        let (tx3, rx3) = channel::<()>();
+        let tx4 = tx3.clone();
+        spawn(move|| {
+            assert_eq!(rx1.recv(), 1);
+            tx2.send(2);
+            tx4.send(());
         });
-        let t2 = Thread::spawn(move|| {
-            tx1.send(1).unwrap();
-            assert_eq!(rx2.recv().unwrap(), 2);
+        spawn(move|| {
+            tx1.send(1);
+            assert_eq!(rx2.recv(), 2);
+            tx3.send(());
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        rx3.recv();
+        rx3.recv();
     }
 
-    #[test]
-    fn oneshot_single_thread_close_port_first() {
+    test! { fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
         let (_tx, rx) = channel::<int>();
         drop(rx);
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_close_chan_first() {
+    test! { fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
         let (tx, _rx) = channel::<int>();
         drop(tx);
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_send_port_close() {
+    test! { fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
         let (tx, rx) = channel::<Box<int>>();
         drop(rx);
-        assert!(tx.send(box 0).is_err());
-    }
+        tx.send(box 0);
+    } #[should_fail] }
 
-    #[test]
-    fn oneshot_single_thread_recv_chan_close() {
+    test! { fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = Thread::spawn(move|| {
             let (tx, rx) = channel::<int>();
             drop(tx);
-            rx.recv().unwrap();
+            rx.recv();
         }).join();
         // What is our res?
         assert!(res.is_err());
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_send_then_recv() {
+    test! { fn oneshot_single_thread_send_then_recv() {
         let (tx, rx) = channel::<Box<int>>();
-        tx.send(box 10).unwrap();
-        assert!(rx.recv().unwrap() == box 10);
-    }
+        tx.send(box 10);
+        assert!(rx.recv() == box 10);
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_send_open() {
+    test! { fn oneshot_single_thread_try_send_open() {
         let (tx, rx) = channel::<int>();
-        assert!(tx.send(10).is_ok());
-        assert!(rx.recv().unwrap() == 10);
-    }
+        assert!(tx.send_opt(10).is_ok());
+        assert!(rx.recv() == 10);
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_send_closed() {
+    test! { fn oneshot_single_thread_try_send_closed() {
         let (tx, rx) = channel::<int>();
         drop(rx);
-        assert!(tx.send(10).is_err());
-    }
+        assert!(tx.send_opt(10).is_err());
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_recv_open() {
+    test! { fn oneshot_single_thread_try_recv_open() {
         let (tx, rx) = channel::<int>();
-        tx.send(10).unwrap();
-        assert!(rx.recv() == Ok(10));
-    }
+        tx.send(10);
+        assert!(rx.recv_opt() == Ok(10));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_recv_closed() {
+    test! { fn oneshot_single_thread_try_recv_closed() {
         let (tx, rx) = channel::<int>();
         drop(tx);
-        assert!(rx.recv().is_err());
-    }
+        assert!(rx.recv_opt() == Err(()));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_data() {
+    test! { fn oneshot_single_thread_peek_data() {
         let (tx, rx) = channel::<int>();
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
-        tx.send(10).unwrap();
+        assert_eq!(rx.try_recv(), Err(Empty));
+        tx.send(10);
         assert_eq!(rx.try_recv(), Ok(10));
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_close() {
+    test! { fn oneshot_single_thread_peek_close() {
         let (tx, rx) = channel::<int>();
         drop(tx);
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
-    }
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_open() {
+    test! { fn oneshot_single_thread_peek_open() {
         let (_tx, rx) = channel::<int>();
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
-    }
+        assert_eq!(rx.try_recv(), Err(Empty));
+    } }
 
-    #[test]
-    fn oneshot_multi_task_recv_then_send() {
+    test! { fn oneshot_multi_task_recv_then_send() {
         let (tx, rx) = channel::<Box<int>>();
-        let _t = Thread::spawn(move|| {
-            assert!(rx.recv().unwrap() == box 10);
+        spawn(move|| {
+            assert!(rx.recv() == box 10);
         });
 
-        tx.send(box 10).unwrap();
-    }
+        tx.send(box 10);
+    } }
 
-    #[test]
-    fn oneshot_multi_task_recv_then_close() {
+    test! { fn oneshot_multi_task_recv_then_close() {
         let (tx, rx) = channel::<Box<int>>();
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             drop(tx);
         });
         let res = Thread::spawn(move|| {
-            assert!(rx.recv().unwrap() == box 10);
+            assert!(rx.recv() == box 10);
         }).join();
         assert!(res.is_err());
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_close_stress() {
+    test! { fn oneshot_multi_thread_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = channel::<int>();
-            let _t = Thread::spawn(move|| {
+            spawn(move|| {
                 drop(rx);
             });
             drop(tx);
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_send_close_stress() {
+    test! { fn oneshot_multi_thread_send_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = channel::<int>();
-            let _t = Thread::spawn(move|| {
+            spawn(move|| {
                 drop(rx);
             });
             let _ = Thread::spawn(move|| {
-                tx.send(1).unwrap();
+                tx.send(1);
             }).join();
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_recv_close_stress() {
+    test! { fn oneshot_multi_thread_recv_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = channel::<int>();
-            Thread::spawn(move|| {
+            spawn(move|| {
                 let res = Thread::spawn(move|| {
-                    rx.recv().unwrap();
+                    rx.recv();
                 }).join();
                 assert!(res.is_err());
-            }).detach();
-            let _t = Thread::spawn(move|| {
-                Thread::spawn(move|| {
+            });
+            spawn(move|| {
+                spawn(move|| {
                     drop(tx);
-                }).detach();
+                });
             });
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_send_recv_stress() {
+    test! { fn oneshot_multi_thread_send_recv_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = channel();
-            let _t = Thread::spawn(move|| {
-                tx.send(box 10i).unwrap();
+            spawn(move|| {
+                tx.send(box 10i);
+            });
+            spawn(move|| {
+                assert!(rx.recv() == box 10i);
             });
-            assert!(rx.recv().unwrap() == box 10i);
         }
-    }
+    } }
 
-    #[test]
-    fn stream_send_recv_stress() {
+    test! { fn stream_send_recv_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = channel();
 
@@ -1400,73 +1412,69 @@ fn stream_send_recv_stress() {
             fn send(tx: Sender<Box<int>>, i: int) {
                 if i == 10 { return }
 
-                Thread::spawn(move|| {
-                    tx.send(box i).unwrap();
+                spawn(move|| {
+                    tx.send(box i);
                     send(tx, i + 1);
-                }).detach();
+                });
             }
 
             fn recv(rx: Receiver<Box<int>>, i: int) {
                 if i == 10 { return }
 
-                Thread::spawn(move|| {
-                    assert!(rx.recv().unwrap() == box i);
+                spawn(move|| {
+                    assert!(rx.recv() == box i);
                     recv(rx, i + 1);
-                }).detach();
+                });
             }
         }
-    }
+    } }
 
-    #[test]
-    fn recv_a_lot() {
+    test! { fn recv_a_lot() {
         // Regression test that we don't run out of stack in scheduler context
         let (tx, rx) = channel();
-        for _ in range(0i, 10000) { tx.send(()).unwrap(); }
-        for _ in range(0i, 10000) { rx.recv().unwrap(); }
-    }
+        for _ in range(0i, 10000) { tx.send(()); }
+        for _ in range(0i, 10000) { rx.recv(); }
+    } }
 
-    #[test]
-    fn shared_chan_stress() {
+    test! { fn shared_chan_stress() {
         let (tx, rx) = channel();
         let total = stress_factor() + 100;
         for _ in range(0, total) {
             let tx = tx.clone();
-            Thread::spawn(move|| {
-                tx.send(()).unwrap();
-            }).detach();
+            spawn(move|| {
+                tx.send(());
+            });
         }
 
         for _ in range(0, total) {
-            rx.recv().unwrap();
+            rx.recv();
         }
-    }
+    } }
 
-    #[test]
-    fn test_nested_recv_iter() {
+    test! { fn test_nested_recv_iter() {
         let (tx, rx) = channel::<int>();
         let (total_tx, total_rx) = channel::<int>();
 
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             let mut acc = 0;
             for x in rx.iter() {
                 acc += x;
             }
-            total_tx.send(acc).unwrap();
+            total_tx.send(acc);
         });
 
-        tx.send(3).unwrap();
-        tx.send(1).unwrap();
-        tx.send(2).unwrap();
+        tx.send(3);
+        tx.send(1);
+        tx.send(2);
         drop(tx);
-        assert_eq!(total_rx.recv().unwrap(), 6);
-    }
+        assert_eq!(total_rx.recv(), 6);
+    } }
 
-    #[test]
-    fn test_recv_iter_break() {
+    test! { fn test_recv_iter_break() {
         let (tx, rx) = channel::<int>();
         let (count_tx, count_rx) = channel();
 
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             let mut count = 0;
             for x in rx.iter() {
                 if count >= 3 {
@@ -1475,51 +1483,49 @@ fn test_recv_iter_break() {
                     count += x;
                 }
             }
-            count_tx.send(count).unwrap();
+            count_tx.send(count);
         });
 
-        tx.send(2).unwrap();
-        tx.send(2).unwrap();
-        tx.send(2).unwrap();
-        let _ = tx.send(2);
+        tx.send(2);
+        tx.send(2);
+        tx.send(2);
+        let _ = tx.send_opt(2);
         drop(tx);
-        assert_eq!(count_rx.recv().unwrap(), 4);
-    }
+        assert_eq!(count_rx.recv(), 4);
+    } }
 
-    #[test]
-    fn try_recv_states() {
+    test! { fn try_recv_states() {
         let (tx1, rx1) = channel::<int>();
         let (tx2, rx2) = channel::<()>();
         let (tx3, rx3) = channel::<()>();
-        let _t = Thread::spawn(move|| {
-            rx2.recv().unwrap();
-            tx1.send(1).unwrap();
-            tx3.send(()).unwrap();
-            rx2.recv().unwrap();
+        spawn(move|| {
+            rx2.recv();
+            tx1.send(1);
+            tx3.send(());
+            rx2.recv();
             drop(tx1);
-            tx3.send(()).unwrap();
+            tx3.send(());
         });
 
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-        tx2.send(()).unwrap();
-        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
         assert_eq!(rx1.try_recv(), Ok(1));
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-        tx2.send(()).unwrap();
-        rx3.recv().unwrap();
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected));
-    }
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Err(Disconnected));
+    } }
 
     // This bug used to end up in a livelock inside of the Receiver destructor
     // because the internal state of the Shared packet was corrupted
-    #[test]
-    fn destroy_upgraded_shared_port_when_sender_still_active() {
+    test! { fn destroy_upgraded_shared_port_when_sender_still_active() {
         let (tx, rx) = channel();
         let (tx2, rx2) = channel();
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap(); // wait on a oneshot
+        spawn(move|| {
+            rx.recv(); // wait on a oneshot
             drop(rx);  // destroy a shared
-            tx2.send(()).unwrap();
+            tx2.send(());
         });
         // make sure the other task has gone to sleep
         for _ in range(0u, 5000) { Thread::yield_now(); }
@@ -1527,334 +1533,303 @@ fn destroy_upgraded_shared_port_when_sender_still_active() {
         // upgrade to a shared chan and send a message
         let t = tx.clone();
         drop(tx);
-        t.send(()).unwrap();
+        t.send(());
 
         // wait for the child task to exit before we exit
-        rx2.recv().unwrap();
-    }
+        rx2.recv();
+    }}
 }
 
 #[cfg(test)]
 mod sync_tests {
-    use prelude::v1::*;
-
+    use prelude::*;
     use os;
-    use thread::Thread;
-    use super::*;
 
     pub fn stress_factor() -> uint {
         match os::getenv("RUST_TEST_STRESS") {
-            Some(val) => val.parse().unwrap(),
+            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
             None => 1,
         }
     }
 
-    #[test]
-    fn smoke() {
+    test! { fn smoke() {
         let (tx, rx) = sync_channel::<int>(1);
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn drop_full() {
+    test! { fn drop_full() {
         let (tx, _rx) = sync_channel(1);
-        tx.send(box 1i).unwrap();
-    }
+        tx.send(box 1i);
+    } }
 
-    #[test]
-    fn smoke_shared() {
+    test! { fn smoke_shared() {
         let (tx, rx) = sync_channel::<int>(1);
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
         let tx = tx.clone();
-        tx.send(1).unwrap();
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn smoke_threads() {
+    test! { fn smoke_threads() {
         let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| {
-            tx.send(1).unwrap();
+        spawn(move|| {
+            tx.send(1);
         });
-        assert_eq!(rx.recv().unwrap(), 1);
-    }
+        assert_eq!(rx.recv(), 1);
+    } }
 
-    #[test]
-    fn smoke_port_gone() {
+    test! { fn smoke_port_gone() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(rx);
-        assert!(tx.send(1).is_err());
-    }
+        tx.send(1);
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_shared_port_gone2() {
+    test! { fn smoke_shared_port_gone2() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
-        assert!(tx2.send(1).is_err());
-    }
+        tx2.send(1);
+    } #[should_fail] }
 
-    #[test]
-    fn port_gone_concurrent() {
+    test! { fn port_gone_concurrent() {
         let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap();
+        spawn(move|| {
+            rx.recv();
         });
-        while tx.send(1).is_ok() {}
-    }
+        loop { tx.send(1) }
+    } #[should_fail] }
 
-    #[test]
-    fn port_gone_concurrent_shared() {
+    test! { fn port_gone_concurrent_shared() {
         let (tx, rx) = sync_channel::<int>(0);
         let tx2 = tx.clone();
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap();
+        spawn(move|| {
+            rx.recv();
         });
-        while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
-    }
+        loop {
+            tx.send(1);
+            tx2.send(1);
+        }
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_chan_gone() {
+    test! { fn smoke_chan_gone() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(tx);
-        assert!(rx.recv().is_err());
-    }
+        rx.recv();
+    } #[should_fail] }
 
-    #[test]
-    fn smoke_chan_gone_shared() {
+    test! { fn smoke_chan_gone_shared() {
         let (tx, rx) = sync_channel::<()>(0);
         let tx2 = tx.clone();
         drop(tx);
         drop(tx2);
-        assert!(rx.recv().is_err());
-    }
+        rx.recv();
+    } #[should_fail] }
 
-    #[test]
-    fn chan_gone_concurrent() {
+    test! { fn chan_gone_concurrent() {
         let (tx, rx) = sync_channel::<int>(0);
-        Thread::spawn(move|| {
-            tx.send(1).unwrap();
-            tx.send(1).unwrap();
-        }).detach();
-        while rx.recv().is_ok() {}
-    }
+        spawn(move|| {
+            tx.send(1);
+            tx.send(1);
+        });
+        loop { rx.recv(); }
+    } #[should_fail] }
 
-    #[test]
-    fn stress() {
+    test! { fn stress() {
         let (tx, rx) = sync_channel::<int>(0);
-        Thread::spawn(move|| {
-            for _ in range(0u, 10000) { tx.send(1).unwrap(); }
-        }).detach();
+        spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1); }
+        });
         for _ in range(0u, 10000) {
-            assert_eq!(rx.recv().unwrap(), 1);
+            assert_eq!(rx.recv(), 1);
         }
-    }
+    } }
 
-    #[test]
-    fn stress_shared() {
+    test! { fn stress_shared() {
         static AMT: uint = 1000;
         static NTHREADS: uint = 8;
         let (tx, rx) = sync_channel::<int>(0);
         let (dtx, drx) = sync_channel::<()>(0);
 
-        Thread::spawn(move|| {
+        spawn(move|| {
             for _ in range(0, AMT * NTHREADS) {
-                assert_eq!(rx.recv().unwrap(), 1);
+                assert_eq!(rx.recv(), 1);
             }
             match rx.try_recv() {
                 Ok(..) => panic!(),
                 _ => {}
             }
-            dtx.send(()).unwrap();
-        }).detach();
+            dtx.send(());
+        });
 
         for _ in range(0, NTHREADS) {
             let tx = tx.clone();
-            Thread::spawn(move|| {
-                for _ in range(0, AMT) { tx.send(1).unwrap(); }
-            }).detach();
+            spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1); }
+            });
         }
         drop(tx);
-        drx.recv().unwrap();
-    }
+        drx.recv();
+    } }
 
-    #[test]
-    fn oneshot_single_thread_close_port_first() {
+    test! { fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
         let (_tx, rx) = sync_channel::<int>(0);
         drop(rx);
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_close_chan_first() {
+    test! { fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
         let (tx, _rx) = sync_channel::<int>(0);
         drop(tx);
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_send_port_close() {
+    test! { fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
         let (tx, rx) = sync_channel::<Box<int>>(0);
         drop(rx);
-        assert!(tx.send(box 0).is_err());
-    }
+        tx.send(box 0);
+    } #[should_fail] }
 
-    #[test]
-    fn oneshot_single_thread_recv_chan_close() {
+    test! { fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = Thread::spawn(move|| {
             let (tx, rx) = sync_channel::<int>(0);
             drop(tx);
-            rx.recv().unwrap();
+            rx.recv();
         }).join();
         // What is our res?
         assert!(res.is_err());
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_send_then_recv() {
+    test! { fn oneshot_single_thread_send_then_recv() {
         let (tx, rx) = sync_channel::<Box<int>>(1);
-        tx.send(box 10).unwrap();
-        assert!(rx.recv().unwrap() == box 10);
-    }
+        tx.send(box 10);
+        assert!(rx.recv() == box 10);
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_send_open() {
+    test! { fn oneshot_single_thread_try_send_open() {
         let (tx, rx) = sync_channel::<int>(1);
         assert_eq!(tx.try_send(10), Ok(()));
-        assert!(rx.recv().unwrap() == 10);
-    }
+        assert!(rx.recv() == 10);
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_send_closed() {
+    test! { fn oneshot_single_thread_try_send_closed() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(rx);
-        assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10)));
-    }
+        assert_eq!(tx.try_send(10), Err(RecvDisconnected(10)));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_send_closed2() {
+    test! { fn oneshot_single_thread_try_send_closed2() {
         let (tx, _rx) = sync_channel::<int>(0);
-        assert_eq!(tx.try_send(10), Err(TrySendError::Full(10)));
-    }
+        assert_eq!(tx.try_send(10), Err(Full(10)));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_recv_open() {
+    test! { fn oneshot_single_thread_try_recv_open() {
         let (tx, rx) = sync_channel::<int>(1);
-        tx.send(10).unwrap();
-        assert!(rx.recv() == Ok(10));
-    }
+        tx.send(10);
+        assert!(rx.recv_opt() == Ok(10));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_try_recv_closed() {
+    test! { fn oneshot_single_thread_try_recv_closed() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(tx);
-        assert!(rx.recv().is_err());
-    }
+        assert!(rx.recv_opt() == Err(()));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_data() {
+    test! { fn oneshot_single_thread_peek_data() {
         let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
-        tx.send(10).unwrap();
+        assert_eq!(rx.try_recv(), Err(Empty));
+        tx.send(10);
         assert_eq!(rx.try_recv(), Ok(10));
-    }
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_close() {
+    test! { fn oneshot_single_thread_peek_close() {
         let (tx, rx) = sync_channel::<int>(0);
         drop(tx);
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
-    }
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+    } }
 
-    #[test]
-    fn oneshot_single_thread_peek_open() {
+    test! { fn oneshot_single_thread_peek_open() {
         let (_tx, rx) = sync_channel::<int>(0);
-        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
-    }
+        assert_eq!(rx.try_recv(), Err(Empty));
+    } }
 
-    #[test]
-    fn oneshot_multi_task_recv_then_send() {
+    test! { fn oneshot_multi_task_recv_then_send() {
         let (tx, rx) = sync_channel::<Box<int>>(0);
-        let _t = Thread::spawn(move|| {
-            assert!(rx.recv().unwrap() == box 10);
+        spawn(move|| {
+            assert!(rx.recv() == box 10);
         });
 
-        tx.send(box 10).unwrap();
-    }
+        tx.send(box 10);
+    } }
 
-    #[test]
-    fn oneshot_multi_task_recv_then_close() {
+    test! { fn oneshot_multi_task_recv_then_close() {
         let (tx, rx) = sync_channel::<Box<int>>(0);
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             drop(tx);
         });
         let res = Thread::spawn(move|| {
-            assert!(rx.recv().unwrap() == box 10);
+            assert!(rx.recv() == box 10);
         }).join();
         assert!(res.is_err());
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_close_stress() {
+    test! { fn oneshot_multi_thread_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
+            spawn(move|| {
                 drop(rx);
             });
             drop(tx);
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_send_close_stress() {
+    test! { fn oneshot_multi_thread_send_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
+            spawn(move|| {
                 drop(rx);
             });
             let _ = Thread::spawn(move || {
-                tx.send(1).unwrap();
+                tx.send(1);
             }).join();
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_recv_close_stress() {
+    test! { fn oneshot_multi_thread_recv_close_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
+            spawn(move|| {
                 let res = Thread::spawn(move|| {
-                    rx.recv().unwrap();
+                    rx.recv();
                 }).join();
                 assert!(res.is_err());
             });
-            let _t = Thread::spawn(move|| {
-                Thread::spawn(move|| {
+            spawn(move|| {
+                spawn(move|| {
                     drop(tx);
-                }).detach();
+                });
             });
         }
-    }
+    } }
 
-    #[test]
-    fn oneshot_multi_thread_send_recv_stress() {
+    test! { fn oneshot_multi_thread_send_recv_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = sync_channel::<Box<int>>(0);
-            let _t = Thread::spawn(move|| {
-                tx.send(box 10i).unwrap();
+            spawn(move|| {
+                tx.send(box 10i);
+            });
+            spawn(move|| {
+                assert!(rx.recv() == box 10i);
             });
-            assert!(rx.recv().unwrap() == box 10i);
         }
-    }
+    } }
 
-    #[test]
-    fn stream_send_recv_stress() {
+    test! { fn stream_send_recv_stress() {
         for _ in range(0, stress_factor()) {
             let (tx, rx) = sync_channel::<Box<int>>(0);
 
@@ -1864,73 +1839,69 @@ fn stream_send_recv_stress() {
             fn send(tx: SyncSender<Box<int>>, i: int) {
                 if i == 10 { return }
 
-                Thread::spawn(move|| {
-                    tx.send(box i).unwrap();
+                spawn(move|| {
+                    tx.send(box i);
                     send(tx, i + 1);
-                }).detach();
+                });
             }
 
             fn recv(rx: Receiver<Box<int>>, i: int) {
                 if i == 10 { return }
 
-                Thread::spawn(move|| {
-                    assert!(rx.recv().unwrap() == box i);
+                spawn(move|| {
+                    assert!(rx.recv() == box i);
                     recv(rx, i + 1);
-                }).detach();
+                });
             }
         }
-    }
+    } }
 
-    #[test]
-    fn recv_a_lot() {
+    test! { fn recv_a_lot() {
         // Regression test that we don't run out of stack in scheduler context
         let (tx, rx) = sync_channel(10000);
-        for _ in range(0u, 10000) { tx.send(()).unwrap(); }
-        for _ in range(0u, 10000) { rx.recv().unwrap(); }
-    }
+        for _ in range(0u, 10000) { tx.send(()); }
+        for _ in range(0u, 10000) { rx.recv(); }
+    } }
 
-    #[test]
-    fn shared_chan_stress() {
+    test! { fn shared_chan_stress() {
         let (tx, rx) = sync_channel(0);
         let total = stress_factor() + 100;
         for _ in range(0, total) {
             let tx = tx.clone();
-            Thread::spawn(move|| {
-                tx.send(()).unwrap();
-            }).detach();
+            spawn(move|| {
+                tx.send(());
+            });
         }
 
         for _ in range(0, total) {
-            rx.recv().unwrap();
+            rx.recv();
         }
-    }
+    } }
 
-    #[test]
-    fn test_nested_recv_iter() {
+    test! { fn test_nested_recv_iter() {
         let (tx, rx) = sync_channel::<int>(0);
         let (total_tx, total_rx) = sync_channel::<int>(0);
 
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             let mut acc = 0;
             for x in rx.iter() {
                 acc += x;
             }
-            total_tx.send(acc).unwrap();
+            total_tx.send(acc);
         });
 
-        tx.send(3).unwrap();
-        tx.send(1).unwrap();
-        tx.send(2).unwrap();
+        tx.send(3);
+        tx.send(1);
+        tx.send(2);
         drop(tx);
-        assert_eq!(total_rx.recv().unwrap(), 6);
-    }
+        assert_eq!(total_rx.recv(), 6);
+    } }
 
-    #[test]
-    fn test_recv_iter_break() {
+    test! { fn test_recv_iter_break() {
         let (tx, rx) = sync_channel::<int>(0);
         let (count_tx, count_rx) = sync_channel(0);
 
-        let _t = Thread::spawn(move|| {
+        spawn(move|| {
             let mut count = 0;
             for x in rx.iter() {
                 if count >= 3 {
@@ -1939,51 +1910,49 @@ fn test_recv_iter_break() {
                     count += x;
                 }
             }
-            count_tx.send(count).unwrap();
+            count_tx.send(count);
         });
 
-        tx.send(2).unwrap();
-        tx.send(2).unwrap();
-        tx.send(2).unwrap();
+        tx.send(2);
+        tx.send(2);
+        tx.send(2);
         let _ = tx.try_send(2);
         drop(tx);
-        assert_eq!(count_rx.recv().unwrap(), 4);
-    }
+        assert_eq!(count_rx.recv(), 4);
+    } }
 
-    #[test]
-    fn try_recv_states() {
+    test! { fn try_recv_states() {
         let (tx1, rx1) = sync_channel::<int>(1);
         let (tx2, rx2) = sync_channel::<()>(1);
         let (tx3, rx3) = sync_channel::<()>(1);
-        let _t = Thread::spawn(move|| {
-            rx2.recv().unwrap();
-            tx1.send(1).unwrap();
-            tx3.send(()).unwrap();
-            rx2.recv().unwrap();
+        spawn(move|| {
+            rx2.recv();
+            tx1.send(1);
+            tx3.send(());
+            rx2.recv();
             drop(tx1);
-            tx3.send(()).unwrap();
+            tx3.send(());
         });
 
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-        tx2.send(()).unwrap();
-        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
         assert_eq!(rx1.try_recv(), Ok(1));
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-        tx2.send(()).unwrap();
-        rx3.recv().unwrap();
-        assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected));
-    }
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Err(Disconnected));
+    } }
 
     // This bug used to end up in a livelock inside of the Receiver destructor
     // because the internal state of the Shared packet was corrupted
-    #[test]
-    fn destroy_upgraded_shared_port_when_sender_still_active() {
+    test! { fn destroy_upgraded_shared_port_when_sender_still_active() {
         let (tx, rx) = sync_channel::<()>(0);
         let (tx2, rx2) = sync_channel::<()>(0);
-        let _t = Thread::spawn(move|| {
-            rx.recv().unwrap(); // wait on a oneshot
+        spawn(move|| {
+            rx.recv(); // wait on a oneshot
             drop(rx);  // destroy a shared
-            tx2.send(()).unwrap();
+            tx2.send(());
         });
         // make sure the other task has gone to sleep
         for _ in range(0u, 5000) { Thread::yield_now(); }
@@ -1991,91 +1960,92 @@ fn destroy_upgraded_shared_port_when_sender_still_active() {
         // upgrade to a shared chan and send a message
         let t = tx.clone();
         drop(tx);
-        t.send(()).unwrap();
+        t.send(());
 
         // wait for the child task to exit before we exit
-        rx2.recv().unwrap();
-    }
+        rx2.recv();
+    } }
 
-    #[test]
-    fn send1() {
+    test! { fn send_opt1() {
         let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| { rx.recv().unwrap(); });
-        assert_eq!(tx.send(1), Ok(()));
-    }
+        spawn(move|| { rx.recv(); });
+        assert_eq!(tx.send_opt(1), Ok(()));
+    } }
 
-    #[test]
-    fn send2() {
+    test! { fn send_opt2() {
         let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| { drop(rx); });
-        assert!(tx.send(1).is_err());
-    }
+        spawn(move|| { drop(rx); });
+        assert_eq!(tx.send_opt(1), Err(1));
+    } }
 
-    #[test]
-    fn send3() {
+    test! { fn send_opt3() {
         let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(tx.send(1), Ok(()));
-        let _t =Thread::spawn(move|| { drop(rx); });
-        assert!(tx.send(1).is_err());
-    }
+        assert_eq!(tx.send_opt(1), Ok(()));
+        spawn(move|| { drop(rx); });
+        assert_eq!(tx.send_opt(1), Err(1));
+    } }
 
-    #[test]
-    fn send4() {
+    test! { fn send_opt4() {
         let (tx, rx) = sync_channel::<int>(0);
         let tx2 = tx.clone();
         let (done, donerx) = channel();
         let done2 = done.clone();
-        let _t = Thread::spawn(move|| {
-            assert!(tx.send(1).is_err());
-            done.send(()).unwrap();
+        spawn(move|| {
+            assert_eq!(tx.send_opt(1), Err(1));
+            done.send(());
         });
-        let _t = Thread::spawn(move|| {
-            assert!(tx2.send(2).is_err());
-            done2.send(()).unwrap();
+        spawn(move|| {
+            assert_eq!(tx2.send_opt(2), Err(2));
+            done2.send(());
         });
         drop(rx);
-        donerx.recv().unwrap();
-        donerx.recv().unwrap();
-    }
+        donerx.recv();
+        donerx.recv();
+    } }
 
-    #[test]
-    fn try_send1() {
+    test! { fn try_send1() {
         let (tx, _rx) = sync_channel::<int>(0);
-        assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
-    }
+        assert_eq!(tx.try_send(1), Err(Full(1)));
+    } }
 
-    #[test]
-    fn try_send2() {
+    test! { fn try_send2() {
         let (tx, _rx) = sync_channel::<int>(1);
         assert_eq!(tx.try_send(1), Ok(()));
-        assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
-    }
+        assert_eq!(tx.try_send(1), Err(Full(1)));
+    } }
 
-    #[test]
-    fn try_send3() {
+    test! { fn try_send3() {
         let (tx, rx) = sync_channel::<int>(1);
         assert_eq!(tx.try_send(1), Ok(()));
         drop(rx);
-        assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1)));
-    }
+        assert_eq!(tx.try_send(1), Err(RecvDisconnected(1)));
+    } }
 
-    #[test]
-    fn issue_15761() {
+    test! { fn try_send4() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            for _ in range(0u, 1000) { Thread::yield_now(); }
+            assert_eq!(tx.try_send(1), Ok(()));
+        });
+        assert_eq!(rx.recv(), 1);
+    } #[ignore(reason = "flaky on libnative")] }
+
+    test! { fn issue_15761() {
         fn repro() {
             let (tx1, rx1) = sync_channel::<()>(3);
             let (tx2, rx2) = sync_channel::<()>(3);
 
-            let _t = Thread::spawn(move|| {
-                rx1.recv().unwrap();
+            spawn(move|| {
+                rx1.recv();
                 tx2.try_send(()).unwrap();
             });
 
             tx1.try_send(()).unwrap();
-            rx2.recv().unwrap();
+            rx2.recv();
         }
 
         for _ in range(0u, 100) {
             repro()
         }
-    }
+    } }
 }
index b2367ff8352fbb8d30f62b7f59080b93eb3bd9cb..bd98b09d77985fcc8974d1af6859d5e99778325c 100644 (file)
@@ -41,7 +41,7 @@
 /// ```
 /// use std::sync::RWLock;
 ///
-/// let lock = RWLock::new(5i);
+/// let lock = RWLock::new(5);
 ///
 /// // many reader locks can be held at once
 /// {
index a441e55a732b01049a187df94b611ce36e8edafe..a31dcc9884f465fa74c4311f443ac670853c0dac 100644 (file)
@@ -14,7 +14,7 @@
 use io::{self, IoError, IoResult};
 use prelude::v1::*;
 use sys::{last_error, retry};
-use c_str::CString;
+use ffi::CString;
 use num::Int;
 use path::BytesContainer;
 use collections;
index 3f67b284f688794d2611944e327463d0fce373c3..4cf891ac4985eba360859a1cff038719ce3ca9a8 100644 (file)
 use self::SocketStatus::*;
 use self::InAddr::*;
 
-use c_str::ToCStr;
+use ffi::CString;
+use ffi;
 use io::net::addrinfo;
 use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
 use io::{IoResult, IoError};
 use libc::{self, c_char, c_int};
-use c_str::CString;
 use mem;
 use num::Int;
 use ptr::{self, null, null_mut};
+use str;
 use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
           wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
           decode_error_detailed};
@@ -234,9 +235,9 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
 
     assert!(host.is_some() || servname.is_some());
 
-    let c_host = host.map(|x| x.to_c_str());
+    let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
     let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
-    let c_serv = servname.map(|x| x.to_c_str());
+    let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
     let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
 
     let hint = hint.map(|hint| {
@@ -324,7 +325,8 @@ pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
     }
 
     unsafe {
-        Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string())
+        Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
+               .unwrap().to_string())
     }
 }
 
index 5b261ea6b9e58a85e9c5a94bc6da6ae4304ff890..ca268a8f27ff34680a915eff95255b7f4acd2093 100644 (file)
 /// to symbols. This is a bit of a hokey implementation as-is, but it works for
 /// all unix platforms we support right now, so it at least gets the job done.
 
-use c_str::CString;
-use io::{IoResult, Writer};
+use prelude::v1::*;
+
+use ffi;
+use io::IoResult;
 use libc;
 use mem;
-use option::Option::{self, Some, None};
-use result::Result::{Ok, Err};
+use str;
 use sync::{StaticMutex, MUTEX_INIT};
 
 use sys_common::backtrace::*;
 #[cfg(all(target_os = "ios", target_arch = "arm"))]
 #[inline(never)]
 pub fn write(w: &mut Writer) -> IoResult<()> {
-    use iter::{IteratorExt, range};
     use result;
-    use slice::SliceExt;
 
     extern {
         fn backtrace(buf: *mut *mut libc::c_void,
@@ -234,19 +233,15 @@ fn dladdr(addr: *const libc::c_void,
         output(w, idx,addr, None)
     } else {
         output(w, idx, addr, Some(unsafe {
-            CString::new(info.dli_sname, false)
+            ffi::c_str_to_bytes(&info.dli_sname)
         }))
     }
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
 fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
-    use iter::{Iterator, IteratorExt};
     use os;
-    use path::GenericPath;
-    use ptr::PtrExt;
     use ptr;
-    use slice::SliceExt;
 
     ////////////////////////////////////////////////////////////////////////
     // libbacktrace.h API
@@ -368,15 +363,15 @@ unsafe fn init_state() -> *mut backtrace_state {
     if ret == 0 || data.is_null() {
         output(w, idx, addr, None)
     } else {
-        output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+        output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
     }
 }
 
 // Finally, after all that work above, we can emit a symbol.
 fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
-          s: Option<CString>) -> IoResult<()> {
+          s: Option<&[u8]>) -> IoResult<()> {
     try!(write!(w, "  {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
-    match s.as_ref().and_then(|c| c.as_str()) {
+    match s.and_then(|s| str::from_utf8(s).ok()) {
         Some(string) => try!(demangle(w, string)),
         None => try!(write!(w, "<unknown>")),
     }
index b49ace8e2f8d83509a13525f0744f7d206d1d28d..1ad775517bba714aac62f8ea639ed31660d1d935 100644 (file)
@@ -12,7 +12,7 @@
 
 use prelude::v1::*;
 
-use c_str::{CString, ToCStr};
+use ffi::{self, CString};
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use io::{IoResult, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
@@ -150,6 +150,10 @@ fn drop(&mut self) {
     }
 }
 
+fn cstr(path: &Path) -> CString {
+    CString::from_slice(path.as_vec())
+}
+
 pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
     let flags = match fm {
         Open => 0,
@@ -165,7 +169,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
                             libc::S_IRUSR | libc::S_IWUSR),
     };
 
-    let path = path.to_c_str();
+    let path = cstr(path);
     match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
         -1 => Err(super::last_error()),
         fd => Ok(FileDesc::new(fd, true)),
@@ -173,7 +177,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
 }
 
 pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
 }
 
@@ -182,7 +186,6 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
     use libc::{opendir, readdir_r, closedir};
 
     fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
-        let root = unsafe { CString::new(root.as_ptr(), false) };
         let root = Path::new(root);
 
         dirs.into_iter().filter(|path| {
@@ -199,7 +202,7 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
     let mut buf = Vec::<u8>::with_capacity(size as uint);
     let ptr = buf.as_mut_ptr() as *mut dirent_t;
 
-    let p = p.to_c_str();
+    let p = CString::from_slice(p.as_vec());
     let dir_ptr = unsafe {opendir(p.as_ptr())};
 
     if dir_ptr as uint != 0 {
@@ -207,10 +210,9 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
         let mut entry_ptr = 0 as *mut dirent_t;
         while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
             if entry_ptr.is_null() { break }
-            let cstr = unsafe {
-                CString::new(rust_list_dir_val(entry_ptr), false)
-            };
-            paths.push(Path::new(cstr));
+            paths.push(unsafe {
+                Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+            });
         }
         assert_eq!(unsafe { closedir(dir_ptr) }, 0);
         Ok(prune(&p, paths))
@@ -220,39 +222,39 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
 }
 
 pub fn unlink(p: &Path) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
 }
 
 pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
-    let old = old.to_c_str();
-    let new = new.to_c_str();
+    let old = cstr(old);
+    let new = cstr(new);
     mkerr_libc(unsafe {
         libc::rename(old.as_ptr(), new.as_ptr())
     })
 }
 
 pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(retry(|| unsafe {
         libc::chmod(p.as_ptr(), mode as libc::mode_t)
     }))
 }
 
 pub fn rmdir(p: &Path) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
 }
 
 pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     mkerr_libc(retry(|| unsafe {
         libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
     }))
 }
 
 pub fn readlink(p: &Path) -> IoResult<Path> {
-    let c_path = p.to_c_str();
+    let c_path = cstr(p);
     let p = c_path.as_ptr();
     let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
     if len == -1 {
@@ -273,14 +275,14 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = src.to_c_str();
-    let dst = dst.to_c_str();
+    let src = cstr(src);
+    let dst = cstr(dst);
     mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
 }
 
 pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
-    let src = src.to_c_str();
-    let dst = dst.to_c_str();
+    let src = cstr(src);
+    let dst = cstr(dst);
     mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
 }
 
@@ -328,7 +330,7 @@ fn gen(_stat: &libc::stat) -> u64 { 0 }
 }
 
 pub fn stat(p: &Path) -> IoResult<FileStat> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -337,7 +339,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn lstat(p: &Path) -> IoResult<FileStat> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
         0 => Ok(mkstat(&stat)),
@@ -346,7 +348,7 @@ pub fn lstat(p: &Path) -> IoResult<FileStat> {
 }
 
 pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
-    let p = p.to_c_str();
+    let p = cstr(p);
     let buf = libc::utimbuf {
         actime: (atime / 1000) as libc::time_t,
         modtime: (mtime / 1000) as libc::time_t,
index ea0d230e8b210c751d80df67a093e7f25f146dd5..6a408aa60f0bfb2aa8bbcbbf8fe3a691fb681e0e 100644 (file)
 #![allow(unused_unsafe)]
 #![allow(unused_mut)]
 
-extern crate libc;
-
-use num;
-use num::{Int, SignedInt};
 use prelude::v1::*;
+
+use ffi;
 use io::{self, IoResult, IoError};
+use libc;
+use num::{Int, SignedInt};
+use num;
+use str;
 use sys_common::mkerr_libc;
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -78,11 +80,10 @@ pub fn last_net_error() -> IoError {
 }
 
 pub fn last_gai_error(s: libc::c_int) -> IoError {
-    use c_str::CString;
 
     let mut err = decode_error(s);
     err.detail = Some(unsafe {
-        CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
+        str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
     });
     err
 }
index 181b8fdd0f8a11af8e610cd751b1aebc6d72da48..175c4e2e353f91044fa0453395c27f173671a870 100644 (file)
 
 use prelude::v1::*;
 
-use c_str::ToCStr;
 use error::{FromError, Error};
+use ffi::{self, CString};
 use fmt;
 use io::{IoError, IoResult};
 use libc::{self, c_int, c_char, c_void};
+use os::TMPBUF_SZ;
 use os;
 use path::{BytesContainer};
 use ptr;
+use str;
 use sys::fs::FileDesc;
 
-use os::TMPBUF_SZ;
-
 const BUF_BYTES : uint = 2048u;
 
 /// Returns the platform-specific value of errno
@@ -108,7 +108,8 @@ fn __xpg_strerror_r(errnum: c_int,
             panic!("strerror_r failure");
         }
 
-        String::from_raw_buf(p as *const u8)
+        let p = p as *const _;
+        str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
     }
 }
 
@@ -122,21 +123,17 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
 }
 
 pub fn getcwd() -> IoResult<Path> {
-    use c_str::CString;
-
     let mut buf = [0 as c_char; BUF_BYTES];
     unsafe {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
             Err(IoError::last_error())
         } else {
-            Ok(Path::new(CString::new(buf.as_ptr(), false)))
+            Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
         }
     }
 }
 
 pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-    use c_str::CString;
-
     extern {
         fn rust_env_pairs() -> *const *const c_char;
     }
@@ -147,8 +144,7 @@ pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
     }
     let mut result = Vec::new();
     while *environ != 0 as *const _ {
-        let env_pair =
-            CString::new(*environ, false).as_bytes_no_nul().to_vec();
+        let env_pair = ffi::c_str_to_bytes(&*environ).to_vec();
         result.push(env_pair);
         environ = environ.offset(1);
     }
@@ -234,14 +230,13 @@ pub fn load_self() -> Option<Vec<u8>> {
 }
 
 pub fn chdir(p: &Path) -> IoResult<()> {
-    p.with_c_str(|buf| {
-        unsafe {
-            match libc::chdir(buf) == (0 as c_int) {
-                true => Ok(()),
-                false => Err(IoError::last_error()),
-            }
+    let p = CString::from_slice(p.as_vec());
+    unsafe {
+        match libc::chdir(p.as_ptr()) == (0 as c_int) {
+            true => Ok(()),
+            false => Err(IoError::last_error()),
         }
-    })
+    }
 }
 
 pub fn page_size() -> uint {
index 9063fbc2ba955b9466f3b12b9b9164f8a9397b36..158a1ce220411439bfeb2f188fdb002bf12ed14d 100644 (file)
@@ -10,8 +10,8 @@
 
 use prelude::v1::*;
 
+use ffi::CString;
 use libc;
-use c_str::CString;
 use mem;
 use sync::{Arc, Mutex};
 use sync::atomic::{AtomicBool, Ordering};
@@ -48,7 +48,7 @@ fn addr_to_sockaddr_un(addr: &CString,
     }
     s.sun_family = libc::AF_UNIX as libc::sa_family_t;
     for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
-        *slot = value;
+        *slot = *value;
     }
 
     // count the null terminator
index b73919fe2a2cc5b063b65624bea6c1a467b734dd..5bc6b0c703b1c9c90057820cb37f2880bec164aa 100644 (file)
@@ -11,8 +11,8 @@
 use prelude::v1::*;
 use self::Req::*;
 
-use c_str::{CString, ToCStr};
 use collections;
+use ffi::CString;
 use hash::Hash;
 use io::process::{ProcessExit, ExitStatus, ExitSignal};
 use io::{self, IoResult, IoError, EndOfFile};
@@ -101,7 +101,7 @@ unsafe fn set_cloexec(fd: c_int) {
 
                 // We may use this in the child, so perform allocations before the
                 // fork
-                let devnull = "/dev/null".to_c_str();
+                let devnull = b"/dev/null\0";
 
                 set_cloexec(output.fd());
 
@@ -204,7 +204,7 @@ fn fail(output: &mut FileDesc) -> ! {
                             } else {
                                 libc::O_RDWR
                             };
-                            libc::open(devnull.as_ptr(), flags, 0)
+                            libc::open(devnull.as_ptr() as *const _, flags, 0)
                         }
                         Some(obj) => {
                             let fd = obj.as_inner().fd();
index 11f29232a925d0e3625a607a9ee1d7c978e5f5db..62f3242a2062580360ee277bc83ce9be8cf97767 100644 (file)
@@ -54,7 +54,7 @@
 use mem;
 use os;
 use ptr;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
 use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
 use sys::c;
 use sys::fs::FileDesc;
index 319a458087b9b51f949c997cf08c101ca55b662f..4ccecfd1f5f2e6cc35f754cbe7049dcd23181388 100644 (file)
@@ -21,7 +21,8 @@
 /// copy of that function in my mingw install (maybe it was broken?). Instead,
 /// this takes the route of using StackWalk64 in order to walk the stack.
 
-use c_str::CString;
+use dynamic_lib::DynamicLibrary;
+use ffi;
 use intrinsics;
 use io::{IoResult, Writer};
 use libc;
 use option::Option::{Some, None};
 use path::Path;
 use result::Result::{Ok, Err};
-use sync::{StaticMutex, MUTEX_INIT};
 use slice::SliceExt;
-use str::StrExt;
-use dynamic_lib::DynamicLibrary;
+use str::{self, StrExt};
+use sync::{StaticMutex, MUTEX_INIT};
 
 use sys_common::backtrace::*;
 
@@ -357,11 +357,11 @@ macro_rules! sym{ ($e:expr, $t:ident) => (unsafe {
 
         if ret == libc::TRUE {
             try!(write!(w, " - "));
-            let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
-            let bytes = cstr.as_bytes();
-            match cstr.as_str() {
-                Some(s) => try!(demangle(w, s)),
-                None => try!(w.write(bytes[..bytes.len()-1])),
+            let ptr = info.Name.as_ptr() as *const libc::c_char;
+            let bytes = unsafe { ffi::c_str_to_bytes(&ptr) };
+            match str::from_utf8(bytes) {
+                Ok(s) => try!(demangle(w, s)),
+                Err(..) => try!(w.write(bytes[..bytes.len()-1])),
             }
         }
         try!(w.write(&['\n' as u8]));
index 1ee57434fb91ada83e4cad503654a6d7b9332afd..945c2e8e7d156ce501ca029f5b54483123a3acd5 100644 (file)
@@ -133,7 +133,7 @@ pub mod compat {
     use intrinsics::{atomic_store_relaxed, transmute};
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::v1::*;
-    use c_str::ToCStr;
+    use ffi::CString;
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
@@ -147,14 +147,13 @@ pub mod compat {
     unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
         let mut module: Vec<u16> = module.utf16_units().collect();
         module.push(0);
-        symbol.with_c_str(|symbol| {
-            let handle = GetModuleHandleW(module.as_ptr());
-            let func: uint = transmute(GetProcAddress(handle, symbol));
-            atomic_store_relaxed(ptr, if func == 0 {
-                fallback
-            } else {
-                func
-            })
+        let symbol = CString::from_slice(symbol.as_bytes());
+        let handle = GetModuleHandleW(module.as_ptr());
+        let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
+        atomic_store_relaxed(ptr, if func == 0 {
+            fallback
+        } else {
+            func
         })
     }
 
index 9a9423006568020e2d83e73fae538d8fd4c944b7..f8c75335b35dc31059790965e7c89e54f52322ec 100644 (file)
@@ -13,7 +13,6 @@
 use alloc::arc::Arc;
 use libc::{self, c_int};
 
-use c_str::CString;
 use mem;
 use sys::os::fill_utf16_buf_and_decode;
 use path;
index 9057515cad294c51f849a0fff470004e77745c97..9996909f2f5bbc18a9781018bd4dd4aaaf952fd1 100644 (file)
 use prelude::v1::*;
 
 use libc;
-use c_str::CString;
+use ffi::CString;
+use io::{self, IoError, IoResult};
 use mem;
 use ptr;
-use sync::{Arc, Mutex};
+use str;
 use sync::atomic::{AtomicBool, Ordering};
-use io::{self, IoError, IoResult};
+use sync::{Arc, Mutex};
 
 use sys_common::{self, eof};
 
-use super::{c, os, timer, to_utf16, decode_error_detailed};
+use super::{c, os, timer, decode_error_detailed};
+
+fn to_utf16(c: &CString) -> IoResult<Vec<u16>> {
+    super::to_utf16(str::from_utf8(c.as_bytes()).ok())
+}
 
 struct Event(libc::HANDLE);
 
@@ -270,7 +275,7 @@ fn try_connect(p: *const u16) -> Option<libc::HANDLE> {
     }
 
     pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
-        let addr = try!(to_utf16(addr.as_str()));
+        let addr = try!(to_utf16(addr));
         let start = timer::now();
         loop {
             match UnixStream::try_connect(addr.as_ptr()) {
@@ -571,7 +576,7 @@ pub fn bind(addr: &CString) -> IoResult<UnixListener> {
         // Although we technically don't need the pipe until much later, we
         // create the initial handle up front to test the validity of the name
         // and such.
-        let addr_v = try!(to_utf16(addr.as_str()));
+        let addr_v = try!(to_utf16(addr));
         let ret = unsafe { pipe(addr_v.as_ptr(), true) };
         if ret == libc::INVALID_HANDLE_VALUE {
             Err(super::last_error())
@@ -661,7 +666,7 @@ pub fn accept(&mut self) -> IoResult<UnixStream> {
         // proceed in accepting new clients in the future
         if self.inner.closed.load(Ordering::SeqCst) { return Err(eof()) }
 
-        let name = try!(to_utf16(self.listener.name.as_str()));
+        let name = try!(to_utf16(&self.listener.name));
 
         // Once we've got a "server handle", we need to wait for a client to
         // connect. The ConnectNamedPipe function will block this thread until
@@ -753,7 +758,7 @@ pub fn handle(&self) -> libc::HANDLE {
 
 impl Clone for UnixAcceptor {
     fn clone(&self) -> UnixAcceptor {
-        let name = to_utf16(self.listener.name.as_str()).ok().unwrap();
+        let name = to_utf16(&self.listener.name).ok().unwrap();
         UnixAcceptor {
             inner: self.inner.clone(),
             event: Event::new(true, false).ok().unwrap(),
index 81e8f974a12238abf9fad4e13d79571078cc050f..9b3f2ca03736efa06114e2177623ab3030838ec4 100644 (file)
 
 use prelude::v1::*;
 
+use collections;
+use ffi::CString;
+use hash::Hash;
+use io::fs::PathExtensions;
+use io::process::{ProcessExit, ExitStatus, ExitSignal};
+use io::{IoResult, IoError};
+use io;
 use libc::{pid_t, c_void, c_int};
 use libc;
-use c_str::{CString, ToCStr};
-use io;
 use mem;
 use os;
-use ptr;
-use io::process::{ProcessExit, ExitStatus, ExitSignal};
-use collections;
 use path::BytesContainer;
-use hash::Hash;
-use io::{IoResult, IoError};
-
+use ptr;
+use str;
+use sys::fs::FileDesc;
 use sys::fs;
 use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
 use sys_common::{AsInner, mkerr_libc, timeout};
 
-use io::fs::PathExtensions;
-
 pub use sys_common::ProcessConfig;
 
 /// A value representing a child process.
@@ -142,10 +141,10 @@ pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in os::split_paths(v.container_as_bytes()).into_iter() {
-                    let path = path.join(cfg.program().as_bytes_no_nul())
+                    let path = path.join(cfg.program().as_bytes())
                                    .with_extension(os::consts::EXE_EXTENSION);
                     if path.exists() {
-                        return Some(path.to_c_str())
+                        return Some(CString::from_slice(path.as_vec()))
                     }
                 }
                 break
@@ -363,11 +362,11 @@ fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMA
 
 fn make_command_line(prog: &CString, args: &[CString]) -> String {
     let mut cmd = String::new();
-    append_arg(&mut cmd, prog.as_str()
+    append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
                              .expect("expected program name to be utf-8 encoded"));
     for arg in args.iter() {
         cmd.push(' ');
-        append_arg(&mut cmd, arg.as_str()
+        append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
                                 .expect("expected argument to be utf-8 encoded"));
     }
     return cmd;
@@ -449,7 +448,7 @@ fn with_dirp<T, F>(d: Option<&CString>, cb: F) -> T where
 {
     match d {
       Some(dir) => {
-          let dir_str = dir.as_str()
+          let dir_str = str::from_utf8(dir.as_bytes()).ok()
                            .expect("expected workingdirectory to be utf-8 encoded");
           let mut dir_str: Vec<u16> = dir_str.utf16_units().collect();
           dir_str.push(0);
index 1d6f49b04a3f510bfcd6d2eb233bba589e859385..63112327415d238e50f0e95c46f28ed73666b4b2 100644 (file)
@@ -435,7 +435,7 @@ fn drop(&mut self) {
 mod test {
     use prelude::v1::*;
 
-    use any::{Any, AnyRefExt};
+    use any::Any;
     use sync::mpsc::{channel, Sender};
     use boxed::BoxAny;
     use result;
index 01f66f3bbd060b2658bf6533d6c8a7cea59a5162..e779821342a17dc76650d62d1794ba0da6762a82 100644 (file)
@@ -182,18 +182,34 @@ pub fn ident(&self) -> Ident {
 /// A mark represents a unique id associated with a macro expansion
 pub type Mrk = u32;
 
+#[cfg(stage0)]
 impl<S: Encoder<E>, E> Encodable<S, E> for Ident {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_str(token::get_ident(*self).get())
     }
 }
 
+#[cfg(not(stage0))]
+impl Encodable for Ident {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(token::get_ident(*self).get())
+    }
+}
+
+#[cfg(stage0)]
 impl<D: Decoder<E>, E> Decodable<D, E> for Ident {
     fn decode(d: &mut D) -> Result<Ident, E> {
         Ok(str_to_ident(try!(d.read_str())[]))
     }
 }
 
+#[cfg(not(stage0))]
+impl Decodable for Ident {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
+        Ok(str_to_ident(try!(d.read_str())[]))
+    }
+}
+
 /// Function name (not all functions have names)
 pub type FnIdent = Option<Ident>;
 
@@ -989,7 +1005,7 @@ pub fn suffix_len(&self) -> uint {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum Lit_ {
     LitStr(InternedString, StrStyle),
-    LitBinary(Rc<Vec<u8> >),
+    LitBinary(Rc<Vec<u8>>),
     LitByte(u8),
     LitChar(char),
     LitInt(u64, LitIntType),
@@ -1204,8 +1220,6 @@ pub enum Ty_ {
     TyPtr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
     TyRptr(Option<Lifetime>, MutTy),
-    /// A closure (e.g. `|uint| -> bool`)
-    TyClosure(P<ClosureTy>),
     /// A bare function (e.g. `fn(uint) -> bool`)
     TyBareFn(P<BareFnTy>),
     /// A tuple (`(A, B, C, D,...)`)
@@ -1299,6 +1313,24 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub enum ImplPolarity {
+    /// impl Trait for Type
+    Positive,
+    /// impl !Trait for Type
+    Negative,
+}
+
+impl fmt::Show for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ImplPolarity::Positive => "positive".fmt(f),
+            ImplPolarity::Negative => "negative".fmt(f),
+        }
+    }
+}
+
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum FunctionRetTy {
     /// Functions with return type ! that always
@@ -1587,6 +1619,7 @@ pub enum Item_ {
               TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Unsafety,
+             ImplPolarity,
              Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
@@ -1667,27 +1700,7 @@ mod test {
     // are ASTs encodable?
     #[test]
     fn check_asts_encodable() {
-        use std::io;
-        let e = Crate {
-            module: Mod {
-                inner: Span {
-                    lo: BytePos(11),
-                    hi: BytePos(19),
-                    expn_id: NO_EXPANSION,
-                },
-                view_items: Vec::new(),
-                items: Vec::new(),
-            },
-            attrs: Vec::new(),
-            config: Vec::new(),
-            span: Span {
-                lo: BytePos(10),
-                hi: BytePos(20),
-                expn_id: NO_EXPANSION,
-            },
-            exported_macros: Vec::new(),
-        };
-        // doesn't matter which encoder we use....
-        let _f = &e as &serialize::Encodable<json::Encoder, fmt::Error>;
+        fn assert_encodable<T: serialize::Encodable>() {}
+        assert_encodable::<Crate>();
     }
 }
index c5dbd194e3e5fae3f47ae1512153fae4f977fb7d..cf09e2777f7c69a0410d7e33275e42e1c37e5d11 100644 (file)
@@ -755,7 +755,7 @@ fn visit_item(&mut self, i: &'ast Item) {
         let parent = self.parent;
         self.parent = i.id;
         match i.node {
-            ItemImpl(_, _, _, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         MethodImplItem(ref m) => {
@@ -859,9 +859,6 @@ fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
 
     fn visit_ty(&mut self, ty: &'ast Ty) {
         match ty.node {
-            TyClosure(ref fd) => {
-                self.visit_fn_decl(&*fd.decl);
-            }
             TyBareFn(ref fd) => {
                 self.visit_fn_decl(&*fd.decl);
             }
index 2c7bbcb6faf723cd50bf5d2de675049b518a4ee7..a49f2614cd7871f1d8eef024bdd677c07fba9b43 100644 (file)
@@ -120,6 +120,7 @@ fn ne(&self, other: &Span) -> bool { !(*self).eq(other) }
 
 impl Eq for Span {}
 
+#[cfg(stage0)]
 impl<S:Encoder<E>, E> Encodable<S, E> for Span {
     /* Note #1972 -- spans are encoded but not decoded */
     fn encode(&self, s: &mut S) -> Result<(), E> {
@@ -127,12 +128,28 @@ fn encode(&self, s: &mut S) -> Result<(), E> {
     }
 }
 
+#[cfg(not(stage0))]
+impl Encodable for Span {
+    /* Note #1972 -- spans are encoded but not decoded */
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_nil()
+    }
+}
+
+#[cfg(stage0)]
 impl<D:Decoder<E>, E> Decodable<D, E> for Span {
     fn decode(_d: &mut D) -> Result<Span, E> {
         Ok(DUMMY_SP)
     }
 }
 
+#[cfg(not(stage0))]
+impl Decodable for Span {
+    fn decode<D: Decoder>(_d: &mut D) -> Result<Span, D::Error> {
+        Ok(DUMMY_SP)
+    }
+}
+
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> Spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
index 94a3784291d0bc595f56482a40a5c380a09f7de9..3f91831a5df76c85f2dd4b1c62164008bac1da11 100644 (file)
@@ -133,11 +133,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
     F: FnMut(&[ast::Attribute]) -> bool
 {
     let item = match item {
-        ast::ItemImpl(u, a, b, c, impl_items) => {
+        ast::ItemImpl(u, o, a, b, c, impl_items) => {
             let impl_items = impl_items.into_iter()
                                        .filter(|ii| impl_item_in_cfg(cx, ii))
                                        .collect();
-            ast::ItemImpl(u, a, b, c, impl_items)
+            ast::ItemImpl(u, o, a, b, c, impl_items)
         }
         ast::ItemTrait(u, a, b, methods) => {
             let methods = methods.into_iter()
index eedec6f37c840f11343dc2f92c8f7da5195c7774..3c74a9f4431df52d94844d2c656c5d9d0efbdd75 100644 (file)
@@ -40,7 +40,7 @@ pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self,
                 attributes: attrs,
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_clone("Clone", c, s, sub)
                 }),
             }
index 7a67fab820de518b8e88e96bc9fe8d5e1e57ed7b..84d30a99004a46f9f9a10fbfb041fd08989d1320 100644 (file)
@@ -40,7 +40,7 @@ fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
                 cx.expr_binary(span, ast::BiAnd, subexpr, eq)
             },
             cx.expr_bool(span, true),
-            |cx, span, _, _| cx.expr_bool(span, false),
+            box |cx, span, _, _| cx.expr_bool(span, false),
             cx, span, substr)
     }
     fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
@@ -57,7 +57,7 @@ fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
                 cx.expr_binary(span, ast::BiOr, subexpr, eq)
             },
             cx.expr_bool(span, false),
-            |cx, span, _, _| cx.expr_bool(span, true),
+            box |cx, span, _, _| cx.expr_bool(span, true),
             cx, span, substr)
     }
 
@@ -72,7 +72,7 @@ macro_rules! md (
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     $f(a, b, c)
                 })
             }
index c02416bfbea3a6a7be9aa3bb3a6acee938d4149e..f9c8d95b3084840bcafced9e9594fc059e89f9f6 100644 (file)
@@ -38,7 +38,7 @@ macro_rules! md (
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|cx, span, substr| {
+                combine_substructure: combine_substructure(box |cx, span, substr| {
                     cs_op($op, $equal, cx, span, substr)
                 })
             }
@@ -61,7 +61,7 @@ macro_rules! md (
         args: vec![borrowed_self()],
         ret_ty: ret_ty,
         attributes: attrs,
-        combine_substructure: combine_substructure(|cx, span, substr| {
+        combine_substructure: combine_substructure(box |cx, span, substr| {
             cs_partial_cmp(cx, span, substr)
         })
     };
@@ -174,7 +174,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
             cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
         },
         equals_expr.clone(),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`")
             } else {
@@ -222,7 +222,7 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt,
             cx.expr_binary(span, ast::BiOr, cmp, and)
         },
         cx.expr_bool(span, equal),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`")
             } else {
index 2b986bea1221eb67b7ed25898d48183b50bf9b29..cdb36ede65da9e8a9dda5d858c0a6e5855d14151 100644 (file)
@@ -32,7 +32,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
             let block = cx.block(span, stmts, None);
             cx.expr_block(block)
         },
-                       |cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
+                       box |cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
                        cx,
                        span,
                        substr)
@@ -57,7 +57,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
                 args: vec!(),
                 ret_ty: nil_ty(),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     cs_total_eq_assert(a, b, c)
                 })
             }
index 65a4c569b44b64b3cc936164303c9d81d21172b6..10ecc86bda530838016a9950ba01065e1cb10681 100644 (file)
@@ -41,7 +41,7 @@ pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     cs_cmp(a, b, c)
                 }),
             }
@@ -130,7 +130,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
             cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
         },
         cx.expr_path(equals_path.clone()),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
             } else {
index 882136cb86259b411c7840b6a15f3de2eeb5f8aa..8094f0d3de8ccedeb30c92967b1761c69c808be7 100644 (file)
@@ -52,29 +52,31 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
-        path: Path::new_(vec!(krate, "Decodable"), None,
-                         vec!(box Literal(Path::new_local("__D")),
-                              box Literal(Path::new_local("__E"))), true),
+        path: Path::new_(vec!(krate, "Decodable"), None, vec!(), true),
         additional_bounds: Vec::new(),
-        generics: LifetimeBounds {
-            lifetimes: Vec::new(),
-            bounds: vec!(("__D", vec!(Path::new_(
-                            vec!(krate, "Decoder"), None,
-                            vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", vec!()))
-        },
+        generics: LifetimeBounds::empty(),
         methods: vec!(
             MethodDef {
                 name: "decode",
-                generics: LifetimeBounds::empty(),
+                generics: LifetimeBounds {
+                    lifetimes: Vec::new(),
+                    bounds: vec!(("__D", vec!(Path::new_(
+                                    vec!(krate, "Decoder"), None,
+                                    vec!(), true))))
+                },
                 explicit_self: None,
                 args: vec!(Ptr(box Literal(Path::new_local("__D")),
                             Borrowed(None, MutMutable))),
-                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"), None,
-                                          vec!(box Self,
-                                               box Literal(Path::new_local("__E"))), true)),
+                ret_ty: Literal(Path::new_(
+                    vec!("std", "result", "Result"),
+                    None,
+                    vec!(box Self, box Literal(Path::new_(
+                        vec!["__D", "Error"], None, vec![], false
+                    ))),
+                    true
+                )),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     decodable_substructure(a, b, c, krate)
                 }),
             })
index 49bcb26a4c283027ed7e85a679480d18fef459ac..047c4fef3c4f185e95973b7535c25ca0ff13c786 100644 (file)
@@ -40,7 +40,7 @@ pub fn expand_deriving_default<F>(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self,
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     default_substructure(a, b, c)
                 })
             })
index b2c929123d586b6f56478c2bf73e3c790fc6d185..0fceb0fbfdac4774dc0e6d489b9b4f877bd63eeb 100644 (file)
@@ -128,31 +128,31 @@ fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
-        path: Path::new_(vec!(krate, "Encodable"), None,
-                         vec!(box Literal(Path::new_local("__S")),
-                              box Literal(Path::new_local("__E"))), true),
+        path: Path::new_(vec!(krate, "Encodable"), None, vec!(), true),
         additional_bounds: Vec::new(),
-        generics: LifetimeBounds {
-            lifetimes: Vec::new(),
-            bounds: vec!(("__S", vec!(Path::new_(
-                            vec!(krate, "Encoder"), None,
-                            vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", vec!()))
-        },
+        generics: LifetimeBounds::empty(),
         methods: vec!(
             MethodDef {
                 name: "encode",
-                generics: LifetimeBounds::empty(),
+                generics: LifetimeBounds {
+                    lifetimes: Vec::new(),
+                    bounds: vec!(("__S", vec!(Path::new_(
+                                    vec!(krate, "Encoder"), None,
+                                    vec!(), true))))
+                },
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(Ptr(box Literal(Path::new_local("__S")),
                             Borrowed(None, MutMutable))),
-                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"),
-                                           None,
-                                           vec!(box Tuple(Vec::new()),
-                                                box Literal(Path::new_local("__E"))),
-                                           true)),
+                ret_ty: Literal(Path::new_(
+                    vec!("std", "result", "Result"),
+                    None,
+                    vec!(box Tuple(Vec::new()), box Literal(Path::new_(
+                        vec!["__S", "Error"], None, vec![], false
+                    ))),
+                    true
+                )),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     encodable_substructure(a, b, c)
                 }),
             })
index 8863de8757bf7ffb22abddccbb66b71301a59235..1fb8189c63c818769a7a0b9c2df02e264f10b86d 100644 (file)
@@ -312,7 +312,7 @@ pub enum SubstructureFields<'a> {
 /// Combine the values of all the fields together. The last argument is
 /// all the fields of all the structures.
 pub type CombineSubstructureFunc<'a> =
-    |&mut ExtCtxt, Span, &Substructure|: 'a -> P<Expr>;
+    Box<FnMut(&mut ExtCtxt, Span, &Substructure) -> P<Expr> + 'a>;
 
 /// Deal with non-matching enum variants.  The tuple is a list of
 /// identifiers (one for each `Self` argument, which could be any of the
@@ -320,11 +320,7 @@ pub enum SubstructureFields<'a> {
 /// holding the variant index value for each of the `Self` arguments.  The
 /// last argument is all the non-`Self` args of the method being derived.
 pub type EnumNonMatchCollapsedFunc<'a> =
-    |&mut ExtCtxt,
-     Span,
-     (&[Ident], &[Ident]),
-     &[P<Expr>]|: 'a
-     -> P<Expr>;
+    Box<FnMut(&mut ExtCtxt, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
 
 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
     -> RefCell<CombineSubstructureFunc<'a>> {
@@ -488,6 +484,7 @@ fn create_derived_impl(&self,
             ident,
             a,
             ast::ItemImpl(ast::Unsafety::Normal,
+                          ast::ImplPolarity::Positive,
                           trait_generics,
                           opt_trait_ref,
                           self_type,
@@ -605,7 +602,7 @@ fn call_substructure_method(&self,
         };
         let mut f = self.combine_substructure.borrow_mut();
         let f: &mut CombineSubstructureFunc = &mut *f;
-        (*f)(cx, trait_.span, &substructure)
+        f.call_mut((cx, trait_.span, &substructure))
     }
 
     fn get_ret_ty(&self,
@@ -1340,7 +1337,7 @@ fn create_enum_variant_pattern(&self,
 pub fn cs_fold<F>(use_foldl: bool,
                   mut f: F,
                   base: P<Expr>,
-                  enum_nonmatch_f: EnumNonMatchCollapsedFunc,
+                  mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
                   cx: &mut ExtCtxt,
                   trait_span: Span,
                   substructure: &Substructure)
@@ -1368,8 +1365,8 @@ pub fn cs_fold<F>(use_foldl: bool,
             }
         },
         EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (all_args[], tuple),
-                            substructure.nonself_args),
+            enum_nonmatch_f.call_mut((cx, trait_span, (all_args[], tuple),
+                                      substructure.nonself_args)),
         StaticEnum(..) | StaticStruct(..) => {
             cx.span_bug(trait_span, "static function in `derive`")
         }
@@ -1386,7 +1383,7 @@ pub fn cs_fold<F>(use_foldl: bool,
 /// ```
 #[inline]
 pub fn cs_same_method<F>(f: F,
-                         enum_nonmatch_f: EnumNonMatchCollapsedFunc,
+                         mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
                          cx: &mut ExtCtxt,
                          trait_span: Span,
                          substructure: &Substructure)
@@ -1408,8 +1405,8 @@ pub fn cs_same_method<F>(f: F,
             f(cx, trait_span, called)
         },
         EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (all_self_args[], tuple),
-                            substructure.nonself_args),
+            enum_nonmatch_f.call_mut((cx, trait_span, (all_self_args[], tuple),
+                                     substructure.nonself_args)),
         StaticEnum(..) | StaticStruct(..) => {
             cx.span_bug(trait_span, "static function in `derive`")
         }
index 9ff42d85cfbb8ea6e63bc33c252548bc45049dd6..b9acde4bf6be9ac21195a30d6b3ce454fe9fdc7f 100644 (file)
@@ -55,7 +55,7 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
                 args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
                 ret_ty: nil_ty(),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     hash_substructure(a, b, c)
                 })
             }
index 8abd846373ae10264802cbb3a8880f64d644cb37..d36bb2cd1c2aaab29866a3798ce96fb3101bcbbb 100644 (file)
@@ -46,7 +46,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs.clone(),
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_from("i64", c, s, sub)
                 }),
             },
@@ -62,7 +62,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs,
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_from("u64", c, s, sub)
                 }),
             })
index 1ddf5b2a5c31eef8106680a72b9491e4143ba059..5517019f804cebde728cb77cfd2b5f17f98b8219 100644 (file)
@@ -45,7 +45,7 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
                 ),
                 ret_ty: Self,
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     rand_substructure(a, b, c)
                 })
             }
index 0513c75cf57dae41a18394c4903ee0d20ad65899..eceac4e9a8368ff38af02b125baaa07a05b5bb92 100644 (file)
@@ -46,7 +46,7 @@ pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
                 args: vec!(fmtr),
                 ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     show_substructure(a, b, c)
                 })
             }
index e65ecc19ea1bbc7a44a63dc5bda0d53260824bec..b3f30dd4581c9ed6edd5453a7621df805fc61cc7 100644 (file)
@@ -1111,7 +1111,7 @@ fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
 
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         let prev_type = self.current_impl_type.clone();
-        if let ast::Item_::ItemImpl(_, _, _, ref ty, _) = item.node {
+        if let ast::Item_::ItemImpl(_, _, _, _, ref ty, _) = item.node {
             self.current_impl_type = Some(ty.clone());
         }
 
index bac82494f28aaca0780d8f9b24ceba31fe5bf1ee..4075b208f787399d2b8b74e577d09da141188dba 100644 (file)
@@ -21,7 +21,6 @@
 
 use std::cell::RefCell;
 use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
 
 /// The SCTable contains a table of SyntaxContext_'s. It
 /// represents a flattened tree structure, to avoid having
@@ -67,10 +66,9 @@ pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext {
 /// Extend a syntax context with a given mark and sctable (explicit memoization)
 fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext {
     let key = (ctxt, m);
-    * match table.mark_memo.borrow_mut().entry(key) {
-        Vacant(entry) => entry.set(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))),
-        Occupied(entry) => entry.into_mut(),
-    }
+    * table.mark_memo.borrow_mut().entry(&key).get().unwrap_or_else(
+          |vacant_entry|
+              vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))))
 }
 
 /// Extend a syntax context with a given rename
@@ -86,10 +84,9 @@ fn apply_rename_internal(id: Ident,
                        table: &SCTable) -> SyntaxContext {
     let key = (ctxt, id, to);
 
-    * match table.rename_memo.borrow_mut().entry(key) {
-        Vacant(entry) => entry.set(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))),
-        Occupied(entry) => entry.into_mut(),
-    }
+    * table.rename_memo.borrow_mut().entry(&key).get().unwrap_or_else(
+          |vacant_entry|
+              vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))))
 }
 
 /// Apply a list of renamings to a context
index 69e473055e8e45a7be41e6dcf1fd4ddedd2c9efe..1438d152554955662f84513ac87f50fd2f2871ea 100644 (file)
@@ -219,9 +219,9 @@ fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
                 }
             }
             &TtToken(sp, MatchNt(bind_name, _, _, _)) => {
-                match ret_val.entry(bind_name) {
+                match ret_val.entry(&bind_name) {
                     Vacant(spot) => {
-                        spot.set(res[*idx].clone());
+                        spot.insert(res[*idx].clone());
                         *idx += 1;
                     }
                     Occupied(..) => {
index f75873ac1c0f79d1c0cbaa3de741b0727ed5a654..cb6277069e1a2b4ccbf3078c7ee23c04eed185df 100644 (file)
@@ -84,6 +84,9 @@
     // A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
     ("old_orphan_check", Deprecated),
 
+    // OIBIT specific features
+    ("optin_builtin_traits", Active),
+
     // These are used to test this portion of the compiler, they don't actually
     // mean anything
     ("test_accepted_feature", Accepted),
@@ -291,7 +294,17 @@ fn visit_item(&mut self, i: &ast::Item) {
                 }
             }
 
-            ast::ItemImpl(_, _, _, _, ref items) => {
+            ast::ItemImpl(_, polarity, _, _, _, ref items) => {
+                match polarity {
+                    ast::ImplPolarity::Negative => {
+                        self.gate_feature("optin_builtin_traits",
+                                          i.span,
+                                          "negative trait bounds are not yet fully implemented; \
+                                          use marker types for now");
+                    },
+                    _ => {}
+                }
+
                 if attr::contains_name(i.attrs[],
                                        "unsafe_destructor") {
                     self.gate_feature("unsafe_destructor",
@@ -351,12 +364,6 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
     }
 
     fn visit_ty(&mut self, t: &ast::Ty) {
-        if let ast::TyClosure(ref closure) =  t.node {
-            // this used to be blocked by a feature gate, but it should just
-            // be plain impossible right now
-            assert!(closure.onceness != ast::Once);
-        }
-
         visit::walk_ty(self, t);
     }
 
index 3d3068f6868c6a3c5c850a542e8a2445e5f55f1b..396b0033b815fcc58dc9c837bf6e5415d302d8c7 100644 (file)
@@ -414,17 +414,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyRptr(region, mt) => {
                 TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
             }
-            TyClosure(f) => {
-                TyClosure(f.map(|ClosureTy {unsafety, onceness, bounds, decl, lifetimes}| {
-                    ClosureTy {
-                        unsafety: unsafety,
-                        onceness: onceness,
-                        bounds: fld.fold_bounds(bounds),
-                        decl: fld.fold_fn_decl(decl),
-                        lifetimes: fld.fold_lifetime_defs(lifetimes)
-                    }
-                }))
-            }
             TyBareFn(f) => {
                 TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
                     lifetimes: fld.fold_lifetime_defs(lifetimes),
@@ -1014,7 +1003,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(unsafety, generics, ifce, ty, impl_items) => {
+        ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
             let mut new_impl_items = Vec::new();
             for impl_item in impl_items.iter() {
                 match *impl_item {
@@ -1037,6 +1026,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                 }
             };
             ItemImpl(unsafety,
+                     polarity,
                      folder.fold_generics(generics),
                      ifce,
                      folder.fold_ty(ty),
@@ -1166,7 +1156,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
     let node = folder.fold_item_underscore(node);
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
-        ItemImpl(_, _, ref maybe_trait, ref ty, _) => {
+        ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
             ast_util::impl_pretty_name(maybe_trait, &**ty)
         }
         _ => ident
index b87e2c6abbc0c31211271a95d6027ff3b8a18fe3..2a27431a0868cff224bbf2a32e6514cf363749e1 100644 (file)
@@ -82,12 +82,21 @@ fn from_iter<I: Iterator<Item=T>>(iter: I) -> OwnedSlice<T> {
     }
 }
 
+#[cfg(stage0)]
 impl<S: Encoder<E>, T: Encodable<S, E>, E> Encodable<S, E> for OwnedSlice<T> {
     fn encode(&self, s: &mut S) -> Result<(), E> {
        self.as_slice().encode(s)
     }
 }
 
+#[cfg(not(stage0))]
+impl<T: Encodable> Encodable for OwnedSlice<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+       self.as_slice().encode(s)
+    }
+}
+
+#[cfg(stage0)]
 impl<D: Decoder<E>, T: Decodable<D, E>, E> Decodable<D, E> for OwnedSlice<T> {
     fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
         Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
@@ -96,3 +105,13 @@ fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
         }))
     }
 }
+
+#[cfg(not(stage0))]
+impl<T: Decodable> Decodable for OwnedSlice<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<OwnedSlice<T>, D::Error> {
+        Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
+            Ok(t) => t,
+            Err(e) => return Err(e)
+        }))
+    }
+}
index e1e456f880ed7020d356fc4f8e645a0d2a7f31be..75b2c17b81bd487512fc8013d7380d2c86e15f66 100644 (file)
@@ -34,6 +34,7 @@ pub enum ObsoleteSyntax {
     ObsoleteExternCrateRenaming,
     ObsoleteProcType,
     ObsoleteProcExpr,
+    ObsoleteClosureType,
 }
 
 pub trait ParserObsoleteMethods {
@@ -94,6 +95,10 @@ fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
             ObsoleteExternCrateRenaming => (
                 "`extern crate foo = bar` syntax",
                 "write `extern crate bar as foo` instead"
+            ),
+            ObsoleteClosureType => (
+                "`|uint| -> bool` closure type syntax",
+                "use unboxed closures instead, no type annotation needed"
             )
         };
 
index 37ac86a33242e54e26ec80233add9c034ccf902f..8e4a385923ab548182854701078409a4c5c451b6 100644 (file)
@@ -14,7 +14,7 @@
 use self::ItemOrViewItem::*;
 
 use abi;
-use ast::{AssociatedType, BareFnTy, ClosureTy};
+use ast::{AssociatedType, BareFnTy};
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
@@ -30,7 +30,6 @@
 use ast::{ExprMethodCall, ExprParen, ExprPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
-use ast::{Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
@@ -55,7 +54,7 @@
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 use ast::{TtDelimited, TtSequence, TtToken};
 use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
-use ast::{TypeField, TyFixedLengthVec, TyClosure, TyBareFn};
+use ast::{TypeField, TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
@@ -1227,38 +1226,29 @@ pub fn parse_ty_closure(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_
 
         */
 
-        let unsafety = self.parse_unsafety();
+        let ty_closure_span = self.last_span;
 
-        let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
+        // To be helpful, parse the closure type as ever
+        let _ = self.parse_unsafety();
 
-        let inputs = if self.eat(&token::OrOr) {
-            Vec::new()
-        } else {
+        let _ = self.parse_legacy_lifetime_defs(lifetime_defs);
+
+        if !self.eat(&token::OrOr) {
             self.expect_or();
 
-            let inputs = self.parse_seq_to_before_or(
+            let _ = self.parse_seq_to_before_or(
                 &token::Comma,
                 |p| p.parse_arg_general(false));
             self.expect_or();
-            inputs
-        };
+        }
 
-        let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
+        let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
 
-        let output = self.parse_ret_ty();
-        let decl = P(FnDecl {
-            inputs: inputs,
-            output: output,
-            variadic: false
-        });
+        let _ = self.parse_ret_ty();
 
-        TyClosure(P(ClosureTy {
-            unsafety: unsafety,
-            onceness: Many,
-            bounds: bounds,
-            decl: decl,
-            lifetimes: lifetime_defs,
-        }))
+        self.obsolete(ty_closure_span, ObsoleteClosureType);
+
+        TyInfer
     }
 
     pub fn parse_unsafety(&mut self) -> Unsafety {
@@ -2976,14 +2966,17 @@ pub fn parse_more_binops(&mut self, lhs: P<Expr>, min_prec: uint) -> P<Expr> {
     /// actually, this seems to be the main entry point for
     /// parsing an arbitrary expression.
     pub fn parse_assign_expr(&mut self) -> P<Expr> {
-        let lo = self.span.lo;
         let lhs = self.parse_binops();
+        self.parse_assign_expr_with(lhs)
+    }
+
+    pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> P<Expr> {
         let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
         match self.token {
           token::Eq => {
               self.bump();
               let rhs = self.parse_expr_res(restrictions);
-              self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs))
+              self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs))
           }
           token::BinOpEq(op) => {
               self.bump();
@@ -3001,8 +2994,9 @@ pub fn parse_assign_expr(&mut self) -> P<Expr> {
                   token::Shr =>     BiShr
               };
               let rhs_span = rhs.span;
+              let span = lhs.span;
               let assign_op = self.mk_assign_op(aop, lhs, rhs);
-              self.mk_expr(lo, rhs_span.hi, assign_op)
+              self.mk_expr(span.lo, rhs_span.hi, assign_op)
           }
           _ => {
               lhs
@@ -3896,8 +3890,9 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
                                     let e = self.mk_mac_expr(span.lo,
                                                              span.hi,
                                                              macro.and_then(|m| m.node));
-                                    let e =
-                                        self.parse_dot_or_call_expr_with(e);
+                                    let e = self.parse_dot_or_call_expr_with(e);
+                                    let e = self.parse_more_binops(e, 0);
+                                    let e = self.parse_assign_expr_with(e);
                                     self.handle_expression_like_statement(
                                         e,
                                         ast::DUMMY_NODE_ID,
@@ -4801,6 +4796,13 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         // allow this to be parsed as a trait.
         let could_be_trait = self.token != token::OpenDelim(token::Paren);
 
+        let neg_span = self.span;
+        let polarity = if self.eat(&token::Not) {
+            ast::ImplPolarity::Negative
+        } else {
+            ast::ImplPolarity::Positive
+        };
+
         // Parse the trait.
         let mut ty = self.parse_ty_sum();
 
@@ -4823,6 +4825,14 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
             ty = self.parse_ty_sum();
             opt_trait_ref
         } else {
+            match polarity {
+                ast::ImplPolarity::Negative => {
+                    // This is a negated type implementation
+                    // `impl !MyType {}`, which is not allowed.
+                    self.span_err(neg_span, "inherent implementation can't be negated");
+                },
+                _ => {}
+            }
             None
         };
 
@@ -4832,7 +4842,7 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
         (ident,
-         ItemImpl(unsafety, generics, opt_trait, ty, impl_items),
+         ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
          Some(attrs))
     }
 
@@ -4875,67 +4885,116 @@ fn parse_item_struct(&mut self) -> ItemInfo {
             self.span_err(ty.span, "`virtual` structs have been removed from the language");
         }
 
-        self.parse_where_clause(&mut generics);
+        // There is a special case worth noting here, as reported in issue #17904.
+        // If we are parsing a tuple struct it is the case that the where clause
+        // should follow the field list. Like so:
+        //
+        // struct Foo<T>(T) where T: Copy;
+        //
+        // If we are parsing a normal record-style struct it is the case
+        // that the where clause comes before the body, and after the generics.
+        // So if we look ahead and see a brace or a where-clause we begin
+        // parsing a record style struct.
+        //
+        // Otherwise if we look ahead and see a paren we parse a tuple-style
+        // struct.
+
+        let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) {
+            self.parse_where_clause(&mut generics);
+            if self.eat(&token::Semi) {
+                // If we see a: `struct Foo<T> where T: Copy;` style decl.
+                (Vec::new(), Some(ast::DUMMY_NODE_ID))
+            } else {
+                // If we see: `struct Foo<T> where T: Copy { ... }`
+                (self.parse_record_struct_body(&class_name), None)
+            }
+        // No `where` so: `struct Foo<T>;`
+        } else if self.eat(&token::Semi) {
+            (Vec::new(), Some(ast::DUMMY_NODE_ID))
+        // Record-style struct definition
+        } else if self.token == token::OpenDelim(token::Brace) {
+            let fields = self.parse_record_struct_body(&class_name);
+            (fields, None)
+        // Tuple-style struct definition with optional where-clause.
+        } else {
+            let fields = self.parse_tuple_struct_body(&class_name, &mut generics);
+            (fields, Some(ast::DUMMY_NODE_ID))
+        };
 
-        let mut fields: Vec<StructField>;
-        let is_tuple_like;
+        (class_name,
+         ItemStruct(P(ast::StructDef {
+             fields: fields,
+             ctor_id: ctor_id,
+         }), generics),
+         None)
+    }
 
+    pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec<StructField> {
+        let mut fields = Vec::new();
         if self.eat(&token::OpenDelim(token::Brace)) {
-            // It's a record-like struct.
-            is_tuple_like = false;
-            fields = Vec::new();
             while self.token != token::CloseDelim(token::Brace) {
                 fields.push(self.parse_struct_decl_field(true));
             }
+
             if fields.len() == 0 {
                 self.fatal(format!("unit-like struct definition should be \
-                                    written as `struct {};`",
-                                   token::get_ident(class_name))[]);
+                    written as `struct {};`",
+                    token::get_ident(class_name.clone()))[]);
             }
+
             self.bump();
-        } else if self.check(&token::OpenDelim(token::Paren)) {
-            // It's a tuple-like struct.
-            is_tuple_like = true;
-            fields = self.parse_unspanned_seq(
+        } else {
+            let token_str = self.this_token_to_string();
+            self.fatal(format!("expected `where`, or `{}` after struct \
+                                name, found `{}`", "{",
+                                token_str)[]);
+        }
+
+        fields
+    }
+
+    pub fn parse_tuple_struct_body(&mut self,
+                                   class_name: &ast::Ident,
+                                   generics: &mut ast::Generics)
+                                   -> Vec<StructField> {
+        // This is the case where we find `struct Foo<T>(T) where T: Copy;`
+        if self.check(&token::OpenDelim(token::Paren)) {
+            let fields = self.parse_unspanned_seq(
                 &token::OpenDelim(token::Paren),
                 &token::CloseDelim(token::Paren),
                 seq_sep_trailing_allowed(token::Comma),
                 |p| {
-                let attrs = p.parse_outer_attributes();
-                let lo = p.span.lo;
-                let struct_field_ = ast::StructField_ {
-                    kind: UnnamedField(p.parse_visibility()),
-                    id: ast::DUMMY_NODE_ID,
-                    ty: p.parse_ty_sum(),
-                    attrs: attrs,
-                };
-                spanned(lo, p.span.hi, struct_field_)
-            });
+                    let attrs = p.parse_outer_attributes();
+                    let lo = p.span.lo;
+                    let struct_field_ = ast::StructField_ {
+                        kind: UnnamedField(p.parse_visibility()),
+                        id: ast::DUMMY_NODE_ID,
+                        ty: p.parse_ty_sum(),
+                        attrs: attrs,
+                    };
+                    spanned(lo, p.span.hi, struct_field_)
+                });
+
             if fields.len() == 0 {
                 self.fatal(format!("unit-like struct definition should be \
-                                    written as `struct {};`",
-                                   token::get_ident(class_name))[]);
+                    written as `struct {};`",
+                    token::get_ident(class_name.clone()))[]);
             }
+
+            self.parse_where_clause(generics);
             self.expect(&token::Semi);
-        } else if self.eat(&token::Semi) {
-            // It's a unit-like struct.
-            is_tuple_like = true;
-            fields = Vec::new();
+            fields
+        // This is the case where we just see struct Foo<T> where T: Copy;
+        } else if self.token.is_keyword(keywords::Where) {
+            self.parse_where_clause(generics);
+            self.expect(&token::Semi);
+            Vec::new()
+        // This case is where we see: `struct Foo<T>;`
         } else {
             let token_str = self.this_token_to_string();
-            self.fatal(format!("expected `{}`, `(`, or `;` after struct \
-                                name, found `{}`", "{",
-                               token_str)[])
+            self.fatal(format!("expected `where`, `{}`, `(`, or `;` after struct \
+                name, found `{}`", "{", token_str)[]);
         }
-
-        let _ = ast::DUMMY_NODE_ID;  // FIXME: Workaround for crazy bug.
-        let new_id = ast::DUMMY_NODE_ID;
-        (class_name,
-         ItemStruct(P(ast::StructDef {
-             fields: fields,
-             ctor_id: if is_tuple_like { Some(new_id) } else { None },
-         }), generics),
-         None)
     }
 
     /// Parse a structure field declaration
index 4bfcc94a083d4c03f29fc6a118a4dbf1b75ab888..b7e89b32b709e6f3c73cb20e5e6da9c1260ca3fe 100644 (file)
@@ -653,6 +653,7 @@ fn ne(&self, other: &InternedString) -> bool {
     }
 }
 
+#[cfg(stage0)]
 impl<D:Decoder<E>, E> Decodable<D, E> for InternedString {
     fn decode(d: &mut D) -> Result<InternedString, E> {
         Ok(get_name(get_ident_interner().intern(
@@ -660,12 +661,28 @@ fn decode(d: &mut D) -> Result<InternedString, E> {
     }
 }
 
+#[cfg(not(stage0))]
+impl Decodable for InternedString {
+    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
+        Ok(get_name(get_ident_interner().intern(
+                    try!(d.read_str())[])))
+    }
+}
+
+#[cfg(stage0)]
 impl<S:Encoder<E>, E> Encodable<S, E> for InternedString {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_str(self.string[])
     }
 }
 
+#[cfg(not(stage0))]
+impl Encodable for InternedString {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(self.string[])
+    }
+}
+
 /// Returns the string contents of a name, using the task-local interner.
 #[inline]
 pub fn get_name(name: ast::Name) -> InternedString {
index 9702c79719c64ac62b20dd53fb3e8af0972d411d..effd6e8218d25fd38cbbd62cee3457697e276239 100644 (file)
@@ -714,25 +714,6 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       Some(&generics),
                                       None));
             }
-            ast::TyClosure(ref f) => {
-                let generics = ast::Generics {
-                    lifetimes: f.lifetimes.clone(),
-                    ty_params: OwnedSlice::empty(),
-                    where_clause: ast::WhereClause {
-                        id: ast::DUMMY_NODE_ID,
-                        predicates: Vec::new(),
-                    },
-                };
-                try!(self.print_ty_fn(None,
-                                      Some('&'),
-                                      f.unsafety,
-                                      f.onceness,
-                                      &*f.decl,
-                                      None,
-                                      &f.bounds,
-                                      Some(&generics),
-                                      None));
-            }
             ast::TyPath(ref path, _) => {
                 try!(self.print_path(path, false));
             }
@@ -917,6 +898,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
             }
 
             ast::ItemImpl(unsafety,
+                          polarity,
                           ref generics,
                           ref opt_trait,
                           ref ty,
@@ -931,6 +913,13 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
                     try!(space(&mut self.s));
                 }
 
+                match polarity {
+                    ast::ImplPolarity::Negative => {
+                        try!(word(&mut self.s, "!"));
+                    },
+                    _ => {}
+                }
+
                 match opt_trait {
                     &Some(ref t) => {
                         try!(self.print_trait_ref(t));
@@ -1067,7 +1056,6 @@ pub fn print_struct(&mut self,
                         span: codemap::Span) -> IoResult<()> {
         try!(self.print_ident(ident));
         try!(self.print_generics(generics));
-        try!(self.print_where_clause(generics));
         if ast_util::struct_def_is_tuple_like(struct_def) {
             if !struct_def.fields.is_empty() {
                 try!(self.popen());
@@ -1086,10 +1074,12 @@ pub fn print_struct(&mut self,
                 ));
                 try!(self.pclose());
             }
+            try!(self.print_where_clause(generics));
             try!(word(&mut self.s, ";"));
             try!(self.end());
             self.end() // close the outer-box
         } else {
+            try!(self.print_where_clause(generics));
             try!(self.nbsp());
             try!(self.bopen());
             try!(self.hardbreak_if_not_bol());
index 6eee1d903ea642fec7652cbddc303c641a3b2f50..13eda7bb88f05eb48b05824d912bb240c85f31c4 100644 (file)
@@ -111,14 +111,30 @@ fn hash(&self, state: &mut S) {
     }
 }
 
+#[cfg(stage0)]
 impl<E, D: Decoder<E>, T: 'static + Decodable<D, E>> Decodable<D, E> for P<T> {
     fn decode(d: &mut D) -> Result<P<T>, E> {
         Decodable::decode(d).map(P)
     }
 }
 
+#[cfg(not(stage0))]
+impl<T: 'static + Decodable> Decodable for P<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
+        Decodable::decode(d).map(P)
+    }
+}
+
+#[cfg(stage0)]
 impl<E, S: Encoder<E>, T: Encodable<S, E>> Encodable<S, E> for P<T> {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         (**self).encode(s)
     }
 }
+
+#[cfg(not(stage0))]
+impl<T: Encodable> Encodable for P<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
index 354ba854b101aa7906f2d9131d8aa3c9a4134ba3..51d655ec0f2c5075070a48299c7af70402b6d537 100644 (file)
 //! This module shows spans for all expressions in the crate
 //! to help with compiler debugging.
 
+use std::str::FromStr;
+
 use ast;
 use diagnostic;
 use visit;
 use visit::Visitor;
 
+enum Mode {
+    Expression,
+    Pattern,
+    Type,
+}
+
+impl FromStr for Mode {
+    fn from_str(s: &str) -> Option<Mode> {
+        let mode = match s {
+            "expr" => Mode::Expression,
+            "pat" => Mode::Pattern,
+            "ty" => Mode::Type,
+            _ => return None
+        };
+        Some(mode)
+    }
+}
+
 struct ShowSpanVisitor<'a> {
     span_diagnostic: &'a diagnostic::SpanHandler,
+    mode: Mode,
 }
 
 impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> {
     fn visit_expr(&mut self, e: &ast::Expr) {
-        self.span_diagnostic.span_note(e.span, "expression");
+        if let Mode::Expression = self.mode {
+            self.span_diagnostic.span_note(e.span, "expression");
+        }
         visit::walk_expr(self, e);
     }
 
+    fn visit_pat(&mut self, p: &ast::Pat) {
+        if let Mode::Pattern = self.mode {
+            self.span_diagnostic.span_note(p.span, "pattern");
+        }
+        visit::walk_pat(self, p);
+    }
+
+    fn visit_ty(&mut self, t: &ast::Ty) {
+        if let Mode::Type = self.mode {
+            self.span_diagnostic.span_note(t.span, "type");
+        }
+        visit::walk_ty(self, t);
+    }
+
     fn visit_mac(&mut self, macro: &ast::Mac) {
         visit::walk_mac(self, macro);
     }
 }
 
-pub fn run(span_diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate) {
-    let mut v = ShowSpanVisitor { span_diagnostic: span_diagnostic };
+pub fn run(span_diagnostic: &diagnostic::SpanHandler,
+           mode: &str,
+           krate: &ast::Crate) {
+    let mode = match mode.parse() {
+        Some(mode) => mode,
+        None => return
+    };
+    let mut v = ShowSpanVisitor {
+        span_diagnostic: span_diagnostic,
+        mode: mode,
+    };
     visit::walk_crate(&mut v, krate);
 }
index ec6b2cfa5c39624fa8610e1b53df0512c0eb6f6c..737f1b73b32907eba034eb585e9ae33e6c278288 100644 (file)
@@ -297,7 +297,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_enum_def(visitor, enum_definition, type_parameters)
         }
-        ItemImpl(_,
+        ItemImpl(_, _,
                  ref type_parameters,
                  ref trait_reference,
                  ref typ,
@@ -404,14 +404,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
                 visitor.visit_ty(&**tuple_element_type)
             }
         }
-        TyClosure(ref function_declaration) => {
-            for argument in function_declaration.decl.inputs.iter() {
-                visitor.visit_ty(&*argument.ty)
-            }
-            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
-            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
-        }
         TyBareFn(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
index 4bac20dd67c06a5ec1af2ae13728387b520bfb6c..3fb2211eff23a367464e4525b15ac3c83a1e230a 100644 (file)
@@ -58,7 +58,7 @@
 use term::Terminal;
 use term::color::{Color, RED, YELLOW, GREEN, CYAN};
 
-use std::any::{Any, AnyRefExt};
+use std::any::Any;
 use std::cmp;
 use std::collections::BTreeMap;
 use std::f64;
index 35af0e763d7dd0711d8b3bfa8020c7fffcaed900..7e7f36f6e83fae1dbdf79b71caeffea8ff3b522b 100644 (file)
@@ -438,12 +438,14 @@ pub fn write_boxplot<W: Writer, T: Float + Show + FromPrimitive>(
 
 /// Returns a HashMap with the number of occurrences of every element in the
 /// sequence that the iterator exposes.
-pub fn freq_count<T: Iterator<Item=U>, U: Eq+Hash>(mut iter: T) -> hash_map::HashMap<U, uint> {
+pub fn freq_count<T, U>(mut iter: T) -> hash_map::HashMap<U, uint>
+  where T: Iterator<Item=U>, U: Eq + Clone + Hash
+{
     let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
     for elem in iter {
-        match map.entry(elem) {
+        match map.entry(&elem) {
             Occupied(mut entry) => { *entry.get_mut() += 1; },
-            Vacant(entry) => { entry.set(1); },
+            Vacant(entry) => { entry.insert(1); },
         }
     }
     map
index 72e9ce2bcafe64fb9b8e9e3825f1db2ef8cd43e1..a3884d0c86e1de78a708508117d6a611e598b3c1 100644 (file)
@@ -44,9 +44,9 @@
 // re-export char so that std et al see it correctly
 /// Character manipulation (`char` type, Unicode Scalar Value)
 ///
-/// This module  provides the `Char` and `UnicodeChar` traits, as well as their
-/// implementation for the primitive `char` type, in order to allow basic character
-/// manipulation.
+/// This module provides the `CharExt` trait, as well as its
+/// implementation for the primitive `char` type, in order to allow
+/// basic character manipulation.
 ///
 /// A `char` actually represents a
 /// *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*,
 /// however the converse is not always true due to the above range limits
 /// and, as such, should be performed via the `from_u32` function..
 pub mod char {
-    pub use core::char::{MAX, from_u32};
-    pub use core::char::{from_digit};
-    pub use core::char::Char;
+    pub use core::char::{MAX, from_u32, from_digit};
 
     pub use normalize::{decompose_canonical, decompose_compatible, compose};
 
     pub use tables::normalization::canonical_combining_class;
     pub use tables::UNICODE_VERSION;
 
-    pub use u_char::UnicodeChar;
+    pub use u_char::CharExt;
 }
 
 pub mod str {
index e3550810010b5db482919b044769810602100445..c755ea93184028fb9f068c2a0b83a902ddbd1752 100644 (file)
@@ -13,7 +13,7 @@
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
 /// The version of [Unicode](http://www.unicode.org/)
-/// that the `UnicodeChar` and `UnicodeStrPrelude` traits are based on.
+/// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on.
 pub const UNICODE_VERSION: (uint, uint, uint) = (7, 0, 0);
 
 fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
index 9c356801604dd44fd95c671eb127f511c526255d..5693c222de123262b874b37e9d5e737eaab80332 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unicode-intensive `char` methods.
+//! Unicode-intensive `char` methods along with the `core` methods.
 //!
 //! These methods implement functionality for `char` that requires knowledge of
 //! Unicode definitions, including normalization, categorization, and display information.
 
+use core::char;
+use core::char::CharExt as C;
 use core::option::Option;
 use tables::{derived_property, property, general_category, conversions, charwidth};
 
-/// Useful functions for Unicode characters.
-#[experimental = "pending prelude organization"]
-pub trait UnicodeChar {
+/// Functionality for manipulating `char`.
+#[stable]
+pub trait CharExt {
+    /// Checks if a `char` parses as a numeric digit in the given radix.
+    ///
+    /// Compared to `is_numeric()`, this function only recognizes the characters
+    /// `0-9`, `a-z` and `A-Z`.
+    ///
+    /// # Return value
+    ///
+    /// Returns `true` if `c` is a valid digit under `radix`, and `false`
+    /// otherwise.
+    ///
+    /// # Panics
+    ///
+    /// Panics if given a radix > 36.
+    #[unstable = "pending integer conventions"]
+    fn is_digit(self, radix: uint) -> bool;
+
+    /// Converts a character to the corresponding digit.
+    ///
+    /// # Return value
+    ///
+    /// If `c` is between '0' and '9', the corresponding value between 0 and
+    /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
+    /// none if the character does not refer to a digit in the given radix.
+    ///
+    /// # Panics
+    ///
+    /// Panics if given a radix outside the range [0..36].
+    #[unstable = "pending integer conventions"]
+    fn to_digit(self, radix: uint) -> Option<uint>;
+
+    /// Returns an iterator that yields the hexadecimal Unicode escape
+    /// of a character, as `char`s.
+    ///
+    /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
+    /// where `NNNN` is the shortest hexadecimal representation of the code
+    /// point.
+    #[stable]
+    fn escape_unicode(self) -> char::EscapeUnicode;
+
+    /// Returns an iterator that yields the 'default' ASCII and
+    /// C++11-like literal escape of a character, as `char`s.
+    ///
+    /// The default is chosen with a bias toward producing literals that are
+    /// legal in a variety of languages, including C++11 and similar C-family
+    /// languages. The exact rules are:
+    ///
+    /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
+    /// * Single-quote, double-quote and backslash chars are backslash-
+    ///   escaped.
+    /// * Any other chars in the range [0x20,0x7e] are not escaped.
+    /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
+    #[stable]
+    fn escape_default(self) -> char::EscapeDefault;
+
+    /// Returns the amount of bytes this character would need if encoded in
+    /// UTF-8.
+    #[stable]
+    fn len_utf8(self) -> uint;
+
+    /// Returns the amount of bytes this character would need if encoded in
+    /// UTF-16.
+    #[stable]
+    fn len_utf16(self) -> uint;
+
+    /// Encodes this character as UTF-8 into the provided byte buffer,
+    /// and then returns the number of bytes written.
+    ///
+    /// If the buffer is not large enough, nothing will be written into it
+    /// and a `None` will be returned.
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf8(self, dst: &mut [u8]) -> Option<uint>;
+
+    /// Encodes this character as UTF-16 into the provided `u16` buffer,
+    /// and then returns the number of `u16`s written.
+    ///
+    /// If the buffer is not large enough, nothing will be written into it
+    /// and a `None` will be returned.
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf16(self, dst: &mut [u16]) -> Option<uint>;
+
     /// Returns whether the specified character is considered a Unicode
     /// alphabetic code point.
+    #[stable]
     fn is_alphabetic(self) -> bool;
 
     /// Returns whether the specified character satisfies the 'XID_Start'
@@ -29,6 +112,7 @@ pub trait UnicodeChar {
     /// 'XID_Start' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to ID_Start but modified for closure under NFKx.
+    #[experimental = "mainly needed for compiler internals"]
     fn is_xid_start(self) -> bool;
 
     /// Returns whether the specified `char` satisfies the 'XID_Continue'
@@ -37,38 +121,45 @@ pub trait UnicodeChar {
     /// 'XID_Continue' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
+    #[experimental = "mainly needed for compiler internals"]
     fn is_xid_continue(self) -> bool;
 
     /// Indicates whether a character is in lowercase.
     ///
     /// This is defined according to the terms of the Unicode Derived Core
     /// Property `Lowercase`.
+    #[stable]
     fn is_lowercase(self) -> bool;
 
     /// Indicates whether a character is in uppercase.
     ///
     /// This is defined according to the terms of the Unicode Derived Core
     /// Property `Uppercase`.
+    #[stable]
     fn is_uppercase(self) -> bool;
 
     /// Indicates whether a character is whitespace.
     ///
     /// Whitespace is defined in terms of the Unicode Property `White_Space`.
+    #[stable]
     fn is_whitespace(self) -> bool;
 
     /// Indicates whether a character is alphanumeric.
     ///
     /// Alphanumericness is defined in terms of the Unicode General Categories
     /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
+    #[stable]
     fn is_alphanumeric(self) -> bool;
 
     /// Indicates whether a character is a control code point.
     ///
     /// Control code points are defined in terms of the Unicode General
     /// Category `Cc`.
+    #[stable]
     fn is_control(self) -> bool;
 
     /// Indicates whether the character is numeric (Nd, Nl, or No).
+    #[stable]
     fn is_numeric(self) -> bool;
 
     /// Converts a character to its lowercase equivalent.
@@ -80,6 +171,7 @@ pub trait UnicodeChar {
     ///
     /// Returns the lowercase equivalent of the character, or the character
     /// itself if no conversion is possible.
+    #[experimental = "pending case transformation decisions"]
     fn to_lowercase(self) -> char;
 
     /// Converts a character to its uppercase equivalent.
@@ -102,6 +194,7 @@ pub trait UnicodeChar {
     /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
     ///
     /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
+    #[experimental = "pending case transformation decisions"]
     fn to_uppercase(self) -> char;
 
     /// Returns this character's displayed width in columns, or `None` if it is a
@@ -117,8 +210,26 @@ pub trait UnicodeChar {
     fn width(self, is_cjk: bool) -> Option<uint>;
 }
 
-#[experimental = "pending prelude organization"]
-impl UnicodeChar for char {
+#[stable]
+impl CharExt for char {
+    #[unstable = "pending integer conventions"]
+    fn is_digit(self, radix: uint) -> bool { C::is_digit(self, radix) }
+    #[unstable = "pending integer conventions"]
+    fn to_digit(self, radix: uint) -> Option<uint> { C::to_digit(self, radix) }
+    #[stable]
+    fn escape_unicode(self) -> char::EscapeUnicode { C::escape_unicode(self) }
+    #[stable]
+    fn escape_default(self) -> char::EscapeDefault { C::escape_default(self) }
+    #[stable]
+    fn len_utf8(self) -> uint { C::len_utf8(self) }
+    #[stable]
+    fn len_utf16(self) -> uint { C::len_utf16(self) }
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> { C::encode_utf8(self, dst) }
+    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    fn encode_utf16(self, dst: &mut [u16]) -> Option<uint> { C::encode_utf16(self, dst) }
+
+    #[stable]
     fn is_alphabetic(self) -> bool {
         match self {
             'a' ... 'z' | 'A' ... 'Z' => true,
@@ -127,10 +238,13 @@ fn is_alphabetic(self) -> bool {
         }
     }
 
+    #[experimental = "mainly needed for compiler internals"]
     fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
 
+    #[experimental = "mainly needed for compiler internals"]
     fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
 
+    #[stable]
     fn is_lowercase(self) -> bool {
         match self {
             'a' ... 'z' => true,
@@ -139,6 +253,7 @@ fn is_lowercase(self) -> bool {
         }
     }
 
+    #[stable]
     fn is_uppercase(self) -> bool {
         match self {
             'A' ... 'Z' => true,
@@ -147,6 +262,7 @@ fn is_uppercase(self) -> bool {
         }
     }
 
+    #[stable]
     fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09' ... '\x0d' => true,
@@ -155,12 +271,15 @@ fn is_whitespace(self) -> bool {
         }
     }
 
+    #[stable]
     fn is_alphanumeric(self) -> bool {
         self.is_alphabetic() || self.is_numeric()
     }
 
+    #[stable]
     fn is_control(self) -> bool { general_category::Cc(self) }
 
+    #[stable]
     fn is_numeric(self) -> bool {
         match self {
             '0' ... '9' => true,
@@ -169,8 +288,10 @@ fn is_numeric(self) -> bool {
         }
     }
 
+    #[experimental = "pending case transformation decisions"]
     fn to_lowercase(self) -> char { conversions::to_lower(self) }
 
+    #[experimental = "pending case transformation decisions"]
     fn to_uppercase(self) -> char { conversions::to_upper(self) }
 
     #[experimental = "needs expert opinion. is_cjk flag stands out as ugly"]
index 1b0c4171134ed03631ab2a1b394adcfc5e603d9c..90949437774f107c3f1aa463af994ed7f2ce9170 100644 (file)
@@ -13,7 +13,7 @@
 //! Unicode-intensive string manipulations.
 //!
 //! This module provides functionality to `str` that requires the Unicode methods provided by the
-//! UnicodeChar trait.
+//! unicode parts of the CharExt trait.
 
 use self::GraphemeState::*;
 use core::prelude::*;
@@ -26,7 +26,7 @@
 use core::slice;
 use core::str::Split;
 
-use u_char::UnicodeChar;
+use u_char::CharExt as UCharExt; // conflicts with core::prelude::CharExt
 use tables::grapheme::GraphemeCat;
 
 /// An iterator over the words of a string, separated by a sequence of whitespace
@@ -529,7 +529,7 @@ fn next(&mut self) -> Option<u16> {
 
         let mut buf = [0u16; 2];
         self.chars.next().map(|ch| {
-            let n = ch.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
+            let n = CharExt::encode_utf16(ch, buf.as_mut_slice()).unwrap_or(0);
             if n == 2 { self.extra = buf[1]; }
             buf[0]
         })
index ec1fdb3b9d3b1fb9e1dae97a65dd3a13db9bfb23..b820135911e17c7a46b901db56baa48e5155bf46 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit ec1fdb3b9d3b1fb9e1dae97a65dd3a13db9bfb23
+Subproject commit b820135911e17c7a46b901db56baa48e5155bf46
index 3a37981744a5af2433fed551f742465c78c9af7f..b5ac4cd44321da10dfd70f070dbc9094ca3f92ff 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3a37981744a5af2433fed551f742465c78c9af7f
+Subproject commit b5ac4cd44321da10dfd70f070dbc9094ca3f92ff
index c1ad6754ca1c36e877c5264f4448b291aca2dd9b..2ac855681f28b9970b1b95e770552532a30149c5 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-01-03
+2015-01-05
index c72fd7978f88588f4dfcf8e43a1059f7c2a984ea..5c21a8a8abfb0c3615031b8bc01b7f7044abfdc9 100644 (file)
@@ -1,3 +1,12 @@
+S 2015-01-04 b2085d9
+  freebsd-x86_64 50ccb6bf9c0645d0746a5167493a39b2be40c2d4
+  linux-i386 b880b98d832c9a049b8ef6a50df50061e363de5a
+  linux-x86_64 82a09c162474b69d2d1e4e8399086f3f0f4e31c3
+  macos-i386 569055bb10d96ab25f78ecf2c80ffbccd5e69b8d
+  macos-x86_64 cff1f9ebd63dae6890359b7d353bd9486d8ecdfc
+  winnt-i386 553790fe493413287a19d17a42bf7225d3e2272d
+  winnt-x86_64 bab0d13960afb7ccdd6bf11452de1b9c457cc3e9
+
 S 2015-01-02 c894171
   freebsd-x86_64 ea8bcf75eada3539f5cbab51708eecf40d436b77
   linux-i386 646ae265721e3cbe19404aae4fea4ffa1f1d90cf
index 40a9a52061fe5a97066ce9f293e03bca142c7523..3b1857f9ccb698efb9c5a925cf979d488d596aff 100644 (file)
 #![crate_name="cci_impl_lib"]
 
 pub trait uint_helpers {
-    fn to(&self, v: uint, f: |uint|);
+    fn to<F>(&self, v: uint, f: F) where F: FnMut(uint);
 }
 
 impl uint_helpers for uint {
     #[inline]
-    fn to(&self, v: uint, f: |uint|) {
+    fn to<F>(&self, v: uint, mut f: F) where F: FnMut(uint) {
         let mut i = *self;
         while i < v {
             f(i);
index 84ade3572f95c158256735b2e897b3e7b3dda011..3ba068df058b3d79003108ea03b9a60230675f56 100644 (file)
@@ -11,7 +11,7 @@
 #![crate_name="cci_iter_lib"]
 
 #[inline]
-pub fn iter<T>(v: &[T], f: |&T|) {
+pub fn iter<T, F>(v: &[T], mut f: F) where F: FnMut(&T) {
     let mut i = 0u;
     let n = v.len();
     while i < n {
index 67f55cca1e16b78b688cb35c84421306733a0982..474925d8838b5214ea45ae3e2ab38709b2e18f6a 100644 (file)
@@ -12,7 +12,7 @@
 
 
 // same as cci_iter_lib, more-or-less, but not marked inline
-pub fn iter(v: Vec<uint> , f: |uint|) {
+pub fn iter<F>(v: Vec<uint> , mut f: F) where F: FnMut(uint) {
     let mut i = 0u;
     let n = v.len();
     while i < n {
index 37edcdf7628988b6e7419de9a548723ae32be76e..690d5783c4bc2b6b7ca7a0ffab26696eb1a18fbd 100644 (file)
 
 // part of issue-6919.rs
 
-pub struct C<'a> {
-    pub k: ||: 'a,
+pub struct C<K> where K: FnOnce() {
+    pub k: K,
 }
 
 fn no_op() { }
-pub const D : C<'static> = C {
-    k: no_op
+pub const D : C<fn()> = C {
+    k: no_op as fn()
 };
 
index 961dad000914a0dfa3022b5520676bd81ba5e2bf..c2820a8d4ae5de075ec0896941cfdcec7229ffef 100644 (file)
@@ -21,7 +21,6 @@ pub fn type_ids() -> Vec<TypeId> {
         ids.push(TypeId::of::<FooEnum>());
         ids.push(TypeId::of::<FooUniq>());
         ids.push(TypeId::of::<FooPtr>());
-        ids.push(TypeId::of::<FooClosure>());
         ids.push(TypeId::of::<&'static FooTrait>());
         ids.push(TypeId::of::<FooStruct>());
         ids.push(TypeId::of::<FooTuple>());
@@ -68,9 +67,6 @@ pub enum FooEnum {
 
     // Skipping ty_bare_fn (how do you get a bare function type, rather than proc or closure?)
 
-    // Tests ty_closure (does not test all types of closures)
-    pub type FooClosure = |arg: u8|: 'static -> u8;
-
     // Tests ty_trait
     pub trait FooTrait {
         fn foo_method(&self) -> uint;
index 0b4bea49fa2499d0481dbdcbe5178c20c8401fe9..6cd94ee5602aa5ccf3db96b0b1f3ccda3dcae6ef 100644 (file)
@@ -27,7 +27,7 @@ fn bar() { }
 fn baz() { }
 
 pub fn test() {
-    let none: Option<Path> = None; // appease the typechecker
+    let none: Option<&Path> = None; // appease the typechecker
     let lib = DynamicLibrary::open(none).unwrap();
     unsafe {
         assert!(lib.symbol::<int>("foo").is_ok());
index fad70a917980d66735b0e8ecbc2319208561745b..399dfb9fa9a5bbc40bf6c955abfd089ea41ee421 100644 (file)
@@ -13,5 +13,5 @@
 
 pub fn foo<T>() {
     fn death() -> int { panic!() }
-    debug!("{}", (||{ death() })());
+    debug!("{}", (|&:|{ death() })());
 }
index 491d910f3517d7853742b2501aefa546d54aad84..1dcac9fe0742d5f6961a2c861eab1aeb92e54036 100644 (file)
@@ -61,12 +61,14 @@ fn contains(&self, k: &uint) -> bool { self.contains(k) }
 
 impl Results {
     pub fn bench_int<T:MutableSet<uint>,
-                     R: rand::Rng>(
+                     R:rand::Rng,
+                     F:FnMut() -> T>(
                      &mut self,
                      rng: &mut R,
                      num_keys: uint,
                      rand_cap: uint,
-                     f: || -> T) { {
+                     mut f: F) {
+        {
             let mut set = f();
             timed(&mut self.sequential_ints, || {
                 for i in range(0u, num_keys) {
@@ -103,11 +105,12 @@ pub fn bench_int<T:MutableSet<uint>,
     }
 
     pub fn bench_str<T:MutableSet<String>,
-                     R:rand::Rng>(
+                     R:rand::Rng,
+                     F:FnMut() -> T>(
                      &mut self,
                      rng: &mut R,
                      num_keys: uint,
-                     f: || -> T) {
+                     mut f: F) {
         {
             let mut set = f();
             timed(&mut self.sequential_strings, || {
index a3f1bc74b44fc07c4a65962ab5dd6a1f26e15a42..adf773a2f252cf723b72bf6f03f7b3ddc4fc3107 100644 (file)
@@ -20,7 +20,6 @@
 use std::sync::mpsc::channel;
 use std::os;
 use std::thread::Thread;
-use std::uint;
 
 // This is a simple bench that creates M pairs of tasks. These
 // tasks ping-pong back and forth over a pair of streams. This is a
@@ -31,24 +30,24 @@ fn ping_pong_bench(n: uint, m: uint) {
 
     // Create pairs of tasks that pingpong back and forth.
     fn run_pair(n: uint) {
-        // Create a stream A->B
-        let (atx, arx) = channel::<()>();
-        // Create a stream B->A
-        let (btx, brx) = channel::<()>();
+        // Create a channel: A->B
+        let (atx, arx) = channel();
+        // Create a channel: B->A
+        let (btx, brx) = channel();
 
         Thread::spawn(move|| {
             let (tx, rx) = (atx, brx);
             for _ in range(0, n) {
-                tx.send(());
-                rx.recv();
+                tx.send(()).unwrap();
+                rx.recv().unwrap();
             }
         }).detach();
 
         Thread::spawn(move|| {
             let (tx, rx) = (btx, arx);
             for _ in range(0, n) {
-                rx.recv();
-                tx.send(());
+                rx.recv().unwrap();
+                tx.send(()).unwrap();
             }
         }).detach();
     }
index 8c0ec667332d39ce46a7afe65d80e32910970e36..e6ef6a8c8c9ec4da7841ca5e263852b94cb25933 100644 (file)
@@ -94,7 +94,9 @@ fn update_freq(mm: &mut HashMap<Vec<u8> , uint>, key: &[u8]) {
 // given a Vec<u8>, for each window call a function
 // i.e., for "hello" and windows of size four,
 // run it("hell") and it("ello"), then return "llo"
-fn windows_with_carry(bb: &[u8], nn: uint, it: |window: &[u8]|) -> Vec<u8> {
+fn windows_with_carry<F>(bb: &[u8], nn: uint, mut it: F) -> Vec<u8> where
+    F: FnMut(&[u8]),
+{
    let mut ii = 0u;
 
    let len = bb.len();
index 438775d8ba0a405f1686e52ad6e65c7c369e9780..cdc7617fec8b074f294cd4117988b1a19e9b6557 100644 (file)
 
 // returns an infinite iterator of repeated applications of f to x,
 // i.e. [x, f(x), f(f(x)), ...], as haskell iterate function.
-fn iterate<'a, T>(x: T, f: |&T|: 'a -> T) -> Iterate<'a, T> {
+fn iterate<T, F>(x: T, f: F) -> Iterate<T, F> where F: FnMut(&T) -> T {
     Iterate {f: f, next: x}
 }
-struct Iterate<'a, T> {
-    f: |&T|: 'a -> T,
+struct Iterate<T, F> where F: FnMut(&T) -> T {
+    f: F,
     next: T
 }
-impl<'a, T> Iterator for Iterate<'a, T> {
+impl<T, F> Iterator for Iterate<T, F> where F: FnMut(&T) -> T {
     type Item = T;
 
     fn next(&mut self) -> Option<T> {
index e1696f0e63ed7607a52fca0aa55f590009b1ba14..f15157d126ed76ee64c85f474f66a9c42efcdeb6 100644 (file)
@@ -11,7 +11,7 @@
 
 struct sty(Vec<int> );
 
-fn unpack(_unpack: |v: &sty| -> Vec<int> ) {}
+fn unpack<F>(_unpack: F) where F: FnOnce(&sty) -> Vec<int> {}
 
 fn main() {
     let _foo = unpack(|s| {
index 453d7ffdad5c3249945623fb8b4c651b2722fb3c..f14668192f8503cfd0d4485b900ef5d2b1247303 100644 (file)
@@ -27,5 +27,5 @@ fn cat(in_x : uint, in_y : int) -> cat {
 
 fn main() {
   let nyan : cat = cat(52u, 99);
-  nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
+  nyan.speak = |&:| println!("meow"); //~ ERROR attempted to take value of method
 }
diff --git a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs
new file mode 100644 (file)
index 0000000..6555aa3
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Box {
+    type Color;
+
+    fn mail(&self) {  }
+}
+
+pub trait BoxCar : Box + Vehicle {
+}
+
+fn dent<C:BoxCar>(c: C, color: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+    //~| NOTE could derive from `Vehicle`
+    //~| NOTE could derive from `Box`
+}
+
+fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+    //~^ ERROR ambiguous associated type
+}
+
+fn paint<C:BoxCar>(c: C, d: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+    //~| NOTE could derive from `Vehicle`
+    //~| NOTE could derive from `Box`
+}
+
+pub fn main() { }
diff --git a/src/test/compile-fail/associated-type-projection-from-supertrait.rs b/src/test/compile-fail/associated-type-projection-from-supertrait.rs
new file mode 100644 (file)
index 0000000..01f9bd3
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Car : Vehicle {
+    fn honk(&self) { }
+    fn chip_paint(&self, c: Self::Color) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+fn a() { dent(ModelT, Black); }
+fn b() { dent(ModelT, Blue); } //~ ERROR type mismatch
+fn c() { dent(ModelU, Black); } //~ ERROR type mismatch
+fn d() { dent(ModelU, Blue); }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn e() { ModelT.chip_paint(Black); }
+fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types
+fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types
+fn h() { ModelU.chip_paint(Blue); }
+
+pub fn main() { }
diff --git a/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs
new file mode 100644 (file)
index 0000000..a362529
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Car : Vehicle {
+    fn honk(&self) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn black_car<C:Car<Color=Black>>(c: C) {
+}
+
+fn blue_car<C:Car<Color=Blue>>(c: C) {
+}
+
+fn a() { black_car(ModelT); }
+fn b() { blue_car(ModelT); } //~ ERROR type mismatch
+fn c() { black_car(ModelU); } //~ ERROR type mismatch
+fn d() { blue_car(ModelU); }
+
+pub fn main() { }
diff --git a/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs
new file mode 100644 (file)
index 0000000..8afd861
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we report an error if the trait ref in an qualified type
+// uses invalid type arguments.
+
+#![feature(associated_types)]
+
+trait Foo<T> {
+    type Bar;
+    fn get_bar(&self) -> Self::Bar;
+}
+
+fn f<T:Foo<int>>(t: &T) {
+    let u: <T as Foo<uint>>::Bar = t.get_bar();
+    //~^ ERROR the trait `Foo<uint>` is not implemented for the type `T`
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs
new file mode 100644 (file)
index 0000000..764b79c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do not ICE when an impl is missing an associated type (and that we report
+// a useful error, of course).
+
+#![feature(associated_types)]
+
+trait Trait {
+    type Type;
+}
+
+impl Trait for int {}  //~ ERROR missing: `Type`
+
+fn main() {}
+
diff --git a/src/test/compile-fail/block-coerce-no-2.rs b/src/test/compile-fail/block-coerce-no-2.rs
deleted file mode 100644 (file)
index e268b0e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Make sure that fn-to-block coercion isn't incorrectly lifted over
-// other tycons.
-
-fn main() {
-    fn f(f: fn(fn(fn()))) {
-    }
-
-    fn g(f: fn(||)) {
-    }
-
-    f(g);
-    //~^ ERROR mismatched types: expected `fn(fn(fn()))`
-}
diff --git a/src/test/compile-fail/block-coerce-no.rs b/src/test/compile-fail/block-coerce-no.rs
deleted file mode 100644 (file)
index 76af956..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// Make sure that fn-to-block coercion isn't incorrectly lifted over
-// other tycons.
-
-fn coerce(b: ||) -> extern fn() {
-    fn lol(f: extern fn(v: ||) -> extern fn(),
-           g: ||) -> extern fn() { return f(g); }
-    fn fn_id(f: extern fn()) -> extern fn() { return f }
-    return lol(fn_id, b);
-    //~^ ERROR mismatched types
-}
-
-fn main() {
-    let i = 8i;
-    let f = coerce(|| println!("{}", i) );
-    f();
-}
index e14911d3508da46ddd106a4cb141152f1efe27e1..a6801a6a51a52d10ae228bed6b16caa563570240 100644 (file)
@@ -24,7 +24,7 @@ fn a() {
     println!("{}", *q);
 }
 
-fn borrow(_x: &[int], _f: ||) {}
+fn borrow<F>(_x: &[int], _f: F) where F: FnOnce() {}
 
 fn b() {
     // here we alias the mutable vector into an imm slice and try to
index 1b4e5891f941de493f284cf808da66326a7b88ea..2804b8c48a703f4f4be64c71d3ac5effd36452af 100644 (file)
@@ -13,7 +13,7 @@ enum Either<T, U> { Left(T), Right(U) }
 struct X(Either<(uint,uint), fn()>);
 
 impl X {
-    pub fn with(&self, blk: |x: &Either<(uint,uint), fn()>|) {
+    pub fn with<F>(&self, blk: F) where F: FnOnce(&Either<(uint, uint), fn()>) {
         let X(ref e) = *self;
         blk(e)
     }
@@ -25,7 +25,7 @@ fn main() {
         |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
             match opt {
                 &Either::Right(ref f) => {
-                    x = X(Either::Left((0,0)));
+                    x = X(Either::Left((0, 0)));
                     (*f)()
                 },
                 _ => panic!()
index a37717ed5d99897d99e26165b6a65b55e5f3eee0..e519e57d178c85b10dc9fd68ec308aecdcc660e7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn force(f: ||) { f(); }
+fn force<F>(f: F) where F: FnOnce() { f(); }
 fn main() {
     let x: int;
     force(|| {  //~ ERROR capture of possibly uninitialized variable: `x`
index 002ae5a7d28b418ab394d40247ff8aa100f4bf42..6dbdff9441d55a8b0283bedfc3598c5b88e206a4 100644 (file)
 
 // Ensure that invoking a closure counts as a unique immutable borrow
 
+#![feature(unboxed_closures)]
 
-type Fn<'a> = ||:'a;
+type Fn<'a> = Box<FnMut() + 'a>;
 
 struct Test<'a> {
-    f: ||: 'a
+    f: Box<FnMut() + 'a>
 }
 
-fn call(f: |Fn|) {
-    f(|| {
-    //~^ ERROR: closure requires unique access to `f` but it is already borrowed
-        f(|| {})
+fn call<F>(mut f: F) where F: FnMut(Fn) {
+    f(box || {
+    //~^ ERROR: cannot borrow `f` as mutable more than once
+        f(box || {})
     });
 }
 
 fn test1() {
-    call(|a| {
-        a();
+    call(|mut a| {
+        a.call_mut(());
     });
 }
 
-fn test2(f: &||) {
-    (*f)(); //~ ERROR: closure invocation in a `&` reference
+fn test2<F>(f: &F) where F: FnMut() {
+    (*f)(); //~ ERROR: cannot borrow immutable dereference of `&`-pointer `*f` as mutable
 }
 
-fn test3(f: &mut ||) {
+fn test3<F>(f: &mut F) where F: FnMut() {
     (*f)();
 }
 
 fn test4(f: &Test) {
-    (f.f)() //~ ERROR: closure invocation in a `&` reference
+    f.f.call_mut(()) //~ ERROR: cannot borrow immutable dereference of `Box` `*f.f` as mutable
 }
 
 fn test5(f: &mut Test) {
-    (f.f)()
+    f.f.call_mut(())
 }
 
 fn test6() {
-    let f = || {};
-    (|| {
+    let mut f = |&mut:| {};
+    (|&mut:| {
         f();
     })();
 }
 
 fn test7() {
-    fn foo(_: |g: |int|, b: int|) {}
-    let f = |g: |int|, b: int| {};
-    f(|a| { //~ ERROR: cannot borrow `f` as immutable because previous closure
+    fn foo<F>(_: F) where F: FnMut(Box<FnMut(int)>, int) {}
+    let mut f = |&mut: g: Box<FnMut(int)>, b: int| {};
+    f(box |a| { //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
         foo(f); //~ ERROR: cannot move out of captured outer variable
     }, 3);
 }
index 886026e45d90f1f8c89734a3b04a0f77e2b1b572..47a47d0443255aab3e06d4d13f3970637a47593b 100644 (file)
@@ -22,37 +22,37 @@ fn set(x: &mut int) {
 
 fn a() {
     let mut x = 3i;
-    let c1 = || x = 4;
-    let c2 = || x * 5; //~ ERROR cannot borrow `x`
+    let c1 = |&mut:| x = 4;
+    let c2 = |&mut:| x * 5; //~ ERROR cannot borrow `x`
 }
 
 fn b() {
     let mut x = 3i;
-    let c1 = || set(&mut x);
-    let c2 = || get(&x); //~ ERROR cannot borrow `x`
+    let c1 = |&mut:| set(&mut x);
+    let c2 = |&mut:| get(&x); //~ ERROR cannot borrow `x`
 }
 
 fn c() {
     let mut x = 3i;
-    let c1 = || set(&mut x);
-    let c2 = || x * 5; //~ ERROR cannot borrow `x`
+    let c1 = |&mut:| set(&mut x);
+    let c2 = |&mut:| x * 5; //~ ERROR cannot borrow `x`
 }
 
 fn d() {
     let mut x = 3i;
-    let c2 = || x * 5;
+    let c2 = |&mut:| x * 5;
     x = 5; //~ ERROR cannot assign
 }
 
 fn e() {
     let mut x = 3i;
-    let c1 = || get(&x);
+    let c1 = |&mut:| get(&x);
     x = 5; //~ ERROR cannot assign
 }
 
 fn f() {
     let mut x = box 3i;
-    let c1 = || get(&*x);
+    let c1 = |&mut:| get(&*x);
     *x = 5; //~ ERROR cannot assign
 }
 
@@ -62,7 +62,7 @@ struct Foo {
     }
 
     let mut x = box Foo { f: box 3 };
-    let c1 = || get(&*x.f);
+    let c1 = |&mut:| get(&*x.f);
     *x.f = 5; //~ ERROR cannot assign to `*x.f`
 }
 
@@ -72,8 +72,8 @@ struct Foo {
     }
 
     let mut x = box Foo { f: box 3 };
-    let c1 = || get(&*x.f);
-    let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable
+    let c1 = |&mut:| get(&*x.f);
+    let c2 = |&mut:| *x.f = 5; //~ ERROR cannot borrow `x` as mutable
 }
 
 fn main() {
index 8163df5e967cd52f8ec9ea9225f3c05bfb4a5952..30e1421ba2660fb873bba3bc85488f9ab9abe519 100644 (file)
@@ -20,9 +20,9 @@ fn set(x: &mut int) {
 }
 
 fn a(x: &int) {
-    let c1 = || set(&mut *x);
+    let c1 = |&mut:| set(&mut *x);
     //~^ ERROR cannot borrow
-    let c2 = || set(&mut *x);
+    let c2 = |&mut:| set(&mut *x);
     //~^ ERROR cannot borrow
     //~| ERROR closure requires unique access
 }
index 6d382854d49f2b2b9cadf49bceb100effba039b2..0f284b5384913f41dce038cdd46da80b67894333 100644 (file)
@@ -15,8 +15,8 @@
 
 fn a() {
     let mut x = 3i;
-    let c1 = || x = 4;
-    let c2 = || x = 5; //~ ERROR cannot borrow `x` as mutable more than once
+    let c1 = |&mut:| x = 4;
+    let c2 = |&mut:| x = 5; //~ ERROR cannot borrow `x` as mutable more than once
 }
 
 fn set(x: &mut int) {
@@ -25,20 +25,20 @@ fn set(x: &mut int) {
 
 fn b() {
     let mut x = 3i;
-    let c1 = || set(&mut x);
-    let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
+    let c1 = |&mut:| set(&mut x);
+    let c2 = |&mut:| set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
 }
 
 fn c() {
     let mut x = 3i;
-    let c1 = || x = 5;
-    let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
+    let c1 = |&mut:| x = 5;
+    let c2 = |&mut:| set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once
 }
 
 fn d() {
     let mut x = 3i;
-    let c1 = || x = 5;
-    let c2 = || { let _y = || set(&mut x); }; // (nested closure)
+    let c1 = |&mut:| x = 5;
+    let c2 = |&mut:| { let _y = |&mut:| set(&mut x); }; // (nested closure)
     //~^ ERROR cannot borrow `x` as mutable more than once
 }
 
@@ -48,8 +48,8 @@ struct Foo {
     }
 
     let mut x = box Foo { f: box 3 };
-    let c1 = || set(&mut *x.f);
-    let c2 = || set(&mut *x.f);
+    let c1 = |&mut:| set(&mut *x.f);
+    let c2 = |&mut:| set(&mut *x.f);
     //~^ ERROR cannot borrow `x` as mutable more than once
 }
 
index dfe5de09c50979284ebd5049d16e8f9916ee5c33..a9cc9e967f6ff70ecdabda9052ef7f118864f3d6 100644 (file)
@@ -16,7 +16,7 @@ pub fn main() {
     let mut this = &mut Foo {
         x: 1,
     };
-    let r = || {
+    let mut r = |&mut:| {
         let p = &this.x;
         &mut this.x; //~ ERROR cannot borrow
     };
index febc84ccd44613c8fb7401c8c852cad9c880ca8b..9a772cc49b87b62ac8b6e84caa81bbf0b7b0467f 100644 (file)
@@ -23,27 +23,27 @@ fn set(x: &mut int) -> int {
 }
 
 fn a(x: &mut int) {
-    let c1 = || get(x);
-    let c2 = || get(x);
+    let c1 = |&mut:| get(x);
+    let c2 = |&mut:| get(x);
 }
 
 fn b(x: &mut int) {
-    let c1 = || get(x);
-    let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+    let c1 = |&mut:| get(x);
+    let c2 = |&mut:| set(x); //~ ERROR closure requires unique access to `x`
 }
 
 fn c(x: &mut int) {
-    let c1 = || get(x);
-    let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+    let c1 = |&mut:| get(x);
+    let c2 = |&mut:| { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
 }
 
 fn d(x: &mut int) {
-    let c1 = || set(x);
-    let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+    let c1 = |&mut:| set(x);
+    let c2 = |&mut:| set(x); //~ ERROR closure requires unique access to `x`
 }
 
 fn e(x: &mut int) {
-    let c1: || = || x = panic!(); //~ ERROR closure cannot assign to immutable local variable
+    let c1 = |&mut:| x = panic!(); //~ ERROR closure cannot assign to immutable local variable
 }
 
 fn main() {
index 735d9ece9b1a500844cf22701ee8f9412cfeee25..23c90fcf574d5bb45b920cb6ba60a6b84475f31b 100644 (file)
@@ -25,7 +25,7 @@ fn drop(&mut self) {
 
 fn main() {
   let mut ptr = box Foo { x: 0 };
-  let test = |foo: &Foo| {
+  let mut test = |&mut: foo: &Foo| {
     ptr = box Foo { x: ptr.x + 1 };
   };
   test(&*ptr); //~ ERROR cannot borrow `*ptr`
index d759a5738bd22703b7187705b8dd3fdca5511201..5496a9dd4b3611c78b2a0fc70f7f4845ea5f6d08 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let j: || -> int = || {
+    let j = |&:| -> int {
         let i: int;
         i //~ ERROR use of possibly uninitialized variable: `i`
     };
index 07e2ff084664dcfc11d8a8abc97baf0341e165ca..33c284c71b341df0558956f2e861747d3d5fa37f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let f: || -> int = || {
+    let f  = |&:| -> int {
         let i: int;
         i //~ ERROR use of possibly uninitialized variable: `i`
     };
index a84a025d8a8ee9d89dcd4323be6ad169781dd34c..0428ee83065173a99156ebf4a7bfa7e78d8cbdd5 100644 (file)
@@ -16,7 +16,7 @@ struct Foo {
 }
 
 impl Foo {
-    pub fn foo(&mut self, fun: |&int|) {
+    pub fn foo<F>(&mut self, mut fun: F) where F: FnMut(&int) {
         for f in self.n.iter() {
             fun(f);
         }
index 8a7ecde700ae6f7cbab94f64f68d198002007978..f798d170f963b35dd8a2f255c96f5c6df4694596 100644 (file)
@@ -18,7 +18,7 @@
 fn borrow(_v: &int) {}
 fn borrow_mut(_v: &mut int) {}
 fn cond() -> bool { panic!() }
-fn for_func(_f: || -> bool) { panic!() }
+fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
 fn produce<T>() -> T { panic!(); }
 
 fn inc(v: &mut Box<int>) {
index 6adcfad33f46c58c582f7ffe1d14538f2cefa762..ff038b545d5fec4013c51b85f3e2692956b2f276 100644 (file)
@@ -112,7 +112,9 @@ fn while_aliased_mut_cond(cond: bool, cond2: bool) {
     }
 }
 
-fn loop_break_pops_scopes<'r>(_v: &'r mut [uint], f: |&'r mut uint| -> bool) {
+fn loop_break_pops_scopes<'r, F>(_v: &'r mut [uint], mut f: F) where
+    F: FnMut(&'r mut uint) -> bool,
+{
     // Here we check that when you break out of an inner loop, the
     // borrows that go out of scope as you exit the inner loop are
     // removed from the bitset.
@@ -128,7 +130,7 @@ fn loop_break_pops_scopes<'r>(_v: &'r mut [uint], f: |&'r mut uint| -> bool) {
     }
 }
 
-fn loop_loop_pops_scopes<'r>(_v: &'r mut [uint], f: |&'r mut uint| -> bool) {
+fn loop_loop_pops_scopes<'r, F>(_v: &'r mut [uint], mut f: F) where F: FnMut(&'r mut uint) -> bool {
     // Similar to `loop_break_pops_scopes` but for the `loop` keyword
 
     while cond() {
index de8c7d9def4e1b709f2441091e18a809c0a42384..85fc7fb87b34034b9a6c4379b7a4191799713b1f 100644 (file)
@@ -18,7 +18,7 @@
 fn borrow(_v: &int) {}
 fn borrow_mut(_v: &mut int) {}
 fn cond() -> bool { panic!() }
-fn for_func(_f: || -> bool) { panic!() }
+fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
 fn produce<T>() -> T { panic!(); }
 
 fn inc(v: &mut Box<int>) {
index 9bd2d48b29a8587c8b6a00108950396ca1cead28..5c282495cc239419705136bcbb19aaf62fb720f4 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::thread::Thread;
 
-fn borrow(v: &int, f: |x: &int|) {
+fn borrow<F>(v: &int, f: F) where F: FnOnce(&int) {
     f(v);
 }
 
index bfa890ada9f1925fc44611c2b15dfd6080a4e7e4..b6a71fcd446abe72bb6fbdf3067a47ab2e0750e6 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn borrow(v: &int, f: |x: &int|) {
+fn borrow<F>(v: &int, f: F) where F: FnOnce(&int) {
     f(v);
 }
 
index d678fd48f21d2584a65ee95e1f0a1709d7c9ea2a..0ada3db47a4b6ec1884fa2bae169fb9bcae24d3c 100644 (file)
@@ -13,14 +13,14 @@ struct point { x: int, y: int }
 
 trait methods {
     fn impurem(&self);
-    fn blockm(&self, f: ||);
+    fn blockm<F>(&self, f: F) where F: FnOnce();
 }
 
 impl methods for point {
     fn impurem(&self) {
     }
 
-    fn blockm(&self, f: ||) { f() }
+    fn blockm<F>(&self, f: F) where F: FnOnce() { f() }
 }
 
 fn a() {
index 200d208d140b69a054538222bf1d7d10c8fdf4a0..7849475ec67991cb519cf33dff826920764bfc84 100644 (file)
@@ -12,7 +12,7 @@
 // (locally rooted) mutable, unique vector, and that we then prevent
 // modifications to the contents.
 
-fn takes_imm_elt(_v: &int, f: ||) {
+fn takes_imm_elt<F>(_v: &int, f: F) where F: FnOnce() {
     f();
 }
 
index 9c9641bccfa144de2d76e538df8f038f3b2c2ef3..35f0751aa7895a941f1adecaf1a7d581114ec7da 100644 (file)
@@ -10,7 +10,7 @@
 
 pub fn main() {
     let bar = box 3;
-    let _g = || {
+    let _g = |&mut:| {
         let _h = move |:| -> int { *bar }; //~ ERROR cannot move out of captured outer variable
     };
 }
index c7b573562e3484747c7d272b28e7cd9f7d9ddc19..c5d23925a89b1f2d25c5470e2b43ea00a318457c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with(f: |&String|) {}
+fn with<F>(f: F) where F: FnOnce(&String) {}
 
 fn arg_item(&_x: &String) {}
     //~^ ERROR cannot move out of dereference of `&`-pointer
index 82189c6b7c1f1b7fa4e1e240ec275b555b7cba66..0a47353683cfb7cfa82483a199c9767260e81183 100644 (file)
@@ -32,7 +32,7 @@ fn foo() {
 
 fn bar() {
     // Original borrow ends at end of closure
-    || {
+    |&:| {
         let mut x = 1u;
         let y = &mut x;
         let z = &mut x; //~ ERROR cannot borrow
index d72398a6ac5a71d2d80a2e0b8a12a5e44d1ebeab..1f257b8a5cba847d2b0d281a1ac0c78bea9cbbf4 100644 (file)
@@ -14,7 +14,7 @@ struct Foo {
 
 fn cond() -> bool { true }
 
-fn foo(_: ||) {}
+fn foo<F>(_: F) where F: FnOnce() {}
 
 fn main() {
     let pth = break; //~ ERROR: `break` outside of loop
index 1ff9dc9dac4c296315b271d3660ab22e344f9d14..a02d6b7f5173acc3ea6b4f4f36b03baf020f4c02 100644 (file)
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct X {
-    field: ||:'static + Send,
+struct X<F> where F: FnOnce() + 'static + Send {
+    field: F,
 }
 
-fn foo(blk: ||:'static) -> X {
-    return X { field: blk }; //~ ERROR expected bounds `Send`
+fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
+    //~^ ERROR the trait `core::kinds::Send` is not implemented for the type
+    return X { field: blk };
 }
 
 fn main() {
diff --git a/src/test/compile-fail/closure-bounds-not-builtin.rs b/src/test/compile-fail/closure-bounds-not-builtin.rs
deleted file mode 100644 (file)
index 6b25e4b..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.
-
-
-trait Foo {}
-
-fn take(f: ||:Foo) {
-    //~^ ERROR only the builtin traits can be used as closure or object bounds
-}
-
-fn main() {}
index 6769740294bc6c7892c78c9b55048c05c3ff3b20..d27529bad43052b776fc8702005e62cd1c01425d 100644 (file)
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn bar(blk: ||:'static) {
+fn bar<F>(blk: F) where F: FnOnce() + 'static {
 }
 
 fn foo(x: &()) {
     bar(|| { //~ ERROR cannot infer an appropriate lifetime
         let _ = x;
-        //~^ ERROR captured variable `x` does not outlive
     })
 }
 
index 5bd9f20dd834368d7913a6c691360b25c841af78..509fffc5c9a882e2806b64b587fbf15d1c73e7e5 100644 (file)
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 
-fn take_any(_: ||) {
+fn take_any<F>(_: F) where F: FnOnce() {
 }
 
-fn take_const_owned(_: ||:Sync+Send) {
+fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
 }
 
-fn give_any(f: ||) {
+fn give_any<F>(f: F) where F: FnOnce() {
     take_any(f);
 }
 
-fn give_owned(f: ||:Send) {
+fn give_owned<F>(f: F) where F: FnOnce() + Send {
     take_any(f);
-    take_const_owned(f); //~ ERROR expected bounds `Send+Sync`, found bounds `Send`
+    take_const_owned(f); //~ ERROR the trait `core::kinds::Sync` is not implemented for the type
 }
 
 fn main() {}
index 1e1889c7339d26ce6e430545bdf71cd5fb7987ac..ef01c96addeb8f555f4ba26919e7f3b65b73c961 100644 (file)
@@ -17,7 +17,7 @@ fn call_bare(f: fn(&str)) {
 
 fn main() {
     let string = "world!";
-    let f: |&str| = |s| println!("{}{}", s, string);
+    let f = |&: s: &str| println!("{}{}", s, string);
     call_bare(f)    //~ ERROR mismatched types
 }
 
diff --git a/src/test/compile-fail/closure-that-fails.rs b/src/test/compile-fail/closure-that-fails.rs
deleted file mode 100644 (file)
index 7a1ebed..0000000
+++ /dev/null
@@ -1,20 +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 foo(f: || -> !) {}
-
-fn main() {
-    // Type inference didn't use to be able to handle this:
-    foo(|| panic!());
-    foo(|| -> ! panic!());
-    foo(|| 22i); //~ ERROR computation may converge in a function marked as diverging
-    foo(|| -> ! 22i); //~ ERROR computation may converge in a function marked as diverging
-    let x = || -> ! 1i; //~ ERROR computation may converge in a function marked as diverging
-}
diff --git a/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs b/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs
deleted file mode 100644 (file)
index 52f4c47..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.
-
-// Test that coercions from fn item types are ok, but not fn pointer
-// types to closures/procs are not allowed.
-
-fn foo() {}
-
-fn fn_item_type() {
-    let f = foo;
-
-    let f_closure: || = f;
-}
-
-fn fn_pointer_type() {
-    let f = foo as fn();
-    let f_closure: || = f;
-    //~^ ERROR: mismatched types
-}
-
-fn main() { }
index 0aa3c40fa5f88c64b1f38034a28635e5d2ceffe0..46f5f41d7282f89254c2c022629204c0aefe2f39 100644 (file)
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-test FIXME(#20574)
+
 #![deny(unreachable_code)]
 
 fn main() {
-    let x: || -> ! = || panic!();
+    let x = |:| panic!();
     x();
     std::io::println("Foo bar"); //~ ERROR: unreachable statement
 }
index 6b01b83db21fd31d0c097a459a52f00c9ba10411..d7586af291e8638d77de1aa3344366c5c7272220 100644 (file)
 extern fn f() {
 }
 
+fn is_fn<F>(_: F) where F: Fn() {}
+
 fn main() {
     // extern functions are extern "C" fn
     let _x: extern "C" fn() = f; // OK
-    let _x: || = f; //~ ERROR mismatched types
+    is_fn(f); //~ ERROR the trait `core::ops::Fn()` is not implemented for the type `extern "C" fn()
 }
index 2277f7080af75c464225f56ee34b52336f579f1d..039628b67528289e2780b50d4f3441ea3199d748 100644 (file)
@@ -12,7 +12,7 @@ fn takes_imm(x: &int) { }
 
 fn takes_mut(x: &mut int) { }
 
-fn apply<T>(t: T, f: |T|) {
+fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
     f(t)
 }
 
index 71328acdd7017f406af5dbeafc876af001aa186b..827e648cca86d0a32113bf2a6ca38cecbea4cd2f 100644 (file)
@@ -14,7 +14,7 @@ fn f(y: Box<int>) {
 }
 
 fn g() {
-    let _frob: |Box<int>| = |q| { *q = 2; }; //~ ERROR cannot assign
+    let _frob = |&: q: Box<int>| { *q = 2; }; //~ ERROR cannot assign
 
 }
 
index 924132c6de26bff8023a066ecc71ff66e77813df..dec4fc3b8f5b274649bb7f06a280f1cd50a64210 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn test<'x>(x: &'x int) {
-    drop::< for<'z>|&'z int| -> &'z int >(|z| {
+    drop::<Box<for<'z> FnMut(&'z int) -> &'z int>>(box |z| {
         x
         //~^ ERROR cannot infer an appropriate lifetime
     });
index 18a00d15eafe36610d5763fa63a6a28251e2fd20..f496c1e1227dbcc3b9be173558453f298a2c5e2c 100644 (file)
@@ -20,7 +20,7 @@ fn drop(&mut self) {
 
 fn main() {
     let mut ptr = box Foo { x: 0 };
-    let test = |foo: &Foo| {
+    let mut test = |&mut: foo: &Foo| {
         println!("access {}", foo.x);
         ptr = box Foo { x: ptr.x + 1 };
         println!("access {}", foo.x);
index e1acab4008a9b1a65586d8859ee05775b8a61469..89667937531536fe306c3eb881b6a1e0dc772d02 100644 (file)
@@ -10,7 +10,7 @@
 
 fn main() {
     let mut v = vec!(1i);
-    let f = || v.push(2i);
+    let mut f = |&mut:| v.push(2i);
     let _w = v; //~ ERROR: cannot move out of `v`
 
     f();
index 24256e31118e35b616ce779039e2cc2d1c2e7d3f..5033576a23482e2847b8bac03c1ccc99fb6e8300 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-test FIXME(japari) remove test
+
 struct Foo {
     f: for <'b> |&'b int|:
       'b -> &'b int //~ ERROR use of undeclared lifetime name `'b`
index 7ec3fef5c878eb05a060356e60fa5b169b03392c..9d2212b69cee116de1d270b87f1010416b4ab45a 100644 (file)
@@ -14,7 +14,7 @@
 // wrong arity.
 
 fn _foo<F: Fn()> (f: F) {
-    |t| f(t); //~ ERROR E0057
+    |&: t| f(t); //~ ERROR E0057
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-17636.rs b/src/test/compile-fail/issue-17636.rs
deleted file mode 100644 (file)
index ad2ebff..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait MyItem<T> {}
-impl<T> MyItem<T> for T {}
-
-pub fn build_archive<'a, I: MyItem<&'a (|&uint|:'a)>>(files: I) {}
-
-fn main() {
-    build_archive(&(|_| { }));
-//~^ ERROR not implemented
-}
index ab396edddf49c1031dce42f0a69a9a6d1ff952f0..970b14c7eb7cc612224a3e12d1bbf226bbd78c5d 100644 (file)
@@ -12,7 +12,7 @@
 // and rejected.
 
 fn main() {
-    (|| box *[0u].as_slice())();
+    (|&:| box *[0u].as_slice())();
     //~^ ERROR cannot move out of dereference
     //~^^ ERROR cannot move a value of type [uint]
 }
diff --git a/src/test/compile-fail/issue-17904.rs b/src/test/compile-fail/issue-17904.rs
new file mode 100644 (file)
index 0000000..96ba712
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
+struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
+struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
+struct Foo<T> where T: Copy, (T); //~ ERROR unexpected token in `where` clause
+struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
+
+fn main() {}
index 1608d2137fc3216ee92862d8f79619c584b9aa09..f87a0d774fa7c7c9745b833654d097c658aa5d29 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct Obj<'a> {
-    closure: ||: 'a -> u32
+struct Obj<F> where F: FnMut() -> u32 {
+    closure: F,
 }
 
 fn main() {
     let o = Obj { closure: || 42 };
-    o.closure(); //~ ERROR type `Obj<'_>` does not implement any method in scope named `closure`
+    o.closure(); //~ ERROR does not implement any method in scope named `closure`
     //~^ NOTE use `(s.closure)(...)` if you meant to call the function stored in the `closure` field
 }
diff --git a/src/test/compile-fail/issue-18345.rs b/src/test/compile-fail/issue-18345.rs
deleted file mode 100644 (file)
index e93acb3..0000000
+++ /dev/null
@@ -1,20 +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.
-
-type Step<'s, R, T> = |R, T|: 's -> R;
-type Transducer<'t, R, T, U> = |Step<'t, R, U>|: 't -> Step<'t, R, T>;
-
-fn mapping<'f, R, T, U>(f: |T|: 'f -> U) -> &'f Transducer<'f, R, T, U> {
-    |step| |r, x|
-        step(r, f(x))
-        //~^ ERROR the type of this value must be known in this context
-}
-
-fn main() {}
index 8097d93ca07458a855fc3adaac8e0be440ff5520..3a0fbddf8185fa3d9fdb5345023d79b131d150f4 100644 (file)
@@ -13,8 +13,8 @@
 fn main() {
     let c = RefCell::new(vec![]);
     let mut y = 1u;
-    c.push(|| y = 0);
-    c.push(|| y = 0);
+    c.push(box || y = 0);
+    c.push(box || y = 0);
 //~^ ERROR cannot borrow `y` as mutable more than once at a time
 }
 
@@ -22,16 +22,16 @@ fn ufcs() {
     let c = RefCell::new(vec![]);
     let mut y = 1u;
 
-    Push::push(&c, || y = 0);
-    Push::push(&c, || y = 0);
+    Push::push(&c, box || y = 0);
+    Push::push(&c, box || y = 0);
 }
 
 trait Push<'c> {
-    fn push<'f: 'c>(&self, push: ||:'f -> ());
+    fn push<'f: 'c>(&self, push: Box<FnMut() + 'f>);
 }
 
-impl<'c> Push<'c> for RefCell<Vec<||:'c>> {
-    fn push<'f: 'c>(&self, fun: ||:'f -> ()) {
+impl<'c> Push<'c> for RefCell<Vec<Box<FnMut() + 'c>>> {
+    fn push<'f: 'c>(&self, fun: Box<FnMut() + 'f>) {
         self.borrow_mut().push(fun)
     }
 }
diff --git a/src/test/compile-fail/issue-19009.rs b/src/test/compile-fail/issue-19009.rs
deleted file mode 100644 (file)
index aa7c4c3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(lang_items)]
-#![no_std]
-#![crate_type="rlib"]
-#[lang="sized"] pub trait Sized for Sized? {}
-
-fn ice(f: for <'s> ||
-    :'s //~ ERROR use of undeclared lifetime name `'s`
-) {}
-fn main() { ice(||{}) }
diff --git a/src/test/compile-fail/issue-19141.rs b/src/test/compile-fail/issue-19141.rs
deleted file mode 100644 (file)
index 545e3f8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let n = 0u;
-
-    let f = move || n += 1;  //~error boxed closures can't capture by value
-}
index 4069ea6b997c4cbc93d41dcaba35653165ee0687..7794c34a04b81bf388e23aa80ea457d3bd0e03e8 100644 (file)
@@ -12,7 +12,7 @@
 
 fn akemi(homura: Homura) {
     let Some(ref madoka) = Some(homura.kaname()); //~ ERROR does not implement any method
-    madoka.clone(); //~ ERROR the type of this value must be known
+    madoka.clone();
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-20193.rs b/src/test/compile-fail/issue-20193.rs
deleted file mode 100644 (file)
index e5d8d33..0000000
+++ /dev/null
@@ -1,24 +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 foo(t: &mut int){
-    println!("{}", t);
-}
-
-fn main() {
-    let test = 10;
-
-    let h = move || {  //~error boxed closures can't capture by value
-        let mut r = &mut test.clone();
-        foo(r);
-    };
-
-    h();
-}
diff --git a/src/test/compile-fail/issue-20228-1.rs b/src/test/compile-fail/issue-20228-1.rs
deleted file mode 100644 (file)
index 3ff4557..0000000
+++ /dev/null
@@ -1,20 +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.
-
-struct S;
-
-impl S {
-    fn foo(&self) {
-        let _ = move || { self };  //~error boxed closures can't capture by value
-    }
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/issue-20228-2.rs b/src/test/compile-fail/issue-20228-2.rs
deleted file mode 100644 (file)
index 5fec426..0000000
+++ /dev/null
@@ -1,20 +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.
-
-struct S;
-
-impl S {
-    fn foo(&self) {
-        let _ = move || { self.foo() };  //~error boxed closures can't capture by value
-    }
-}
-
-fn main() {
-}
index b688cafb67459aab05c1701e8eb6968083c9c430..691660f897157f309dfcb52a2e3420b4db1dd729 100644 (file)
@@ -9,17 +9,17 @@
 // except according to those terms.
 
 trait vec_monad<A> {
-    fn bind<B>(&self, f: |A| -> Vec<B> );
+    fn bind<B, F>(&self, f: F) where F: FnMut(A) -> Vec<B>;
 }
 
 impl<A> vec_monad<A> for Vec<A> {
-    fn bind<B>(&self, f: |A| -> Vec<B> ) {
+    fn bind<B, F>(&self, mut f: F) where F: FnMut(A) -> Vec<B> {
         let mut r = panic!();
         for elt in self.iter() { r = r + f(*elt); }
         //~^ ERROR the type of this value must be known
    }
 }
 fn main() {
-    ["hi"].bind(|x| [x] );
+    ["hi"].bind(|&mut: x| [x] );
     //~^ ERROR type `[&str; 1]` does not implement any method in scope named `bind`
 }
index 0f7cc2cb72b8e2b05b73dcb6456119e3ade48d33..c67d6b1ce8f7ce17e063dcc42ab31835527ca254 100644 (file)
@@ -11,7 +11,7 @@
 
 fn main() {
     let needlesArr: Vec<char> = vec!('a', 'f');
-    needlesArr.iter().fold(|x, y| {
+    needlesArr.iter().fold(|&: x, y| {
     });
     //~^^ ERROR this function takes 2 parameters but 1 parameter was supplied
     //
index 38f28bd79dfa1905d9ed09d82583c03d4b5f1ee4..86ab9be77fc6808389e948f913e33d1ac10ff23e 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 trait A {
-  fn a(&self) {
-      || self.b() //~ ERROR type `&Self` does not implement any method in scope named `b`
-  }
+    fn a(&self) {
+        |&:| self.b() //~ ERROR type `&Self` does not implement any method in scope named `b`
+        //~^ ERROR expected (), found closure
+    }
 }
 fn main() {}
index eadd16348b2e8573b81138986176cd7d9aca6f4e..d4f9ea5b276f9fc4ed4165528e021999db1e37c5 100644 (file)
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 fn id<T>(t: T) -> T { t }
 
-fn f<'r, T>(v: &'r T) -> ||: 'r -> T {
-    id(|| *v) //~ ERROR cannot infer
+fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+    id(box |&mut:| *v) //~ ERROR cannot infer
 }
 
 fn main() {
     let v = &5i;
-    println!("{}", f(v)());
+    println!("{}", f(v).call_mut(()));
 }
diff --git a/src/test/compile-fail/issue-4523.rs b/src/test/compile-fail/issue-4523.rs
deleted file mode 100644 (file)
index 5063a78..0000000
+++ /dev/null
@@ -1,17 +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 foopy() {}
-
-static f: ||: 'static = foopy;
-
-fn main () {
-    f(); //~ ERROR closure invocation in a static location
-}
index 18af9736ed9f8408224d80d0c78095a9d1e0a189..fef414ce978a8756e263cc821d6035950611033d 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 fn f() { }
-struct S(||); //~ ERROR explicit lifetime bound required
+struct S(Box<FnMut()>); //~ ERROR explicit lifetime bound required
 pub static C: S = S(f);
 
 
 fn g() { }
-type T = ||;  //~ ERROR explicit lifetime bound required
+type T = Box<FnMut()>;  //~ ERROR explicit lifetime bound required
 pub static D: T = g;
 
 fn main() {}
index 88b08655caad2547d3fc066932c15cf1e1062859..1691688fd84645f65d31446cae23cdd48d3e2f44 100644 (file)
@@ -11,6 +11,6 @@
 // Regression test for issue #5239
 
 fn main() {
-    let x: |int| -> int = |ref x| { x += 1; };
+    let x = |&: ref x: int| -> int { x += 1; };
     //~^ ERROR binary assignment operation `+=` cannot be applied to type `&int`
 }
index 5925f6869391a1d4f6280a08567d8bac6e3a714c..433ae3bf89e03a540c9965ef21f327556d044c52 100644 (file)
@@ -17,13 +17,13 @@ fn twice(x: Box<uint>) -> uint {
      *x * 2
 }
 
-fn invoke(f: || -> uint) {
+fn invoke<F>(f: F) where F: FnOnce() -> uint {
      f();
 }
 
 fn main() {
       let x  : Box<uint>  = box 9;
-      let sq : || -> uint =  || { *x * *x };
+      let sq =  |:| { *x * *x };
 
       twice(x); //~ ERROR: cannot move out of
       invoke(sq);
index 0e978a09edd2d8669ae60c7dd7f147e6978065ae..897afb1c10245a256ddeb449afe47292b8b44b6b 100644 (file)
@@ -25,7 +25,7 @@ fn new(s: &str) -> CrateId {
 
 pub fn remove_package_from_database() {
     let mut lines_to_use: Vec<&CrateId> = Vec::new();
-    let push_id = |installed_id: &CrateId| {
+    let push_id = |&mut: installed_id: &CrateId| {
         lines_to_use.push(installed_id);
         //~^ ERROR cannot infer an appropriate lifetime for automatic coercion due to
         // conflicting requirements
@@ -38,7 +38,7 @@ pub fn remove_package_from_database() {
 
 }
 
-pub fn list_database(f: |&CrateId|) {
+pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
     let stuff = ["foo", "bar"];
 
     for l in stuff.iter() {
index 8868c7f8256da5b646386e049ae389a028c9de66..b5725249812f6ccd2edfb018b5d3fddbe9d62ded 100644 (file)
@@ -57,9 +57,6 @@ fn test<'a,T,U:Copy>(_: &'a int) {
     // mutable object types are not ok
     assert_copy::<&'a mut (Dummy+Copy)>();  //~ ERROR `core::kinds::Copy` is not implemented
 
-    // closures are like an `&mut` object
-    assert_copy::<||>(); //~ ERROR `core::kinds::Copy` is not implemented
-
     // unsafe ptrs are ok
     assert_copy::<*const int>();
     assert_copy::<*const &'a mut int>();
index f5740992af48eadba48e8fd4b2103f5b0d684950..d66fd0d77d6a9b6a6ef645a64e1ca8b7cbcf351b 100644 (file)
@@ -11,7 +11,6 @@
 // Test that Copy bounds inherited by trait are checked.
 
 use std::any::Any;
-use std::any::AnyRefExt;
 
 trait Foo : Copy {
 }
index 3b67e98f42ca81d55e51967c243fa74a41952ef5..c300096caf1e09c87bcb4f8e6c99d8e9cecbe837 100644 (file)
@@ -27,14 +27,9 @@ fn box_object_with_no_bound_not_ok<'a>() {
     assert_send::<Box<Dummy>>(); //~ ERROR the trait `core::kinds::Send` is not implemented
 }
 
-fn closure_with_no_bound_not_ok<'a>() {
-    assert_send::<||:'static>(); //~ ERROR the trait `core::kinds::Send` is not implemented
-}
-
 fn object_with_send_bound_ok() {
     assert_send::<&'static (Dummy+Send)>();
     assert_send::<Box<Dummy+Send>>();
-    assert_send::<||:Send>;
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/lint-raw-ptr-derive.rs b/src/test/compile-fail/lint-raw-ptr-derive.rs
new file mode 100644 (file)
index 0000000..3198e78
--- /dev/null
@@ -0,0 +1,34 @@
+// 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.
+
+#![allow(dead_code)]
+#![deny(raw_pointer_derive)]
+
+#[derive(Clone)]
+struct Foo {
+    x: *const int //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+#[derive(Clone)]
+struct Bar(*mut int); //~ ERROR use of `#[derive]` with a raw pointer
+
+#[derive(Clone)]
+enum Baz {
+    A(*const int), //~ ERROR use of `#[derive]` with a raw pointer
+    B { x: *mut int } //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+#[derive(Clone)]
+struct Buzz {
+    x: (*const int, //~ ERROR use of `#[derive]` with a raw pointer
+        *const uint) //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/lint-raw-ptr-deriving.rs b/src/test/compile-fail/lint-raw-ptr-deriving.rs
deleted file mode 100644 (file)
index 6fe8862..0000000
+++ /dev/null
@@ -1,34 +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.
-
-#![allow(dead_code)]
-#![deny(raw_pointer_deriving)]
-
-#[derive(Clone)]
-struct Foo {
-    x: *const int //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-#[derive(Clone)]
-struct Bar(*mut int); //~ ERROR use of `#[derive]` with a raw pointer
-
-#[derive(Clone)]
-enum Baz {
-    A(*const int), //~ ERROR use of `#[derive]` with a raw pointer
-    B { x: *mut int } //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-#[derive(Clone)]
-struct Buzz {
-    x: (*const int, //~ ERROR use of `#[derive]` with a raw pointer
-        *const uint) //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-fn main() {}
index 29b4686198be1fc8a91a539d3282ba4e5b3cef9d..7513e1bc21a4a7e1a953beb1dcbde9af804cb43d 100644 (file)
@@ -35,7 +35,7 @@ fn main() {
       _ => {}
     }
 
-    let x = |mut y: int| 10i; //~ ERROR: variable does not need to be mutable
+    let x = |&: mut y: int| 10i; //~ ERROR: variable does not need to be mutable
     fn what(mut foo: int) {} //~ ERROR: variable does not need to be mutable
 
     // positive cases
@@ -65,7 +65,7 @@ fn what(mut foo: int) {} //~ ERROR: variable does not need to be mutable
       _ => {}
     }
 
-    let x = |mut y: int| y = 32i;
+    let x = |&mut: mut y: int| y = 32i;
     fn nothing(mut foo: int) { foo = 37i; }
 
     // leading underscore should avoid the warning, just like the
@@ -73,7 +73,7 @@ fn what(mut foo: int) {} //~ ERROR: variable does not need to be mutable
     let mut _allowed = 1i;
 }
 
-fn callback(f: ||) {}
+fn callback<F>(f: F) where F: FnOnce() {}
 
 // make sure the lint attribute can be turned off
 #[allow(unused_mut)]
index df3feefa881f3f28231da76f42a16c03d62c80c4..5c8e73e674751d109db04ffec9e4d657e0abae90 100644 (file)
@@ -20,7 +20,7 @@ mod foo {
     }
 }
 
-fn callback<T>(_f: || -> T) -> T { panic!() }
+fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
 unsafe fn unsf() {}
 
 fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
index 6466310eb4d2e133b681961478cc29941c38cd6e..82de02f09813ce9a7ca0acd663f32048cd1007a9 100644 (file)
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn force(f: || -> int) -> int { f() }
+fn force<F>(f: F) -> int where F: FnOnce() -> int { f() }
 fn main() { println!("{}", force(|| {})); } //~ ERROR mismatched types
index ee57377943d12b28a962c6316dee3b81cdcc7f24..14af49dfc49c5d379c9907fb9b49e66041d659a9 100644 (file)
@@ -20,7 +20,7 @@ enum E {
     Baz
 }
 
-fn f(s: &S, g: |&S|) {
+fn f<G>(s: &S, g: G) where G: FnOnce(&S) {
     g(s)
 }
 
index f9614574abda970b749a44f43b6781085caa7e74..ab762332ee43da3ba48d32eeca32b4ca3cfd4b25 100644 (file)
@@ -14,5 +14,5 @@ fn test(_x: Box<uint>) {}
 
 fn main() {
     let i = box 3;
-    let _f = || test(i); //~ ERROR cannot move out
+    let _f = |&:| test(i); //~ ERROR cannot move out
 }
index 2a73b769895eeeb75be648157400f0bc3d73d75d..9053f97e8a7dd9368c3395160701510edf8b72e3 100644 (file)
 // bound must be noncopyable. For details see
 // http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
 
+#![feature(unboxed_closures)]
+
 struct R<'a> {
     // This struct is needed to create the
     // otherwise infinite type of a fn that
     // accepts itself as argument:
-    c: |&mut R, bool|: 'a
+    c: Box<FnMut(&mut R, bool) + 'a>
 }
 
 fn innocent_looking_victim() {
@@ -28,7 +30,7 @@ fn innocent_looking_victim() {
             match x {
                 Some(ref msg) => {
                     (f.c)(f, true);
-                    //~^ ERROR: cannot borrow `*f` as mutable because
+                    //~^ ERROR: cannot borrow `*f` as mutable more than once at a time
                     println!("{}", msg);
                 },
                 None => panic!("oops"),
@@ -37,8 +39,8 @@ fn innocent_looking_victim() {
     })
 }
 
-fn conspirator(f: |&mut R, bool|) {
-    let mut r = R {c: f};
+fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
+    let mut r = R {c: box f};
     f(&mut r, false) //~ ERROR use of moved value
 }
 
index 4de56e32f560a98ba7dbb34e459bede38f950d01..ebda4e9103d604669547d28dd73e1d4e2a2aef8f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn let_in<T>(x: T, f: |T|) {}
+fn let_in<T, F>(x: T, f: F) where F: FnOnce(T) {}
 
 fn main() {
     let_in(3u, |i| { assert!(i == 3i); });
index 954d4b23e30faa942734b7a752d885591b0116d4..575e9864a92d3bd633febe9e08cdfb73c86acf9f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let f = |3: int| println!("hello");
+    let f = |&: 3: int| println!("hello");
     //~^ ERROR refutable pattern in function argument: `_` not covered
     f(4);
 }
index 13ab7acaf48353b99391e48826941e33afe59d4d..9e8281faf2f567c4f4bf4561182420c0771a1885 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn call_rec(f: |uint| -> uint) -> uint {
-    (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f`
+fn call_rec<F>(mut f: F) -> uint where F: FnMut(uint) -> uint {
+    (|&mut: x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/regionck-closure-lifetimes.rs b/src/test/compile-fail/regionck-closure-lifetimes.rs
deleted file mode 100644 (file)
index bb895a3..0000000
+++ /dev/null
@@ -1,60 +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 env<'a>(blk: |p: ||: 'a|) {
-    // Test that the closure here cannot be assigned
-    // the lifetime `'a`, which outlives the current
-    // block.
-
-    let mut state = 0i;
-    let statep = &mut state;
-    blk(|| *statep = 1i); //~ ERROR captured variable `statep` does not outlive
-}
-
-fn no_env_no_for<'a>(blk: |p: |||: 'a) {
-    // Test that a closure with no free variables CAN
-    // outlive the block in which it is created.
-
-    blk(|| ())
-}
-
-fn repeating_loop() {
-    // Test that the closure cannot be created within `loop` loop and
-    // called without, even though the state that it closes over is
-    // external to the loop.
-
-    let closure;
-    let state = 0i;
-
-    loop {
-        closure = || state; //~ ERROR cannot infer
-        break;
-    }
-
-    closure();
-}
-
-fn repeating_while() {
-    // Test that the closure cannot be created within `while` loop and
-    // called without, even though the state that it closes over is
-    // external to the loop.
-
-    let closure;
-    let state = 0i;
-
-    while true {
-        closure = || state; //~ ERROR cannot infer
-        break;
-    }
-
-    closure();
-}
-
-fn main() {}
index 7a146c043c8389cfb776c42dc104be176c666f5e..fb60d8f7b27a4acb442fe0fcc7b3fafc3b5911d3 100644 (file)
@@ -16,7 +16,7 @@ struct dog {
 
 impl dog {
     pub fn chase_cat(&mut self) {
-        let _f = || {
+        let _f = |&:| {
             let p: &'static mut uint = &mut self.food; //~ ERROR cannot infer
             *p = 3u;
         };
index e15cb25295aac7defa8ec6fa8766911fedf96830..0628bbb8bb08eb70a85813bb450bd8c8ee155da3 100644 (file)
@@ -69,11 +69,6 @@ fn object_with_send_bound_not_ok<'a>() {
     //~^ ERROR declared lifetime bound not satisfied
 }
 
-fn closure_with_lifetime_not_ok<'a>() {
-    assert_send::<||:'a>();
-    //~^ ERROR not implemented
-}
-
 // unsafe pointers are ok unless they point at unsendable things
 
 struct UniqueUnsafePtr(Unique<*const int>);
diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs
new file mode 100644 (file)
index 0000000..8466407
--- /dev/null
@@ -0,0 +1,83 @@
+// 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(associated_types)]
+
+trait X {}
+
+trait Iter {
+    type Item: X;
+
+    fn into_item(self) -> Self::Item;
+    fn as_item(&self) -> &Self::Item;
+}
+
+fn bad1<T: Iter>(v: T) -> Box<X+'static>
+{
+    let item = v.into_item();
+    box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad2<T: Iter>(v: T) -> Box<X+'static>
+    where Box<T::Item> : X
+{
+    let item = box v.into_item();
+    box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad3<'a, T: Iter>(v: T) -> Box<X+'a>
+{
+    let item = v.into_item();
+    box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad4<'a, T: Iter>(v: T) -> Box<X+'a>
+    where Box<T::Item> : X
+{
+    let item = box v.into_item();
+    box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn ok1<'a, T: Iter>(v: T) -> Box<X+'a>
+    where T::Item : 'a
+{
+    let item = v.into_item();
+    box item // OK, T::Item : 'a is declared
+}
+
+fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<X+'a>
+    where T::Item : Clone
+{
+    let item = Clone::clone(w);
+    box item // OK, T::Item : 'a is implied
+}
+
+fn ok3<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+    where T::Item : Clone + 'a
+{
+    let item = Clone::clone(v.as_item());
+    box item // OK, T::Item : 'a was declared
+}
+
+fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+    where T::Item : Clone
+{
+    // This case is kind of interesting. It's the same as `ok3` but
+    // without the explicit declaration. In principle, it seems like
+    // we ought to be able to infer that `T::Item : 'a` because we
+    // invoked `v.as_self()` which yielded a value of type `&'a
+    // T::Item`. But we're not that smart at present.
+
+    let item = Clone::clone(v.as_item());
+    box item //~ ERROR associated type `<T as Iter>::Item` may not live
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs
new file mode 100644 (file)
index 0000000..3e91d09
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+
+trait X {}
+
+fn p1<T>(v: T) -> Box<X+'static>
+    where T : X
+{
+    box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p2<T>(v: Box<T>) -> Box<X+'static>
+    where Box<T> : X
+{
+    box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p3<'a,T>(v: T) -> Box<X+'a>
+    where T : X
+{
+    box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+    where Box<T> : X
+{
+    box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn main() {}
+
index b15f0405d23c69bb5651e2003765a495b0aef151..1774c9fada946fc6a3806735a0052ace3f3d6a48 100644 (file)
@@ -27,14 +27,14 @@ fn compute(x: &ast) -> uint {
     }
 }
 
-fn map_nums<'a,'b>(x: &ast, f: |uint| -> uint) -> &'a ast<'b> {
+fn map_nums<'a,'b, F>(x: &ast, f: &mut F) -> &'a ast<'b> where F: FnMut(uint) -> uint {
     match *x {
       ast::num(x) => {
-        return &ast::num(f(x)); //~ ERROR borrowed value does not live long enough
+        return &ast::num((*f)(x)); //~ ERROR borrowed value does not live long enough
       }
       ast::add(x, y) => {
-        let m_x = map_nums(x, |z| f(z));
-        let m_y = map_nums(y, |z| f(z));
+        let m_x = map_nums(x, f);
+        let m_y = map_nums(y, f);
         return &ast::add(m_x, m_y);  //~ ERROR borrowed value does not live long enough
       }
     }
index 66103eb95888ac941e1cf123c8641d2b0978c584..547accbf0860d27ce85d7b65aedc27f0c709123d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: |x: &int|) {
+fn with_int<F>(f: F) where F: FnOnce(&int) {
     let x = 3;
     f(&x);
 }
index fee84cf9656d1ceaae73f4fb5d02a75c55a63579..6d67bd80650fad0afa66f5e2a9e46087345eaa59 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn with_int(f: |x: &int|) {
+fn with_int<F>(f: F) where F: FnOnce(&int) {
     let x = 3;
     f(&x);
 }
index f92c264784ae6a402dc6d8d60e69e29d63b4abdd..e3771cfebba255cf7f656f3e4153486b0c6c6829 100644 (file)
@@ -16,7 +16,7 @@
 struct S;
 
 impl S {
-    fn f<B>(&self, _: |&i32| -> B) {
+    fn f<B, F>(&self, _: F) where F: FnOnce(&i32) -> B {
     }
 }
 
index adc960b069d05d89f798d1a7e7673c5445e1189a..873d4cea0395e627f2dcbfcecdef8b4c59e19c81 100644 (file)
@@ -20,7 +20,7 @@ fn get(self) -> int {
     }
 }
 
-fn with<R:Deref>(f: |x: &int| -> R) -> int {
+fn with<R:Deref, F>(f: F) -> int where F: FnOnce(&int) -> R {
     f(&3).get()
 }
 
diff --git a/src/test/compile-fail/regions-fn-subtyping.rs b/src/test/compile-fail/regions-fn-subtyping.rs
deleted file mode 100644 (file)
index 91a6ff7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn of<'a,T>() -> |T|:'a { 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.
-
-    subtype::< for<'a>|&'a T|>(
-        of::< for<'a>|&'a T|>());
-
-    subtype::< for<'a>|&'a T|>(
-        of::< for<'b>|&'b T|>());
-
-    subtype::< for<'b>|&'b T|>(
-        of::<|&'x T|>());
-
-    subtype::<|&'x T|>(
-        of::< for<'b>|&'b T|>());  //~ ERROR mismatched types
-
-    subtype::< for<'a,'b>|&'a T, &'b T|>(
-        of::< for<'a>|&'a T, &'a T|>());
-
-    subtype::< for<'a>|&'a T, &'a T|>(
-        of::< for<'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
-
-    subtype::< for<'a,'b>|&'a T, &'b T|>(
-        of::<|&'x T, &'y T|>());
-
-    subtype::<|&'x T, &'y T|>(
-        of::< for<'a,'b>|&'a T, &'b T|>()); //~ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/regions-fns.rs b/src/test/compile-fail/regions-fns.rs
deleted file mode 100644 (file)
index 854584e..0000000
+++ /dev/null
@@ -1,21 +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.
-
-// Before fn subtyping was properly implemented,
-// we reported errors in this case:
-
-fn not_ok<'b>(a: &uint, b: &'b uint) {
-    let mut g: |x: &uint| = |x: &'b uint| {};
-    //~^ ERROR mismatched types
-    g(a);
-}
-
-fn main() {
-}
index 435d10a0a29a1c07db7a43a40d2ca3bfee547143..6e59a29b8cf2236f8e57110c0f4d00171b5eb47a 100644 (file)
@@ -30,7 +30,7 @@ fn ordering3<'a, 'b>(x: &'a uint, y: &'b uint) -> &'a &'b uint {
     panic!();
 }
 
-fn ordering4<'a, 'b>(a: &'a uint, b: &'b uint, x: |&'a &'b uint|) {
+fn ordering4<'a, 'b, F>(a: &'a uint, b: &'b uint, x: F) where F: FnOnce(&'a &'b uint) {
     // Do not infer ordering from closure argument types.
     let z: Option<&'a &'b uint> = None;
     //~^ ERROR reference has a longer lifetime than the data it references
diff --git a/src/test/compile-fail/regions-freevar.rs b/src/test/compile-fail/regions-freevar.rs
deleted file mode 100644 (file)
index 76bbe71..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn wants_static_fn(_x: ||: 'static) {}
-
-fn main() {
-    let i = 3i;
-    wants_static_fn(|| {
-        println!("i={}", i); //~ ERROR captured variable `i` does not outlive
-    })
-}
index 8af341e3ace42b9d949319d92199f98008180d8b..0c250e38258cec518bddb3a48a81e14c965be69b 100644 (file)
@@ -9,15 +9,15 @@
 // except according to those terms.
 
 struct parameterized1<'a> {
-    g: ||: 'a
+    g: Box<FnMut() + 'a>
 }
 
 struct not_parameterized1 {
-    g: ||: 'static
+    g: Box<FnMut() + 'static>
 }
 
 struct not_parameterized2 {
-    g: ||: 'static
+    g: Box<FnMut() + 'static>
 }
 
 fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
index cf1fa2cfc4c2cbd8986f850bf48f8d06becf6086..c8edd936bf28b232a16e7fa50e33aded71fef4ef 100644 (file)
 
 fn borrow<T>(x: &T) -> &T {x}
 
-fn foo(cond: || -> bool, make_box: || -> Box<int>) {
+fn foo<C, M>(mut cond: C, mut make_box: M) where
+    C: FnMut() -> bool,
+    M: FnMut() -> Box<int>,
+{
     let mut y: &int;
     loop {
         let x = make_box();
index 66f958c789336a1b778d7028d062e942379bb91d..ac41f2a5b3e47be208a6c53d257990538ab6dc51 100644 (file)
@@ -10,7 +10,7 @@
 
 fn select<'r>(x: &'r int, y: &'r int) -> &'r int { x }
 
-fn with<T>(f: |x: &int| -> T) -> T {
+fn with<T, F>(f: F) -> T where F: FnOnce(&int) -> T {
     f(&20)
 }
 
index 33573cae0f66d5a2aa78d6c2d0b0348433de651d..190e444fe7e830bc92879e0e8792547767f753bb 100644 (file)
@@ -10,7 +10,7 @@
 
 
 struct invariant<'a> {
-    f: |x: &mut &'a int|: 'static
+    f: Box<FnOnce(&mut &'a int) + 'static>,
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
index 66dcb5fdebd2d0fa3d4bee961aadf0b807854160..71d0c988c5e274e0849c8c6b8b24c4169d0f14d6 100644 (file)
@@ -10,7 +10,7 @@
 
 
 struct invariant<'a> {
-    f: ||: 'static -> &mut &'a int
+    f: Box<for<'b> FnOnce() -> &'b mut &'a int + 'static>,
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
index b84f13ec37feb44d16654af4e6bf795c965046f3..323ebc3c20b37c3aad95cc84735b4de70bdc0483 100644 (file)
@@ -14,12 +14,12 @@ struct direct<'a> {
 
 struct indirect1 {
     // Here the lifetime parameter of direct is bound by the fn()
-    g: |direct|: 'static
+    g: Box<FnOnce(direct) + 'static>
 }
 
 struct indirect2<'a> {
     // But here it is set to 'a
-    g: |direct<'a>|: 'static
+    g: Box<FnOnce(direct<'a>) + 'static>
 }
 
 fn take_direct<'a,'b>(p: direct<'a>) -> direct<'b> { p } //~ ERROR mismatched types
index ffd1501075e94c594b3e3f7c9932f742654196c1..b9c721159f2b44c125117afe7e7523f6b047a821 100644 (file)
@@ -43,19 +43,16 @@ fn f(a: &'a int) { } //~ ERROR undeclared lifetime
 
     // &'a CAN be declared on functions and used then:
     fn g<'a>(a: &'a int) { } // OK
-    fn h(a: for<'a>|&'a int|) { } // OK
-
-    // But not in the bound of a closure, it's not in scope *there*
-    fn i(a: for<'a>|&int|:'a) { } //~ ERROR undeclared lifetime
+    fn h(a: Box<for<'a> FnOnce(&'a int)>) { } // OK
 }
 
 // Test nesting of lifetimes in fn type declarations
 fn fn_types(a: &'a int, //~ ERROR undeclared lifetime
-            b: for<'a>|a: &'a int,
-                       b: &'b int, //~ ERROR undeclared lifetime
-                       c: for<'b>|a: &'a int,
-                                  b: &'b int|,
-                       d: &'b int|, //~ ERROR undeclared lifetime
+            b: Box<for<'a> FnOnce(&'a int,
+                                  &'b int, //~ ERROR undeclared lifetime
+                                  Box<for<'b> FnOnce(&'a int,
+                                                     &'b int)>,
+                                  &'b int)>, //~ ERROR undeclared lifetime
             c: &'a int) //~ ERROR undeclared lifetime
 {
 }
index a08cf2263894dfc5396a63164f119f48588b16a8..b7fe893a1f5bbca1a2857c8b9212e0238b02bdcc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn ignore(_f: for<'z>|&'z int| -> &'z int) {}
+fn ignore<F>(_f: F) where F: for<'z> FnOnce(&'z int) -> &'z int {}
 
 fn nested() {
     let y = 3;
index f4654367970d11d052b16a23f73f54b8933e3113..5d8ef718ef0d354b7bfe93720256f002b8f55c2a 100644 (file)
@@ -14,13 +14,13 @@ fn nested<'x>(x: &'x int) {
     let y = 3;
     let mut ay = &y;
 
-    ignore::< for<'z>|&'z int|>(|z| {
+    ignore::<Box<for<'z> FnMut(&'z int)>>(box |z| {
         ay = x; //~ ERROR cannot infer
         ay = &y;
         ay = z;
     });
 
-    ignore::< for<'z>|&'z int| -> &'z int>(|z| {
+    ignore::< Box<for<'z> FnMut(&'z int) -> &'z int>>(box |z| {
         if false { return x; }  //~ ERROR cannot infer an appropriate lifetime for automatic
         if false { return ay; }
         return z;
diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs
new file mode 100644 (file)
index 0000000..3f722c9
--- /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.
+
+fn assert_send<T: Send>(_t: T) {}
+
+fn main() {
+    let line = String::new();
+    match [line.as_slice()] { //~ ERROR `line` does not live long enough
+        [ word ] => { assert_send(word); }
+    }
+}
diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs
new file mode 100644 (file)
index 0000000..da839d7
--- /dev/null
@@ -0,0 +1,20 @@
+// 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 a0 = 0u8;
+    let f = 1u8;
+    let mut a1 = &a0;
+    match (&a1,) {
+        (&ref b0,) => {
+            a1 = &f; //~ ERROR cannot assign
+        }
+    }
+}
index 47fca8bb8df2374e83395d5a46599afbf96441cd..f9eecb60c6af118a72680ad92e3ef5fb1f7bc9b6 100644 (file)
@@ -13,7 +13,7 @@ fn arg_item(box ref x: Box<int>) -> &'static int {
     x //~^ ERROR borrowed value does not live long enough
 }
 
-fn with<R>(f: |Box<int>| -> R) -> R { f(box 3) }
+fn with<R, F>(f: F) -> R where F: FnOnce(Box<int>) -> R { f(box 3) }
 
 fn arg_closure() -> &'static int {
     with(|box ref x| x) //~ ERROR borrowed value does not live long enough
index 997775efa84b52d60756dfc3ed3c62652f37dbbb..bd14d31217e88269ee580d55bdb45ed2fa255b03 100644 (file)
@@ -12,7 +12,7 @@
 // some point regions-ret-borrowed reported an error but this file did
 // not, due to special hardcoding around the anonymous region.
 
-fn with<R>(f: for<'a>|x: &'a int| -> R) -> R {
+fn with<R, F>(f: F) -> R where F: for<'a> FnOnce(&'a int) -> R {
     f(&3)
 }
 
index 465f4410fbbccb2d05451c0db6240e5433815a9f..4dfd4f1709a6f2894da09c0d2a7deac419595b32 100644 (file)
@@ -15,7 +15,7 @@
 // used to successfully compile because we failed to account for the
 // fact that fn(x: &int) rebound the region &.
 
-fn with<R>(f: |x: &int| -> R) -> R {
+fn with<R, F>(f: F) -> R where F: FnOnce(&int) -> R {
     f(&3)
 }
 
index aedaced5794a784a9449be54262e31beab676478..d7b2a45cc63bb6f10457472e5ba11db80dbc0604 100644 (file)
@@ -20,11 +20,4 @@ fn main() {
         let x = f();
         let y = f();
     }
-    // Boxed closure case
-    {
-        let mut x = 0u;
-        let f = || &mut x; //~ ERROR cannot infer
-        let x = f();
-        let y = f();
-    }
 }
index 7ffc6a75cff8ca9ac9d5a8b48a3d5fecf355f45b..991040bc62fea1ef8f4151002c6187db889e9283 100644 (file)
@@ -8,18 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 struct closure_box<'a> {
-    cl: ||: 'a
+    cl: Box<FnMut() + 'a>,
 }
 
-fn box_it<'r>(x: ||: 'r) -> closure_box<'r> {
+fn box_it<'r>(x: Box<FnMut() + 'r>) -> closure_box<'r> {
     closure_box {cl: x}
 }
 
 fn main() {
     let cl_box = {
-        let mut i = 3;
-        box_it(|| i += 1) //~ ERROR cannot infer
+        let mut i = 3i;
+        box_it(box || i += 1) //~ ERROR cannot infer
     };
-    (cl_box.cl)();
+    cl_box.cl.call_mut(());
 }
diff --git a/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs b/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs
new file mode 100644 (file)
index 0000000..e6dc712
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::kinds::Send;
+
+struct TestType;
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative trait bounds
+
+fn main() {}
diff --git a/src/test/compile-fail/syntax-trait-polarity.rs b/src/test/compile-fail/syntax-trait-polarity.rs
new file mode 100644 (file)
index 0000000..3c84bc2
--- /dev/null
@@ -0,0 +1,33 @@
+// 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(optin_builtin_traits)]
+
+use std::kinds::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent implementation can't be negated
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+impl !TestTrait for TestType {}
+
+struct TestType2<T>;
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent implementation can't be negated
+
+unsafe impl<T> !Send for TestType2<T> {}
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
index ac2f9d0379f64d1a63bd3c468ceb032e53bca8c6..3249794e5c822a879e0b83e6f5356cb1b93510bc 100644 (file)
@@ -10,6 +10,6 @@
 
 // error-pattern:can't use type parameters from outer function; try using
 fn foo<T>(x: T) {
-    fn bar(f: |T| -> T) { }
+    fn bar(f: Box<FnMut(T) -> T>) { }
 }
 fn main() { foo(1); }
index b3528f7abe71927f0c8284dae48340f0d1347bb6..61f1317283272b8737c17bc76b572bc771d2e48a 100644 (file)
@@ -14,6 +14,6 @@
 
 pub fn main() {
     let mut f = |&mut: x: int, y: int| -> int { x + y };
-    let z = f.call_mut((1u, 2));    //~ ERROR type mismatch
+    let z = f(1u, 2);    //~ ERROR mismatched types
     println!("{}", z);
 }
index a96bde7cca4cdcb06ce12c1140709b7b9aa22e32..85b33f73bbcb7cdefbbc419691ba8738458206f8 100644 (file)
@@ -13,7 +13,7 @@
 use std::ops::FnMut;
 
 fn call_it<F:FnMut<(int,int),int>>(y: int, mut f: F) -> int {
-    f.call_mut((2, y))
+    f(2, y)
 }
 
 pub fn main() {
index 43db4dfd395b059e1cbd835d653a1f28b28928ab..92dbea0424b6f6627bcd1faccf790bd64faae656 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test syntax checks for `type` keyword.
 
-struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name, found `for`
+struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for`
 
 pub fn main() {
 }
diff --git a/src/test/compile-fail/variance-trait-matching-2.rs b/src/test/compile-fail/variance-trait-matching-2.rs
deleted file mode 100644 (file)
index cae7a4c..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.
-
-extern crate serialize;
-
-use std::fmt;
-use serialize::{Encodable, Encoder};
-
-pub fn buffer_encode<'a,
-                     T:Encodable<serialize::json::Encoder<'a>,fmt::Error>>(
-                     to_encode_object: &T)
-                     -> String {
-    let mut m = String::new();
-    {
-        let mut encoder =
-            serialize::json::Encoder::new(&mut m);
-        //~^ ERROR `m` does not live long enough
-        to_encode_object.encode(&mut encoder);
-    }
-    m
-}
-
-fn main() {}
index 84366ae71146501ee1e25e61d44c4d67fc009f78..e3cb190c3f2c46162ab1a7bb85a848f6c65ae9c7 100644 (file)
@@ -50,7 +50,7 @@
 
 fn some_generic_fun<T1, T2>(a: T1, b: T2) -> (T2, T1) {
 
-    let closure = |x, y| {
+    let closure = |&: x, y| {
         zzz(); // #break
         (y, x)
     };
index b451f61d05e0efd9edaec24a4810d140b5905648..b2617c57742522c6788e0e32c0e80df6b86f62cc 100644 (file)
@@ -18,7 +18,7 @@
 
 // Nothing to do here really, just make sure it compiles. See issue #8513.
 fn main() {
-    let _ = ||();
+    let _ = |&:|();
     let _ = range(1u,3).map(|_| 5i);
 }
 
index d6e3a43eea0a6383f478ebf0a23243515bfcff8c..f2d092216697ff25c543c4f380daff04703f4a23 100644 (file)
@@ -79,7 +79,7 @@ fn main() {
     zzz(); // #break
     sentinel();
 
-    let stack_closure: |int| = |x| {
+    let closure = |&: x: int| {
         zzz(); // #break
         sentinel();
 
@@ -97,7 +97,7 @@ fn main() {
     zzz(); // #break
     sentinel();
 
-    stack_closure(1000);
+    closure(1000);
 
     zzz(); // #break
     sentinel();
index dd0d86bf742e6415adadd180bc6e836bfee08d05..cb7e26327c3def2f52406095226ad97a03475a21 100644 (file)
@@ -24,5 +24,5 @@ struct C { θ: u8 }
 
 fn main() {
     let x =  C { θ: 0 };
-    (|c: C| c.θ )(x);
+    (|&: c: C| c.θ )(x);
 }
index 93348e7b53e559b9732726850bae5c61fb1898ed..73a68893e933cac81089fa72a0b11d63a88cd2bd 100644 (file)
@@ -25,11 +25,9 @@ pub struct Window<'a> {
 }
 
 struct WindowCallbacks<'a> {
-    pos_callback: Option<WindowPosCallback<'a>>,
+    pos_callback: Option<Box<FnMut(&Window, i32, i32) + 'a>>,
 }
 
-pub type WindowPosCallback<'a> = |&Window, i32, i32|: 'a;
-
 fn main() {
     let x = WindowCallbacks { pos_callback: None };
 }
index ddcbfdcceee01c2c8bbb36d54055a53990cd3d62..aac5824af00507e6731cc860e5b2762f7e47c7f8 100644 (file)
 
 
 // CLOSURES
-// gdb-command:whatis stack_closure1
-// gdb-check:type = struct (&mut|int|, uint)
+// gdb-command:whatis closure1
+// gdb-check:type = struct (closure, uint)
 
-// gdb-command:whatis stack_closure2
-// gdb-check:type = struct (&mut|i8, f32| -> f32, uint)
+// gdb-command:whatis closure2
+// gdb-check:type = struct (closure, uint)
 
 #![omit_gdb_pretty_printer_section]
 
@@ -321,8 +321,8 @@ fn main() {
     // how that maps to rustc's internal representation of these forms.
     // Once closures have reached their 1.0 form, the tests below should
     // probably be expanded.
-    let stack_closure1 = (|x:int| {}, 0u);
-    let stack_closure2 = (|x:i8, y: f32| { (x as f32) + y }, 0u);
+    let closure1 = (|&: x:int| {}, 0u);
+    let closure2 = (|&: x:i8, y: f32| { (x as f32) + y }, 0u);
 
     zzz(); // #break
 }
index 99d67c60516b5a6fe1e8652c6efcf6e6952b7c4a..3a7fbb9a3a1324ad02b515c53c257f2c401e4f9e 100644 (file)
@@ -100,10 +100,10 @@ fn main() {
     let struct_ref = &a_struct;
     let owned = box 6;
 
-    let closure = || {
+    let mut closure = |&mut:| {
         let closure_local = 8;
 
-        let nested_closure = || {
+        let mut nested_closure = |&mut:| {
             zzz(); // #break
             variable = constant + a_struct.a + struct_ref.a + *owned + closure_local;
         };
index f474e8d1317993feb8647e2d2626a4fb32ab9b9f..a743adae51e9c54e01989351a4fa4ead3e7d09ad 100644 (file)
@@ -94,20 +94,20 @@ fn main() {
     let owned = box 6;
 
     {
-        let closure = || {
+        let mut first_closure = |&mut:| {
             zzz(); // #break
             variable = constant + a_struct.a + struct_ref.a + *owned;
         };
 
-        closure();
+        first_closure();
     }
 
     {
-        let mut unboxed_closure = |&mut:| {
+        let mut second_closure = |&mut:| {
             zzz(); // #break
             variable = constant + a_struct.a + struct_ref.a + *owned;
         };
-        unboxed_closure();
+        second_closure();
     }
 }
 
index 328d4245eb61011acc5edbff4e2998a7356c513d..094e3ce91568623094d272c85a5c10366498be88 100644 (file)
@@ -15,9 +15,9 @@
 
 fn call_it(f: Box<FnMut(String) -> String>) { }
 
-fn call_this(f: |&str|: Send) { }
+fn call_this<F>(f: F) where F: Fn(&str) + Send { }
 
-fn call_that(f: <'a>|&'a int, &'a int| -> int) { }
+fn call_that<F>(f: F) where F: for<'a>Fn(&'a int, &'a int) -> int { }
 
 fn call_extern(f: fn() -> int) { }
 
index 78658a4c12169db5709fcdefc9dd14c3c5ed4f97..0c4cd103b82ef73547ebf7c1e32da23d101d18ef 100644 (file)
@@ -14,7 +14,7 @@
 // preserved.  They are needed to disambiguate `{return n+1}; - 0` from
 // `({return n+1}-0)`.
 
-fn id(f: || -> int) -> int { f() }
+fn id<F>(f: F) -> int where F: Fn() -> int { f() }
 
 fn wsucc(_n: int) -> int { id(|| { 1 }) - 0 }
 fn main() { }
index cd7a5b29a8af1eef189c8604220e33efad5a995e..e0066053f3c5baf5b9d2f0ad2c347055a7b5db10 100644 (file)
@@ -10,6 +10,6 @@
 
 // pp-exact
 
-fn f(f: |int|) { f(10) }
+fn f<F>(f: F) where F: Fn(int) { f(10) }
 
 fn main() { f(|i| { assert!(i == 10) }) }
index 1313af2df3d88c742a5b11f7b9658ca6519157e4..31efb0c9ab1ebd84f9a87f6126194232faaf846f 100644 (file)
@@ -11,5 +11,5 @@
 // pp-exact
 
 fn from_foreign_fn(_x: fn()) { }
-fn from_stack_closure(_x: ||) { }
+fn from_stack_closure<F>(_x: F) where F: Fn() { }
 fn main() { }
diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs
new file mode 100644 (file)
index 0000000..47c36ac
--- /dev/null
@@ -0,0 +1,23 @@
+// 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(optin_builtin_traits)]
+
+// pp-exact
+
+trait UnsafeTrait {
+    fn foo(&self);
+}
+
+impl !UnsafeTrait for int {
+    fn foo(&self) { }
+}
+
+pub fn main() { }
index 5e75e1cd1cbdcfa701237d14d46bb65ec307430e..c3fa1a68e164c4e491909effa259f37813083f82 100644 (file)
@@ -19,7 +19,7 @@ fn drop(&mut self) {
     }
 }
 
-pub fn callback(f: ||) {
+pub fn callback<F>(f: F) where F: FnOnce() {
     let _a = A;
     f();
 }
index 75e197923c635448efdd22735f0be3d1068387e8..dfce311529028c49d02e0ff9a62afe770e50e9ea 100644 (file)
@@ -20,7 +20,7 @@ fn f1(a: &mut X, b: &mut int, c: int) -> int {
     return r;
 }
 
-fn f2(a: int, f: |int|) -> int { f(1); return a; }
+fn f2<F>(a: int, f: F) -> int where F: FnOnce(int) { f(1); return a; }
 
 pub fn main() {
     let mut a = X {x: 1};
diff --git a/src/test/run-pass/associated-type-doubleendediterator-object.rs b/src/test/run-pass/associated-type-doubleendediterator-object.rs
new file mode 100644 (file)
index 0000000..429027c
--- /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.
+
+fn pairwise_sub(mut t: Box<DoubleEndedIterator<Item=int>>) -> int {
+    let mut result = 0;
+    loop {
+        let front = t.next();
+        let back = t.next_back();
+        match (front, back) {
+            (Some(f), Some(b)) => { result += b - f; }
+            _ => { return result; }
+        }
+    }
+}
+
+fn main() {
+    let v = vec!(1, 2, 3, 4, 5, 6);
+    let r = pairwise_sub(box v.into_iter());
+    assert_eq!(r, 9);
+}
diff --git a/src/test/run-pass/associated-types-iterator-binding.rs b/src/test/run-pass/associated-types-iterator-binding.rs
new file mode 100644 (file)
index 0000000..f825846
--- /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.
+
+fn pairwise_sub<T:DoubleEndedIterator<Item=int>>(mut t: T) -> int {
+    let mut result = 0;
+    loop {
+        let front = t.next();
+        let back = t.next_back();
+        match (front, back) {
+            (Some(f), Some(b)) => { result += b - f; }
+            _ => { return result; }
+        }
+    }
+}
+
+fn main() {
+    let v = vec!(1, 2, 3, 4, 5, 6);
+    let r =pairwise_sub(v.into_iter());
+    assert_eq!(r, 9);
+}
index f5766ae1e53c291251d821a870f02038f99f90bf..ed471ed0079e3c5cd21166e7fbd7e47c397ffb9a 100644 (file)
 
 fn f<T>(x: Vec<T>) -> T { return x.into_iter().next().unwrap(); }
 
-fn g(act: |Vec<int> | -> int) -> int { return act(vec!(1, 2, 3)); }
+fn g<F>(act: F) -> int where F: FnOnce(Vec<int>) -> int { return act(vec!(1, 2, 3)); }
 
 pub fn main() {
     assert_eq!(g(f), 1);
-    let f1: |Vec<String>| -> String = f;
+    let f1 = f;
     assert_eq!(f1(vec!["x".to_string(), "y".to_string(), "z".to_string()]),
                "x".to_string());
 }
index b4e366296517416d9be41076e3c208f8b47cd8dd..6c54f33fbe6c927e26a25d0a846748351ca34723 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn asBlock(f: || -> uint) -> uint {
+fn asBlock<F>(f: F) -> uint where F: FnOnce() -> uint {
    return f();
 }
 
index 63051d71271dde0314978206707352e4be051686..54b650d762bf46b2af5c0fa7c9004057c1d92e87 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 pub fn main() {
-    fn as_buf<T>(s: String, f: |String| -> T) -> T { f(s) }
+    fn as_buf<T, F>(s: String, f: F) -> T where F: FnOnce(String) -> T { f(s) }
     as_buf("foo".to_string(), |foo: String| -> () println!("{}", foo) );
 }
index bbb30e9578e9e10a26389db3b2e3efafa327f6c0..fe52b1a693cdcb9f76f71ac95c94fcb7450f5f05 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn force(f: || -> int) -> int { return f(); }
+fn force<F>(f: F) -> int where F: FnOnce() -> int { return f(); }
+
 pub fn main() {
     fn f() -> int { return 7; }
     assert_eq!(force(f), 7);
-    let g = {||force(f)};
+    let g = {|&:|force(f)};
     assert_eq!(g(), 7);
 }
index ce20c3024d6fb7e2d186fdf4197fc6a094cda62d..972bde5f29a0d0f78ceff1cdf35940606d16b57c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn iter_vec<T>(v: Vec<T> , f: |&T|) { for x in v.iter() { f(x); } }
+fn iter_vec<T, F>(v: Vec<T> , mut f: F) where F: FnMut(&T) { for x in v.iter() { f(x); } }
 
 pub fn main() {
     let v = vec!(1i, 2, 3, 4, 5, 6, 7);
index 7bb9d0ddf99af1aa93237eb1296f04fa36d612b5..1032fb486a1ed08f94f217a634e50c561024458c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn iter_vec<T>(v: Vec<T> , f: |&T|) { for x in v.iter() { f(x); } }
+fn iter_vec<T, F>(v: Vec<T>, mut f: F) where F: FnMut(&T) { for x in v.iter() { f(x); } }
 
 pub fn main() {
     let v = vec!(1i, 2, 3, 4, 5);
index 8c4995e710097b24366935a4c40cebf718c771e4..038f9e5c9ab43b7c94e781e08e63296c4f7d6e7d 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn borrow(x: &int, f: |x: &int|) {
+fn borrow<F>(x: &int, f: F) where F: FnOnce(&int) {
     f(x)
 }
 
index 3bd12b030411e17b3340f4e502b18bdf06633338..33e4294366f075f93ccc05fb6a60f57e6dd38bca 100644 (file)
 // the closures are in scope. Issue #6801.
 
 fn a() -> int {
-    let mut x = 3;
+    let mut x = 3i;
     x += 1;
-    let c1 = || x * 4;
-    let c2 = || x * 5;
+    let c1 = |&:| x * 4;
+    let c2 = |&:| x * 5;
     c1() * c2() * x
 }
 
@@ -29,16 +29,16 @@ fn get(x: &int) -> int {
 fn b() -> int {
     let mut x = 3;
     x += 1;
-    let c1 = || get(&x);
-    let c2 = || get(&x);
+    let c1 = |&:| get(&x);
+    let c2 = |&:| get(&x);
     c1() * c2() * x
 }
 
 fn c() -> int {
     let mut x = 3;
     x += 1;
-    let c1 = || x * 5;
-    let c2 = || get(&x);
+    let c1 = |&:| x * 5;
+    let c2 = |&:| get(&x);
     c1() * c2() * x
 }
 
index 176c7277efddc8c4c14ae09161e42677701002e2..dac8945b6e828f850352afb4f5eda3c00f9f266e 100644 (file)
@@ -21,7 +21,7 @@ fn add_int(x: &mut Ints, v: int) {
     swap(&mut values, &mut x.values);
 }
 
-fn iter_ints(x: &Ints, f: |x: &int| -> bool) -> bool {
+fn iter_ints<F>(x: &Ints, mut f: F) -> bool where F: FnMut(&int) -> bool {
     let l = x.values.len();
     range(0u, l).all(|i| f(&x.values[i]))
 }
index c95cf0bfdee453d8c5a43bd9c20ecab323c39fb6..22c322b86c97963d800c3485a482d2c7aa2d846d 100644 (file)
@@ -12,7 +12,7 @@
 
 extern crate libc;
 
-use std::c_str::ToCStr;
+use std::ffi::CString;
 
 mod mlibc {
     use libc::{c_char, c_long, c_longlong};
@@ -24,11 +24,13 @@ mod mlibc {
 }
 
 fn atol(s: String) -> int {
-    s.as_slice().with_c_str(|x| unsafe { mlibc::atol(x) as int })
+    let c = CString::from_slice(s.as_bytes());
+    unsafe { mlibc::atol(c.as_ptr()) as int }
 }
 
 fn atoll(s: String) -> i64 {
-    s.as_slice().with_c_str(|x| unsafe { mlibc::atoll(x) as i64 })
+    let c = CString::from_slice(s.as_bytes());
+    unsafe { mlibc::atoll(c.as_ptr()) as i64 }
 }
 
 pub fn main() {
index 432d022c69b779a2a6f05c66b6504fcb7506be56..29fcdf504de6e53ca6ef5219b3f1ed51e59b244b 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 fn foo() -> int { 22 }
 
 pub fn main() {
index d24b9332917bf9ee96da2d9f0ef1b8751c5f60cd..6e8ed4fd5a15a3bca26550b7d8f61e321487a9f7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn each<T>(x: &[T], f: |&T|) {
+fn each<T, F>(x: &[T], mut f: F) where F: FnMut(&T) {
     for val in x.iter() {
         f(val)
     }
index 410b74165460232c9c8840872418d3c43ff859bd..893003dd997226171d8ce39966524097eb9bae40 100644 (file)
@@ -11,9 +11,9 @@
 
 fn foo(i: int) -> int { i + 1 }
 
-fn apply<A>(f: |A| -> A, v: A) -> A { f(v) }
+fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
 
 pub fn main() {
-    let f = {|i| foo(i)};
+    let f = {|i| foo(i)};
     assert_eq!(apply(f, 2), 3);
 }
index 6666b8e3cfad581e4f20508c23c92dfbddd0adb7..03b10b881f7ae95004971490d64d7d8070a30141 100644 (file)
@@ -11,7 +11,7 @@
 // Test a rather underspecified example:
 
 pub fn main() {
-    let f = {|i| i};
+    let f = {|&: i| i};
     assert_eq!(f(2i), 2i);
     assert_eq!(f(5i), 5i);
 }
index 03d9511b41c78c31f95a897b81c0816154e6c1a8..a2e7d7bd7e3e3137ec7ba288be539c742ac0953f 100644 (file)
@@ -22,25 +22,14 @@ fn call_it<F>(f: F)
     println!("{}", f("Fred".to_string()))
 }
 
-fn call_a_thunk(f: ||) {
+fn call_a_thunk<F>(f: F) where F: FnOnce() {
     f();
 }
 
-fn call_this(f: |&str|:Send) {
+fn call_this<F>(f: F) where F: FnOnce(&str) + Send {
     f("Hello!");
 }
 
-fn call_that(f: <'a>|&'a int, &'a int| -> int) {
-    let (ten, forty_two) = (10, 42);
-    println!("Your lucky number is {}", f(&ten, &forty_two));
-}
-
-fn call_cramped(f:||->uint,g:<'a>||->&'a uint) {
-    let number = f();
-    let other_number = *g();
-    println!("Ticket {} wins an all-expenses-paid trip to Mountain View", number + other_number);
-}
-
 fn call_bare(f: fn(&str)) {
     f("Hello world!")
 }
@@ -71,16 +60,6 @@ pub fn main() {
 
     call_this(|s| println!("{}", s));
 
-    call_that(|x, y| *x + *y);
-
-    let z = 100;
-    call_that(|x, y| *x + *y - z);
-
-    call_cramped(|| 1, || unsafe {
-        static a: uint = 100;
-        mem::transmute(&a)
-    });
-
     // External functions
 
     call_bare(println);
diff --git a/src/test/run-pass/closure-return-bang.rs b/src/test/run-pass/closure-return-bang.rs
deleted file mode 100644 (file)
index 9b4033a..0000000
+++ /dev/null
@@ -1,20 +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.
-
-#![allow(dead_code)]
-
-fn f(x: || -> !) -> ! {
-    x();
-}
-
-fn main() {
-    let x: || -> ! = || panic!();
-    let _y: || -> ! = || x();
-}
diff --git a/src/test/run-pass/closure-syntax.rs b/src/test/run-pass/closure-syntax.rs
deleted file mode 100644 (file)
index 4caa234..0000000
+++ /dev/null
@@ -1,79 +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.
-
-#![allow(dead_code)]
-#![feature(unboxed_closures)]
-
-// compile-flags:-g
-
-fn foo<T>() {}
-
-trait Bar3 {}
-impl<'b> Bar3 for <'a>|&'a int|: 'b + Send -> &'a int {}
-
-struct Foo<'a> {
-    a: ||: 'a,
-    b: ||: 'static,
-    c: <'b>||: 'a,
-    d: ||: 'a + Sync,
-    e: <'b>|int|: 'a + Sync -> &'b f32,
-}
-
-fn f<'a>(a: &'a int, f: <'b>|&'b int| -> &'b int) -> &'a int {
-    f(a)
-}
-
-fn g<'a>(a: &'a int) -> &'a int {
-    a
-}
-
-struct A;
-
-impl A {
-    fn foo<T>(&self) {}
-}
-
-fn bar<'b>() {
-    foo::<||>();
-    foo::<|| -> ()>();
-    foo::<||:>();
-    foo::<||:'b>();
-    foo::<||:'b + Sync>();
-    foo::<||:Sync>();
-    foo::< <'a>|int, f32, &'a int|:'b + Sync -> &'a int>();
-
-    foo::<<'a>||>();
-
-    // issue #11209
-    let _: ||: 'b; // for comparison
-    let _: <'a> ||;
-
-    let _: Option<||:'b>;
-    let _: Option<<'a>||>;
-    let _: Option< <'a>||>;
-
-    // issue #11210
-    let _: ||: 'static;
-
-    let a = A;
-    a.foo::<<'a>||>();
-
-    // issue #13490
-    let _ = || -> ! loop {};
-
-    // issue #17021
-    let c = box |&:| {};
-}
-
-struct B<T>;
-impl<'b> B<<'a>||: 'b> {}
-
-pub fn main() {
-}
diff --git a/src/test/run-pass/coerce-to-closure-and-proc.rs b/src/test/run-pass/coerce-to-closure-and-proc.rs
deleted file mode 100644 (file)
index 413717d..0000000
+++ /dev/null
@@ -1,37 +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(unboxed_closures)]
-
-fn id<T>(x: T) -> T {
-    x
-}
-
-#[derive(PartialEq, Show)]
-struct Foo<T>(T);
-
-#[derive(PartialEq, Show)]
-enum Bar<T> {
-    Baz(T)
-}
-
-pub fn main() {
-    let f: |int| -> int = id;
-    assert_eq!(f(5), 5);
-
-    let f: |int| -> Foo<int> = Foo;
-    assert_eq!(f(5), Foo(5));
-
-    let f: |int| -> Bar<int> = Bar::Baz;
-    assert_eq!(f(5), Bar::Baz(5));
-
-    let f: |int| -> Option<int> = Some;
-    assert_eq!(f(5), Some(5));
-}
index 57e37aaf393bcea755d371a2e16a0460e7d4388c..8394c53cba5cb44c19da054f3a99ce9dc51075d2 100644 (file)
@@ -12,9 +12,9 @@ fn foo() -> int {
     return 0xca7f000d;
 }
 
-struct Bar<'a> { f: ||: 'a -> int }
+struct Bar<F> where F: FnMut() -> int { f: F }
 
-static mut b : Bar<'static> = Bar { f: foo };
+static mut b : Bar<fn() -> int> = Bar { f: foo as fn() -> int};
 
 pub fn main() {
     unsafe { assert_eq!((b.f)(), 0xca7f000d); }
diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs
new file mode 100644 (file)
index 0000000..25c1464
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(macro_rules)]
+
+use std::collections::Bitv;
+use std::default::Default;
+use std::iter::FromIterator;
+use std::option::IntoIter as OptionIter;
+use std::rand::Rand;
+use std::rand::XorShiftRng as DummyRng;
+// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
+use std::vec::Vec;
+
+#[derive(PartialEq, Eq)]
+struct Newt<T>(T);
+
+fn id<T>(x: T) -> T { x }
+fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
+fn u8_as_i8(x: u8) -> i8 { x as i8 }
+fn odd(x: uint) -> bool { x % 2 == 1 }
+fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
+
+macro_rules! tests {
+    ($($expr:expr: $ty:ty /($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        static S: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+        assert!(eq(S($($test),*), $expr($($test),*)));
+        assert!(eq(C($($test),*), S($($test),*)));
+    })+})
+}
+
+tests! {
+    // Free function.
+    id: fn(int) -> int /(5);
+    id::<int>: fn(int) -> int /(5);
+
+    // Enum variant constructor.
+    Some: fn(int) -> Option<int> /(5);
+    Some::<int>: fn(int) -> Option<int> /(5);
+
+    // Tuple struct constructor.
+    Newt: fn(int) -> Newt<int> /(5);
+    Newt::<int>: fn(int) -> Newt<int> /(5);
+
+    // Inherent static methods.
+    Vec::new: fn() -> Vec<()> /();
+    Vec::<()>::new: fn() -> Vec<()> /();
+    Vec::with_capacity: fn(uint) -> Vec<()> /(5);
+    Vec::<()>::with_capacity: fn(uint) -> Vec<()> /(5);
+    Bitv::from_fn: fn(uint, fn(uint) -> bool) -> Bitv /(5, odd);
+    Bitv::from_fn::<fn(uint) -> bool>: fn(uint, fn(uint) -> bool) -> Bitv /(5, odd);
+
+    // Inherent non-static method.
+    Vec::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+        /(vec![b'f', b'o', b'o'], u8_as_i8);
+    Vec::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+        /(vec![b'f', b'o', b'o'], u8_as_i8);
+    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
+    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //     /(vec![b'f', b'o', b'o'], u8_as_i8);
+    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //     /(vec![b'f', b'o', b'o'], u8_as_i8);
+
+    // Trait static methods.
+    // FIXME qualified path expressions aka UFCS i.e. <T as Trait>::method.
+    Default::default: fn() -> int /();
+    Rand::rand: fn(&mut DummyRng) -> int /(&mut dummy_rng());
+    Rand::rand::<DummyRng>: fn(&mut DummyRng) -> int /(&mut dummy_rng());
+
+    // Trait non-static methods.
+    Clone::clone: fn(&int) -> int /(&5);
+    FromIterator::from_iter: fn(OptionIter<int>) -> Vec<int> /(Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<int>>: fn(OptionIter<int>) -> Vec<int>
+        /(Some(5).into_iter());
+}
index 5e028d3774fc50d4c7c06edd1bc204e8a5600ae2..1a84236793b4f8d6d3d9f623b717fb227be4d9d9 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::{str, string};
-use std::c_str::ToCStr;
 
 const A: [u8; 2] = ['h' as u8, 'i' as u8];
 const B: &'static [u8; 2] = &A;
@@ -23,8 +22,5 @@ pub fn main() {
         assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string());
         assert!(*C == A[0]);
         assert!(*(&B[0] as *const u8) == A[0]);
-
-        let bar = str::from_utf8_unchecked(&A).to_c_str();
-        assert_eq!(bar.as_str(), "hi".to_c_str().as_str());
     }
 }
index 86cac14b4439defecd05882b8069af8ab9e760f9..f21f7d1903cf3fd3a847ab38d2876ddaaf6be72f 100644 (file)
@@ -17,8 +17,8 @@
 
 fn f() { }
 static bare_fns: &'static [fn()] = &[f, f];
-struct S<'a>(||:'a);
-static mut closures: &'static mut [S<'static>] = &mut [S(f), S(f)];
+struct S<F: FnOnce()>(F);
+static mut closures: &'static mut [S<fn()>] = &mut [S(f as fn()), S(f as fn())];
 
 pub fn main() {
     unsafe {
index 58eb4ce2f7a559a4814c0247980937afed6a59cb..d9201746440854f124d23df14fe344a699f87527 100644 (file)
@@ -25,6 +25,6 @@ fn wrapper3(i: chan) {
 }
 
 pub fn main() {
-    let wrapped = {||wrapper3(chan::chan_t)};
+    let wrapped = {|&:|wrapper3(chan::chan_t)};
     wrapped();
 }
index 34ff0b3821cc6dfc85ce519e46c962ae5e03fb65..797c26556aaa1aa3de97fa7521ad350764e1d73f 100644 (file)
@@ -19,9 +19,6 @@
 trait Trait {}
 
 fn main() {
-    // Closures - ||
-    assert_eq!(size_of::<||>(), size_of::<Option<||>>());
-
     // Functions
     assert_eq!(size_of::<fn(int)>(), size_of::<Option<fn(int)>>());
     assert_eq!(size_of::<extern "C" fn(int)>(), size_of::<Option<extern "C" fn(int)>>());
index 3a6cd61fa099234b7233933a13ba8745f7818a8c..ed246e2cb7d7bd6008b8f2345bf2a0a00bf25239 100644 (file)
@@ -11,9 +11,8 @@
 
 
 fn test_fn() {
-    type t = ||: 'static -> int;
     fn ten() -> int { return 10; }
-    let rs: t = ten;
+    let rs = ten;
     assert!((rs() == 10));
 }
 
index ec5013122acae3c72400117a6c4cc1580d2c5210..5c1039fe4336883b64c59291f0f1a7923b741ad4 100644 (file)
@@ -8,12 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-type compare<'a, T> = |Box<T>, Box<T>|: 'a -> bool;
-
-fn test_generic<T:Clone>(expected: Box<T>, eq: compare<T>) {
+fn test_generic<T, F>(expected: Box<T>, eq: F) where T: Clone, F: FnOnce(Box<T>, Box<T>) -> bool {
     let actual: Box<T> = { expected.clone() };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_box() {
@@ -22,7 +19,7 @@ fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool {
         println!("{}", *b2);
         return *b1 == *b2;
     }
-    test_generic::<bool>(box true, compare_box);
+    test_generic::<bool, _>(box true, compare_box);
 }
 
 pub fn main() { test_box(); }
index 48e27dc449cba4d1e18c67cb306ef3e8524500e3..3d736cca6d524464085e48bea819edef5ba97ef4 100644 (file)
@@ -8,17 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-type compare<'a, T> = |T, T|: 'a -> bool;
-
-fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+fn test_generic<T, F>(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool {
     let actual: T = { expected.clone() };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_vec() {
     fn compare_vec(v1: Box<int>, v2: Box<int>) -> bool { return v1 == v2; }
-    test_generic::<Box<int>>(box 1, compare_vec);
+    test_generic::<Box<int>, _>(box 1, compare_vec);
 }
 
 pub fn main() { test_vec(); }
index f1363c42961e1d5d83045e1570273f36a8a9890d..91b847d47cbcc679d6b9efda3c59594a2a674524 100644 (file)
@@ -8,19 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-
-// Tests for standalone blocks as expressions with dynamic type sizes
-type compare<'a, T> = |T, T|: 'a -> bool;
-
-fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool {
     let actual: T = { expected.clone() };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_bool() {
     fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; }
-    test_generic::<bool>(true, compare_bool);
+    test_generic::<bool, _>(true, compare_bool);
 }
 
 #[derive(Clone)]
@@ -33,7 +28,7 @@ fn test_rec() {
     fn compare_rec(t1: Pair, t2: Pair) -> bool {
         t1.a == t2.a && t1.b == t2.b
     }
-    test_generic::<Pair>(Pair {a: 1, b: 2}, compare_rec);
+    test_generic::<Pair, _>(Pair {a: 1, b: 2}, compare_rec);
 }
 
 pub fn main() { test_bool(); test_rec(); }
index d9300d0bc335aec9767dd9f1fd0304d4c882ea84..fb2a120e6f4a17d839b2cccc2ca2736437deb667 100644 (file)
@@ -8,18 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-// Tests for if as expressions with dynamic type sizes
-type compare<T> = |T, T|: 'static -> bool;
-
-fn test_generic<T:Clone>(expected: T, not_expected: T, eq: compare<T>) {
+fn test_generic<T, F>(expected: T, not_expected: T, eq: F) where
+    T: Clone,
+    F: FnOnce(T, T) -> bool,
+{
     let actual: T = if true { expected.clone() } else { not_expected };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_bool() {
     fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; }
-    test_generic::<bool>(true, false, compare_bool);
+    test_generic::<bool, _>(true, false, compare_bool);
 }
 
 #[derive(Clone)]
@@ -32,7 +31,7 @@ fn test_rec() {
     fn compare_rec(t1: Pair, t2: Pair) -> bool {
         t1.a == t2.a && t1.b == t2.b
     }
-    test_generic::<Pair>(Pair{a: 1, b: 2}, Pair{a: 2, b: 3}, compare_rec);
+    test_generic::<Pair, _>(Pair{a: 1, b: 2}, Pair{a: 2, b: 3}, compare_rec);
 }
 
 pub fn main() { test_bool(); test_rec(); }
index aed4024b5bc5cb140490c32c2a60db94636bf871..5fc9a502ca8a0e54f0c488e0958bb1f375189659 100644 (file)
@@ -8,22 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-type compare<T> = |Box<T>, Box<T>|: 'static -> bool;
-
-fn test_generic<T:Clone>(expected: Box<T>, eq: compare<T>) {
+fn test_generic<T: Clone, F>(expected: Box<T>, eq: F) where F: FnOnce(Box<T>, Box<T>) -> bool {
     let actual: Box<T> = match true {
         true => { expected.clone() },
         _ => panic!("wat")
     };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_box() {
     fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool {
         return *b1 == *b2;
     }
-    test_generic::<bool>(box true, compare_box);
+    test_generic::<bool, _>(box true, compare_box);
 }
 
 pub fn main() { test_box(); }
index 89adef378f1a1dabc6aa48639bd80a7cf22c0967..e608f9c46c79c1fff1f2920f8c82a80e25e1e5fc 100644 (file)
@@ -8,20 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-type compare<'a, T> = |T, T|: 'a -> bool;
-
-fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool {
     let actual: T = match true {
         true => expected.clone(),
         _ => panic!("wat")
     };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_vec() {
     fn compare_box(v1: Box<int>, v2: Box<int>) -> bool { return v1 == v2; }
-    test_generic::<Box<int>>(box 1, compare_box);
+    test_generic::<Box<int>, _>(box 1, compare_box);
 }
 
 pub fn main() { test_vec(); }
index 1231a49dcd31be7f521683c87b9e8797fdcfa495..09508b9b136296423ce4e78f4bdbcf0173b79b0c 100644 (file)
@@ -10,7 +10,7 @@
 
 fn bare() {}
 
-fn likes_block(f: ||) { f() }
+fn likes_block<F>(f: F) where F: FnOnce() { f() }
 
 pub fn main() {
     likes_block(bare);
index 6b7490ba67368ce0b56f77e648b3c1690b9cb85c..bf6926050ba96b2f780a885a1b96de8dfb06e8ed 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct r<'a> {
-    field: ||: 'a,
+struct r<F> where F: FnOnce() {
+    field: F,
 }
 
 pub fn main() {
     fn f() {}
-    let _i: r = r {field: f};
+    let _i: r<fn()> = r {field: f as fn()};
 }
index fb75abc6ea0934bba220ecef8d2e6234bda73dc0..24bf1f94d887b49fe156fe0bbb8e0e85d2ab97c8 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-    let f: |(int,int)| = |(x, y)| {
+    let f = |&: (x, y): (int, int)| {
         assert_eq!(x, 1);
         assert_eq!(y, 2);
     };
index 80d3527736f40b9de881f4ce43bedf98eda37976..ae22ff5cce03526d28e5a499c1c7c2991b71b81d 100644 (file)
@@ -12,7 +12,7 @@
 
 pub fn main() {
     // We should be able to type infer inside of ||s.
-    let _f = || {
+    let _f = |&:| {
         let i = 10i;
     };
 }
index 2a54f22ee665b44f843e7deee0c12805c296c5e1..f6466994955e79e537a65dd8779a46f2e079781b 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn two(it: |int|) { it(0); it(1); }
+fn two<F>(mut it: F) where F: FnMut(int) { it(0); it(1); }
 
 pub fn main() {
     let mut a: Vec<int> = vec!(-1, -1, -1, -1);
index 7a728e18a290143a34181084f5612ca14bdfad08..029dddb7a21109734d92a3f14d05dc7f6cb0da24 100644 (file)
@@ -10,7 +10,7 @@
 
 
 
-fn pairs(it: |(int, int)|) {
+fn pairs<F>(mut it: F) where F: FnMut((int, int)) {
     let mut i: int = 0;
     let mut j: int = 0;
     while i < 10 { it((i, j)); i += 1; j += i; }
index bb726773bb5dbe64936e9e6cef6bd48b71d2c145..9ccb2dd56cfdcd20ecc7b2df910c038d60e956c7 100644 (file)
@@ -19,7 +19,7 @@ pub fn main() {
     assert_eq!(sum, 45);
 }
 
-fn first_ten(it: |int|) {
+fn first_ten<F>(mut it: F) where F: FnMut(int) {
     let mut i: int = 0;
     while i < 10 { println!("first_ten"); it(i); i = i + 1; }
 }
index 8a75fdd685dd1055fb2515d5372182a30cb50cee..dff1a1eaa0473aaf7b3a3225051da1d5072ad8ff 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-fast doesn't like extern crate
 
 extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
 
 mod mlibc {
     use libc::{c_char, size_t};
@@ -24,11 +24,10 @@ mod mlibc {
 
 fn strlen(str: String) -> uint {
     // C string is terminated with a zero
-    str.as_slice().with_c_str(|buf| {
-        unsafe {
-            mlibc::my_strlen(buf) as uint
-        }
-    })
+    let s = CString::from_slice(str.as_bytes());
+    unsafe {
+        mlibc::my_strlen(s.as_ptr()) as uint
+    }
 }
 
 pub fn main() {
index 479f4f8387fb46a00dd780d6671d453d5a852ecf..3955bedb168aeb373fad6b1ce6fae029b18a0e37 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn ho(f: |int| -> int) -> int { let n: int = f(3); return n; }
+fn ho<F>(f: F) -> int where F: FnOnce(int) -> int { let n: int = f(3); return n; }
 
 fn direct(x: int) -> int { return x + 1; }
 
index 032db16c61714def782e849db6a2af2dce2085a3..f992847e4e9f6b093b92614cd17022f96ebf825c 100644 (file)
 
 
 trait vec_utils<T> {
-    fn map_<U>(x: &Self, f: |&T| -> U) -> Vec<U> ;
+    fn map_<U, F>(x: &Self, f: F) -> Vec<U> where F: FnMut(&T) -> U;
 }
 
 impl<T> vec_utils<T> for Vec<T> {
-    fn map_<U>(x: &Vec<T> , f: |&T| -> U) -> Vec<U> {
+    fn map_<U, F>(x: &Vec<T> , mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
         let mut r = Vec::new();
         for elt in x.iter() {
             r.push(f(elt));
index 7fd8ca1fd8a9e3ac975ccbbe4d241d89da153fcf..3bcce5388715d6e34df5117549980565e4d765ef 100644 (file)
@@ -9,13 +9,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 /**
    A somewhat reduced test case to expose some Valgrind issues.
 
    This originally came from the word-count benchmark.
 */
 
-pub fn map(filename: String, emit: map_reduce::putter) {
+pub fn map(filename: String, mut emit: map_reduce::putter) {
     emit(filename, "1".to_string());
 }
 
@@ -25,7 +27,7 @@ mod map_reduce {
     use std::str;
     use std::thread::Thread;
 
-    pub type putter<'a> = |String, String|: 'a;
+    pub type putter<'a> = Box<FnMut(String, String) + 'a>;
 
     pub type mapper = extern fn(String, putter);
 
@@ -58,7 +60,7 @@ fn emit(im: &mut HashMap<String, int>,
         }
 
         let ctrl_clone = ctrl.clone();
-        ::map(input, |a,b| emit(&mut intermediates, ctrl.clone(), a, b) );
+        ::map(input, box |a,b| emit(&mut intermediates, ctrl.clone(), a, b) );
         ctrl_clone.send(ctrl_proto::mapper_done).unwrap();
     }
 
index 5bdfa3cafd747973cb915cdb8c108d79d93ae2d0..9e857a33245d16be5b060469a0d0a548e8a3ddc0 100644 (file)
@@ -13,8 +13,7 @@ fn method(&self, data: &'tcx int) -> &'tcx int { data }
     fn dummy(&self) { }
 }
 
-fn g(_: |&Typer|) {
-}
+fn g<F>(_: F) where F: FnOnce(&Typer) {}
 
 fn h() {
     g(|typer| typer.dummy())
index 53749f09f741e86207186f9d84b20e9ee03f541a..41b7c0fae0746d165e80c29e4e759ba1c23d979a 100644 (file)
@@ -40,8 +40,5 @@ fn foo21(t: for<'a> unsafe fn(int) -> int) { }
 fn foo22(t: for<'a> extern "C" fn(int) -> int) { }
 fn foo23(t: for<'a> unsafe extern "C" fn(int) -> int) { }
 
-fn foo30(t: for<'a> |int| -> int) { }
-fn foo31(t: for<'a> unsafe |int| -> int) { }
-
 fn main() {
 }
index 076b9c7684ec4010b0de0cad705edece265b19f7..c90c3643d4e54f8dd5d301ad635b662260f903c0 100644 (file)
@@ -23,7 +23,7 @@ struct NoAnn<'ast> {
 impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
 }
 
-fn foo<'ast> (f: Option<&'ast uint>, g: |&PrinterSupport|) {
+fn foo<'ast, G>(f: Option<&'ast uint>, g: G) where G: FnOnce(&PrinterSupport) {
     let annotation = NoAnn { f: f };
     g(&annotation)
 }
index 24deb7c2e4b408ec23629cf0e1d22aa6d6fa6e61..d0d8a8589a4e2b861232dc0dd777b8683b75f218 100644 (file)
@@ -40,16 +40,10 @@ enum WireProtocol {
     // ...
 }
 
-fn encode_json<
-               T: for<'a> Encodable<json::Encoder<'a>,
-                            fmt::Error>>(val: &T,
-                                               wr: &mut SeekableMemWriter) {
+fn encode_json<T: Encodable>(val: &T, wr: &mut SeekableMemWriter) {
     write!(wr, "{}", json::as_json(val));
 }
-fn encode_rbml<'a,
-               T: Encodable<writer::Encoder<'a, SeekableMemWriter>,
-                            io::IoError>>(val: &T,
-                                               wr: &'a mut SeekableMemWriter) {
+fn encode_rbml<T: Encodable>(val: &T, wr: &mut SeekableMemWriter) {
     let mut encoder = writer::Encoder::new(wr);
     val.encode(&mut encoder);
 }
index e223feede02e6cb10fbe680c84a1a83741f57ced..e5fd17e2dfed0017791c9b0c81276c79fbd2c4c1 100644 (file)
@@ -15,7 +15,7 @@ trait Repro {
   fn repro(self, s: MyStruct) -> String;
 }
 
-impl Repro for |MyStruct|:'static -> String {
+impl<F> Repro for F where F: FnOnce(MyStruct) -> String {
   fn repro(self, s: MyStruct) -> String {
     self(s)
   }
@@ -26,5 +26,5 @@ fn do_stuff<R: Repro>(r: R) -> String {
 }
 
 pub fn main() {
-  assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{}", s)));
+  assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{}", s)));
 }
index 626381c334dd73f168911bdb78ef534baf1a24a4..4d150e7a68e7cf5dc21dd1f31a1f4ef947a771b1 100644 (file)
@@ -24,7 +24,6 @@ pub fn type_ids() -> Vec<TypeId> {
     ids.push(TypeId::of::<testtypes::FooEnum>());
     ids.push(TypeId::of::<testtypes::FooUniq>());
     ids.push(TypeId::of::<testtypes::FooPtr>());
-    ids.push(TypeId::of::<testtypes::FooClosure>());
     ids.push(TypeId::of::<&'static testtypes::FooTrait>());
     ids.push(TypeId::of::<testtypes::FooStruct>());
     ids.push(TypeId::of::<testtypes::FooTuple>());
index e20090adcf6134ac18c1cd065cde2a8ebfbf5a53..c0652b946dbe580b5a1711738b46dc39c23aa187 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 struct Foo<'a> {
-    listener: ||: 'a
+    listener: Box<FnMut() + 'a>,
 }
 
 impl<'a> Foo<'a> {
-    fn new(listener: ||: 'a) -> Foo<'a> {
-        Foo { listener: listener }
+    fn new<F>(listener: F) -> Foo<'a> where F: FnMut() + 'a {
+        Foo { listener: box listener }
     }
 }
 
index 8176262abd918fc8ed47143923f7223b16588d6e..2091a5437c2dcbcedb31a10c25428b8deb553773 100644 (file)
@@ -10,5 +10,5 @@
 
 
 pub fn main() {
-    {|i| if 1i == i { }};
+    {|&: i| if 1i == i { }};
 }
index d66bbe9187a289a126bd3165d49af7c24d5ff508..d5590e99f2cb994ac6f9f8c814062dc630d4d55b 100644 (file)
@@ -16,7 +16,7 @@ trait Matcher {
 
 struct CharPredMatcher<'a, 'b> {
     str: &'a str,
-    pred: |char|:'b -> bool
+    pred: Box<FnMut(char) -> bool + 'b>,
 }
 
 impl<'a, 'b> Matcher for CharPredMatcher<'a, 'b> {
@@ -29,11 +29,11 @@ trait IntoMatcher<'a, T> {
     fn into_matcher(self, &'a str) -> T;
 }
 
-impl<'a, 'b> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for |char|:'b -> bool {
+impl<'a, 'b, F> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for F where F: FnMut(char) -> bool + 'b {
     fn into_matcher(self, s: &'a str) -> CharPredMatcher<'a, 'b> {
         CharPredMatcher {
             str: s,
-            pred: self
+            pred: box self,
         }
     }
 }
@@ -57,6 +57,6 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi
 
 fn main() {
     let s = "abcbdef";
-    match_indices(s, |c: char| c == 'b')
+    match_indices(s, |&mut: c: char| c == 'b')
         .collect::<Vec<(uint, uint)>>();
 }
diff --git a/src/test/run-pass/issue-1516.rs b/src/test/run-pass/issue-1516.rs
deleted file mode 100644 (file)
index 3c5af9c..0000000
+++ /dev/null
@@ -1,13 +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.
-
-pub fn main() {
-    let early_error: |&str|: 'static -> ! = |_msg| { panic!() };
-}
index 1ab8deda3830e035c91436617afe1d55d30bd1f0..db9f1cc9df7c9138c4b577c0bf083ef6c31d5204 100644 (file)
@@ -21,7 +21,7 @@ struct Foo<T> {
 }
 
 #[unsafe_destructor]
-impl<T: for<'a> Encodable<json::Encoder<'a>, fmt::Error>> Drop for Foo<T> {
+impl<T: Encodable> Drop for Foo<T> {
     fn drop(&mut self) {
         json::encode(&self.v);
     }
index 48ea3a93296e3194420f2e9c79c05e23c907cade..e7422e233a62903385b1a0b8823eb7c6de44b47d 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     let mut buf = Vec::new();
-    |c: u8| buf.push(c);
+    |&mut: c: u8| buf.push(c);
 }
index f36594cb401450b683707ae717c752eafefe1499..1febf33742974ba2e49616219c3367b2504648ff 100644 (file)
@@ -20,8 +20,8 @@ impl<'a, I, O: 'a> Parser<'a, I, O> {
     fn compose<K: 'a>(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> {
         Parser {
             parse: box move |&mut: x: I| {
-                match (*self.parse).call_mut((x,)) {
-                    Ok(r) => (*rhs.parse).call_mut((r,)),
+                match (self.parse)(x) {
+                    Ok(r) => (rhs.parse)(r),
                     Err(e) => Err(e)
                 }
             }
diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs
new file mode 100644 (file)
index 0000000..3ce347d
--- /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<T> where T: Copy;
+struct Bar<T>(T) where T: Copy;
+struct Bleh<T, U>(T, U) where T: Copy, U: Sized;
+struct Baz<T> where T: Copy {
+    field: T
+}
+
+fn main() {}
index ebcaf97c5f7e74782ad585be22e1eaf99150ba39..120ada96c15b731c932c0f5e74f680ddb94556c2 100644 (file)
 #![allow(non_camel_case_types)]
 
 pub fn main() {
-    let one: || -> uint = || {
+    let one = |&:| {
         enum r { a };
         r::a as uint
     };
-    let two: || -> uint = || {
+    let two = |&:| {
         enum r { a };
         r::a as uint
     };
index d8c12d8511c32d65ec20a56eda6ac2815709463e..aa61d52b2a32d4b1648d3eca2c897ffaac72962a 100644 (file)
@@ -29,7 +29,7 @@ fn socket() -> socket {
     }
 }
 
-fn closure(f: ||) { f() }
+fn closure<F>(f: F) where F: FnOnce() { f() }
 
 fn setsockopt_bytes(_sock: int) { }
 
index 00e6b5ca8fedc3d19131c8e57c9857046b4809ba..72cf2219bb6f090963d453bcf8771f80a1750e4c 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 
-type Connection = |Vec<u8>|: 'static;
+type Connection = Box<FnMut(Vec<u8>) + 'static>;
 
 fn f() -> Option<Connection> {
-    let mock_connection: Connection = |_| {};
+    let mock_connection: Connection = box |&mut: _| {};
     Some(mock_connection)
 }
 
index 651315ea6417347bbd1868d0104f64535b3409ab..528870d033476e70fcc0c1abb95af0489b0aaabc 100644 (file)
@@ -27,7 +27,7 @@ fn tester()
     };
 
     let path = path::Path::new("blah");
-    assert!(loader.call_mut((&path,)).is_ok());
+    assert!(loader(&path).is_ok());
 }
 
 pub fn main() {}
index cce90f8a2cd29339edf892cfdfce9f55f0b3618a..60c53450004363917843728b96dda31d397ed800 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-  let x = 1;
-  let y: || -> int = || x;
+  let x = 1u;
+  let y = |&:| x;
   let _z = y();
 }
index c616c09c70e6074a8d1a252120d78cfe05f80250..9226bebd2dcea424a93b4d919480c729d39bad59 100644 (file)
@@ -10,7 +10,7 @@
 
 enum PureCounter { PureCounterVariant(uint) }
 
-fn each(thing: PureCounter, blk: |v: &uint|) {
+fn each<F>(thing: PureCounter, blk: F) where F: FnOnce(&uint) {
     let PureCounter::PureCounterVariant(ref x) = thing;
     blk(x);
 }
index 81a7d073c4cda18237a930e61db10d365538e64d..e917ecc745f0ba3f6d47ccdf8588e62bc50fe2c3 100644 (file)
@@ -8,21 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-type ErrPrinter<'a> = |&str, &str|: 'a;
-
 fn example_err(prog: &str, arg: &str) {
     println!("{}: {}", prog, arg)
 }
 
-fn exit(print: ErrPrinter, prog: &str, arg: &str) {
+fn exit<F>(print: F, prog: &str, arg: &str) where F: FnOnce(&str, &str) {
     print(prog, arg);
 }
 
-struct X<'a> {
-    err: ErrPrinter<'a>
+struct X<F> where F: FnOnce(&str, &str) {
+    err: F,
 }
 
-impl<'a> X<'a> {
+impl<F> X<F> where F: FnOnce(&str, &str) {
     pub fn boom(self) {
         exit(self.err, "prog", "arg");
     }
index e5cc8414f064b631ff04e8ad192022209efc8e04..220332f63548af28921350fec8d9cd2fe38f1c55 100644 (file)
@@ -13,7 +13,7 @@
 
 use serialize::{json, Decodable};
 
-trait JD : Decodable<json::Decoder, json::DecoderError> { }
+trait JD : Decodable {}
 
 fn exec<T: JD>() {
     let doc = json::from_str("").unwrap();
index 863acc5c0c3c0c1d30067885c5347c55dbe449a0..69255c576811fd075b8c5b039e276f92a75e950f 100644 (file)
@@ -11,7 +11,7 @@
 // Regression test for issue #5239
 
 pub fn main() {
-    let _f: |int| -> int = |ref x: int| { *x };
+    let _f = |&: ref x: int| { *x };
     let foo = 10;
     assert!(_f(foo) == 10);
 }
index fa784e17b10f22806d43c514a01a4af18eeb7291..b2b64e62c39a4d645043b54ceb800ac56d185ffc 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn swap(f: |Vec<int> | -> Vec<int> ) -> Vec<int> {
+fn swap<F>(f: F) -> Vec<int> where F: FnOnce(Vec<int>) -> Vec<int> {
     let x = vec!(1, 2, 3);
     f(x)
 }
index 23e700855040c4a4f680ce7811824f11ad67a775..07c7c6888e1ebdb4780246c8c35c016d86179722 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub trait OpInt<'a> { fn call(&mut self, int, int) -> int; }
+pub trait OpInt { fn call(&mut self, int, int) -> int; }
 
-impl<'a> OpInt<'a> for |int, int|: 'a -> int {
+impl<F> OpInt for F where F: FnMut(int, int) -> int {
     fn call(&mut self, a:int, b:int) -> int {
         (*self)(a, b)
     }
@@ -21,7 +21,7 @@ fn squarei<'a>(x: int, op: &'a mut OpInt) -> int { op.call(x, x) }
 fn muli(x:int, y:int) -> int { x * y }
 
 pub fn main() {
-    let mut f = |x,y| muli(x,y);
+    let mut f = |&mut: x, y| muli(x, y);
     {
         let g = &mut f;
         let h = g as &mut OpInt;
index 99ab83ec62073123afe4ef28cd0cc8e82dfa4674..72bdd1af746c17c1bf03f40fd5f9d3e612a36b68 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f<T>(g: || -> T) -> T { g() }
+fn f<T, F>(g: F) -> T where F: FnOnce() -> T { g() }
 
 pub fn main() {
   let _x = f( | | { 10i });
@@ -20,5 +20,5 @@ pub fn main() {
     let _: () = f(| | { });
     // empty block with no type info should compile too
     let _ = f(||{});
-    let _ = (||{});
+    let _ = (|&:|{});
 }
index a6746f452065d9fd93944c1a7afdaca410b19a57..3ca060f45a5f50f031d9bedfa194b4644c2909e1 100644 (file)
@@ -29,7 +29,7 @@ fn Ident_new() -> Ident {
 
 pub fn light_fuse(fld: Box<bomb>) {
     int3!();
-    let f = || {
+    let f = |&:| {
         int3!();
         fld.boom(Ident_new()); // *** 1
     };
index 794c4f4016e62729770e8674a292c4fe5c20499c..29ac563878bc4ce7aec13a54c703a3681afb181c 100644 (file)
@@ -10,7 +10,7 @@
 
 
 
-fn range_(a: int, b: int, it: |int|) {
+fn range_<F>(a: int, b: int, mut it: F) where F: FnMut(int) {
     assert!((a < b));
     let mut i: int = a;
     while i < b { it(i); i += 1; }
index 190d25015840ce2090e97e9930c2c39a6a0a02d1..b33e6512b18bdafab6c280bc5755150237ab6ec9 100644 (file)
@@ -16,7 +16,7 @@ struct Refs { refs: Vec<int> , n: int }
 
 pub fn main() {
     let mut e = Refs{refs: vec!(), n: 0};
-    let _f: || = || println!("{}", e.n);
+    let _f = |&:| println!("{}", e.n);
     let x: &[int] = e.refs.as_slice();
     assert_eq!(x.len(), 0);
 }
index c0dcf9e609418a4839dca2cc60e60769774a058f..8ef5df5d6969729f2365ee0f8f99ad8bfb61c107 100644 (file)
@@ -10,7 +10,7 @@
 
 // Issue #1818
 
-fn lp<T>(s: String, f: |String| -> T) -> T {
+fn lp<T, F>(s: String, mut f: F) -> T where F: FnMut(String) -> T {
     while false {
         let r = f(s);
         return (r);
@@ -18,8 +18,8 @@ fn lp<T>(s: String, f: |String| -> T) -> T {
     panic!();
 }
 
-fn apply<T>(s: String, f: |String| -> T) -> T {
-    fn g<T>(s: String, f: |String| -> T) -> T {f(s)}
+fn apply<T, F>(s: String, mut f: F) -> T where F: FnMut(String) -> T {
+    fn g<T, F>(s: String, mut f: F) -> T where F: FnMut(String) -> T {f(s)}
     g(s, |v| { let r = f(v); r })
 }
 
index c9ea520576a756335a397ca89a7a5e893052b2b7..6615bb6368fd75df46b1fd3a7911ee8c2aeee153 100644 (file)
 
 // Make sure #1399 stays fixed
 
+#![feature(unboxed_closures)]
 
 struct A { a: Box<int> }
 
-fn foo() -> ||: 'static -> int {
+fn foo() -> Box<FnMut() -> int + 'static> {
     let k = box 22i;
     let _u = A {a: k.clone()};
-    let result: ||: 'static -> int = || 22;
-    result
+    let result  = |&mut:| 22;
+    box result
 }
 
 pub fn main() {
-    assert_eq!(foo()(), 22);
+    assert_eq!(foo().call_mut(()), 22);
 }
index 6d5624e2b588004a379797216a33e1a92dbc18fc..206d4db3db4f841eaf10ce617caa13aec6f9d623 100644 (file)
@@ -13,7 +13,7 @@
 struct A { a: Box<int> }
 
 pub fn main() {
-    fn invoke(f: ||) { f(); }
+    fn invoke<F>(f: F) where F: FnOnce() { f(); }
     let k = box 22i;
     let _u = A {a: k.clone()};
     invoke(|| println!("{}", k.clone()) )
index c5f39bc1a538331820819f0e3c822c935a43b90d..2a0a2b208875fa97005f21eea6f733bdae28846c 100644 (file)
@@ -13,7 +13,7 @@
 
 enum thing { a, b, c, }
 
-fn foo(it: |int|) { it(10); }
+fn foo<F>(it: F) where F: FnOnce(int) { it(10); }
 
 pub fn main() {
     let mut x = true;
index 4f9e573ccff26979a602e83b8e3a1c3131a5ca2f..acd8078b1f4d3a183fbf8f387e94dd8ed47d64c3 100644 (file)
 
 
 trait vec_monad<A> {
-    fn bind<B>(&self, f: |&A| -> Vec<B> ) -> Vec<B> ;
+    fn bind<B, F>(&self, f: F ) -> Vec<B> where F: FnMut(&A) -> Vec<B> ;
 }
 
 impl<A> vec_monad<A> for Vec<A> {
-    fn bind<B>(&self, f: |&A| -> Vec<B> ) -> Vec<B> {
+    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.iter() {
             r.extend(f(elt).into_iter());
@@ -25,11 +25,11 @@ fn bind<B>(&self, f: |&A| -> Vec<B> ) -> Vec<B> {
 }
 
 trait option_monad<A> {
-    fn bind<B>(&self, f: |&A| -> Option<B>) -> Option<B>;
+    fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B>;
 }
 
 impl<A> option_monad<A> for Option<A> {
-    fn bind<B>(&self, f: |&A| -> Option<B>) -> Option<B> {
+    fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B> {
         match *self {
             Some(ref a) => { f(a) }
             None => { None }
index 4b613e9beaab2605b237bc2463828a655cab11ec..b7cd3003e750c4204394ce865daf9209bd80654f 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 // Issue #922
-fn f2(_thing: ||) { }
+fn f2<F>(_thing: F) where F: FnOnce() { }
 
-fn f(thing: ||) {
+fn f<F>(thing: F) where F: FnOnce() {
     f2(thing);
 }
 
index 39441227f6074ee5b436234127edb0a76d8c5213..f80728519136ed684a244aeca3b713066b5d032d 100644 (file)
@@ -15,7 +15,7 @@ fn f(mut y: Box<int>) {
 }
 
 fn g() {
-    let frob: |Box<int>| = |mut q| { *q = 2; assert!(*q == 2); };
+    let frob = |&: mut q: Box<int>| { *q = 2; assert!(*q == 2); };
     let w = box 37;
     frob(w);
 
index 139122b7b81256406256a3edb638622f85a12bcc..ad9161f9bd48736fa5911391859c739d80855000 100644 (file)
@@ -75,6 +75,6 @@ struct A {
     x = 30;
     assert_eq!(x, 30);
 
-    (|A { x: mut t }: A| { t = t+1; t })(A { x: 34 });
+    (|&: A { x: mut t }: A| { t = t+1; t })(A { x: 34 });
 
 }
index 043136fdad9956a3028a890b8672a1dd048ef60b..01875288aef0e97cdbc73e40769567af7a6f2826 100644 (file)
@@ -10,9 +10,9 @@
 
 // Tests for the new |args| expr lambda syntax
 
-fn f(i: int, f: |int| -> int) -> int { f(i) }
+fn f<F>(i: int, f: F) -> int where F: FnOnce(int) -> int { f(i) }
 
-fn g(_g: ||) { }
+fn g<G>(_g: G) where G: FnOnce() { }
 
 pub fn main() {
     assert_eq!(f(10, |a| a), 10);
index 8262432db607f3b04fd0127535fa0940a6776004..e422cb803215bb591be773f40c4413a555290a0b 100644 (file)
@@ -12,7 +12,7 @@ struct X {
     repr: int
 }
 
-fn apply<T>(x: T, f: |T|) {
+fn apply<T, F>(x: T, f: F) where F: FnOnce(T) {
     f(x);
 }
 
index f8bc0929bfa807fc0481a5b4ffd61d2714ee687c..4964b3f67284428ee4bdcfa7f3d35eaa2c9bdd1f 100644 (file)
@@ -12,7 +12,6 @@
 // traits.
 
 use std::any::Any;
-use std::any::AnyRefExt;
 
 trait Wrap {
     fn get(&self) -> int;
diff --git a/src/test/run-pass/overloaded-calls-object-one-arg.rs b/src/test/run-pass/overloaded-calls-object-one-arg.rs
new file mode 100644 (file)
index 0000000..25b63cd
--- /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.
+
+// Tests calls to closure arguments where the closure takes 1 argument.
+// This is a bit tricky due to rust-call ABI.
+
+fn foo(f: &mut FnMut(int) -> int) -> int {
+    f(22)
+}
+
+fn main() {
+    let z = foo(&mut |x| x *100);
+    assert_eq!(z, 2200);
+}
diff --git a/src/test/run-pass/overloaded-calls-object-two-args.rs b/src/test/run-pass/overloaded-calls-object-two-args.rs
new file mode 100644 (file)
index 0000000..026ebc3
--- /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.
+
+// Tests calls to closure arguments where the closure takes 2 arguments.
+// This is a bit tricky due to rust-call ABI.
+
+fn foo(f: &mut FnMut(int, int) -> int) -> int {
+    f(1, 2)
+}
+
+fn main() {
+    let z = foo(&mut |x, y| x * 10 + y);
+    assert_eq!(z, 12);
+}
diff --git a/src/test/run-pass/overloaded-calls-object-zero-args.rs b/src/test/run-pass/overloaded-calls-object-zero-args.rs
new file mode 100644 (file)
index 0000000..b38f821
--- /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.
+
+// Tests calls to closure arguments where the closure takes 0 arguments.
+// This is a bit tricky due to rust-call ABI.
+
+fn foo(f: &mut FnMut() -> int) -> int {
+    f()
+}
+
+fn main() {
+    let z = foo(&mut || 22);
+    assert_eq!(z, 22);
+}
index b0a40f74ff973dff2466d35148406636cb71ec63..bb5b88d3674a1b8d1d42be64c75ebfd5db397bc4 100644 (file)
@@ -50,7 +50,7 @@ fn main() {
         x: 3,
         y: 3,
     };
-    let ans = s.call_mut((3,));
+    let ans = s(3);
 
     assert_eq!(ans, 27);
     let s = S2 {
@@ -64,7 +64,7 @@ fn main() {
         x: 3,
         y: 3,
     };
-    let ans = s.call_once((3, 1));
+    let ans = s(3, 1);
     assert_eq!(ans, 27);
 }
 
diff --git a/src/test/run-pass/parse-complex-macro-invoc-op.rs b/src/test/run-pass/parse-complex-macro-invoc-op.rs
new file mode 100644 (file)
index 0000000..e9ec624
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test parsing binary operators after macro invocations.
+
+#![feature(macro_rules)]
+
+macro_rules! id {
+    ($e: expr) => { $e }
+}
+
+fn foo() {
+    id!(1i) + 1;
+    id![1i] - 1;
+    id!(1i) * 1;
+    id![1i] / 1;
+    id!(1i) % 1;
+
+    id!(1i) & 1;
+    id![1i] | 1;
+    id!(1i) ^ 1;
+
+    let mut x = 1i;
+    id![x] = 2;
+    id!(x) += 1;
+
+    id!(1f64).clone();
+
+    id!([1i, 2, 3])[1];
+    id![drop](1i);
+
+    id!(true) && true;
+    id![true] || true;
+}
+
+fn main() {}
index e4f1df2d6376df916c553f21a2e8ec7abbaf7d17..c718b948f8dc07723f4dfe49a69f351af11775dd 100644 (file)
@@ -14,8 +14,8 @@ struct Foo {
 }
 
 pub fn main() {
-    let f = |(x, _): (int, int)| println!("{}", x + 1);
-    let g = |Foo { x: x, y: _y }: Foo| println!("{}", x + 1);
+    let f = |&: (x, _): (int, int)| println!("{}", x + 1);
+    let g = |&: Foo { x: x, y: _y }: Foo| println!("{}", x + 1);
     f((2, 3));
     g(Foo { x: 1, y: 2 });
 }
index 3bceefb831851ce1a0535cbc35470e0792772a33..c5588a29cb526cccdd622b01f6f8d5e1d8ac4c1e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn something(f: ||) { f(); }
+fn something<F>(f: F) where F: FnOnce() { f(); }
 pub fn main() {
     something(|| println!("hi!") );
 }
index b4523ce41ce751af93ba7c58690fa58ea2727666..a7724e68310a7603e9c0b93a7c41e5b52deddf46 100644 (file)
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 struct closure_box<'a> {
-    cl: ||: 'a,
+    cl: Box<FnMut() + 'a>,
 }
 
-fn box_it(x: ||) -> closure_box {
+fn box_it<'a>(x: Box<FnMut() + 'a>) -> closure_box<'a> {
     closure_box {cl: x}
 }
 
@@ -20,9 +22,9 @@ pub fn main() {
     let mut i = 3i;
     assert_eq!(i, 3);
     {
-        let cl = || i += 1;
-        let cl_box = box_it(cl);
-        (cl_box.cl)();
+        let cl = |&mut:| i += 1;
+        let mut cl_box = box_it(box cl);
+        cl_box.cl.call_mut(());
     }
     assert_eq!(i, 4);
 }
index 311fd1bcdf2e06cb72392b50a06ab7fe61db7bad..e7dc5e99c2bb97e05b6d981ff62e64f2a0560df9 100644 (file)
@@ -11,9 +11,9 @@
 // Test lifetimes are linked properly when we autoslice a vector.
 // Issue #3148.
 
-fn subslice(v: ||) -> || { v }
+fn subslice<F>(v: F) -> F where F: FnOnce() { v }
 
-fn both(v: ||) -> || {
+fn both<F>(v: F) -> F where F: FnOnce() {
     subslice(subslice(v))
 }
 
index 9d2a959eae1c7fa807a8697eda8c1db0c857994b..70c90ee05b35764713de34b22b72f89c8e1886aa 100644 (file)
 // Here, `f` is a function that takes a pointer `x` and a function
 // `g`, where `g` requires its argument `y` to be in the same region
 // that `x` is in.
-fn has_same_region(f: <'a>|x: &'a int, g: |y: &'a int||) {
+fn has_same_region(f: Box<for<'a> FnMut(&'a int, Box<FnMut(&'a int)>)>) {
     // `f` should be the type that `wants_same_region` wants, but
     // right now the compiler complains that it isn't.
     wants_same_region(f);
 }
 
-fn wants_same_region(_f: <'b>|x: &'b int, g: |y: &'b int||) {
+fn wants_same_region(_f: Box<for<'b> FnMut(&'b int, Box<FnMut(&'b int)>)>) {
 }
 
 pub fn main() {
index 705a0e128522c941453f0794315a58dfb55e0098..e9f774150dcfd915c76b9e6a25e0a126668107ec 100644 (file)
 #![allow(unused_variable)]
 
 // Should pass region checking.
-fn ok(f: |x: &uint|) {
+fn ok(f: Box<FnMut(&uint)>) {
     // Here, g is a function that can accept a uint pointer with
     // lifetime r, and f is a function that can accept a uint pointer
     // with any lifetime.  The assignment g = f should be OK (i.e.,
     // f's type should be a subtype of g's type), because f can be
     // used in any context that expects g's type.  But this currently
     // fails.
-    let mut g: <'r>|y: &'r uint| = |x| { };
+    let mut g: Box<for<'r> FnMut(&'r uint)> = box |x| { };
     g = f;
 }
 
 // This version is the same as above, except that here, g's type is
 // inferred.
-fn ok_inferred(f: |x: &uint|) {
-    let mut g: <'r>|x: &'r uint| = |_| {};
+fn ok_inferred(f: Box<FnMut(&uint)>) {
+    let mut g: Box<for<'r> FnMut(&'r uint)> = box |_| {};
     g = f;
 }
 
index 3350c3b65d09071f8bdc631f3ab140cb29ff80e6..cfb6c8585634d7049a4ded78a2992c78e7936bfb 100644 (file)
@@ -10,7 +10,7 @@
 
 fn takes_two(x: &int, y: &int) -> int { *x + *y }
 
-fn with<T>(f: |x: &int| -> T) -> T {
+fn with<T, F>(f: F) -> T where F: FnOnce(&int) -> T {
     f(&20)
 }
 
index 77ecb077fef169ce8c3d457a007fe89881c773d0..c796566b79d57b2af0bef2106cd2d6dd56ca5de5 100644 (file)
 
 pub fn main() {
     fn explicit() {
-        fn test(_x: Option<|f: <'a> |g: &'a int||>) {}
-        test(Some(|_f: <'a> |g: &'a int|| {}));
+        fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<for<'a> FnMut(&'a int)>) {}
+        test(Some(box |&mut: _f: Box<for<'a> FnMut(&'a int)>| {}));
     }
 
     // The code below is shorthand for the code above (and more likely
     // to represent what one encounters in practice).
     fn implicit() {
-        fn test(_x: Option<|f:      |g: &   int||>) {}
-        test(Some(|_f:      |g: &   int|| {}));
+        fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<        FnMut(&   int)>) {}
+        test(Some(box |&mut: _f: Box<        FnMut(&   int)>| {}));
     }
 
     explicit();
index 2823622bdf6d9bd76cfeddc95e9ecad188c25b03..8822d3880397a8f57ef12370bc4fba3f4d7ba53b 100644 (file)
@@ -13,7 +13,7 @@
 
 #![allow(dead_code)]
 
-fn with<'a>(_: |&'a Vec<int>| -> &'a Vec<int>) { }
+fn with<'a, F>(_: F) where F: FnOnce(&'a Vec<int>) -> &'a Vec<int> { }
 
 fn foo() {
     with(|&ref ints| ints);
index c0e821b8d3854424fe960f2f7eba8bec0a2ed8a8..0042d3a765bfd070a5111021cb5325a8ce7e2866 100644 (file)
@@ -11,7 +11,7 @@
 
 fn region_identity(x: &uint) -> &uint { x }
 
-fn apply<T>(t: T, f: |T| -> T) -> T { f(t) }
+fn apply<T, F>(t: T, f: F) -> T where F: FnOnce(T) -> T { f(t) }
 
 fn parameterized(x: &uint) -> uint {
     let z = apply(x, ({|y|
diff --git a/src/test/run-pass/regions-reassign-let-bound-pointer.rs b/src/test/run-pass/regions-reassign-let-bound-pointer.rs
new file mode 100644 (file)
index 0000000..ecf79de
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+fn foo(x: &int) {
+    let a = 1;
+    let mut z = x;
+    z = &a;
+}
+
+pub fn main() {
+    foo(&1);
+}
diff --git a/src/test/run-pass/regions-reassign-match-bound-pointer.rs b/src/test/run-pass/regions-reassign-match-bound-pointer.rs
new file mode 100644 (file)
index 0000000..18312b1
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+fn foo(x: &int) {
+    let a = 1;
+    match x {
+        mut z => {
+            z = &a;
+        }
+    }
+}
+
+pub fn main() {
+    foo(&1);
+}
diff --git a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs
new file mode 100644 (file)
index 0000000..aa0ed02
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that this fairly specialized, but also reasonable, pattern
+// typechecks. The pattern involves regions bound in closures that
+// wind up related to inference variables.
+//
+// NB. Changes to the region implementatiosn have broken this pattern
+// a few times, but it happens to be used in the compiler so those
+// changes were caught. However, those uses in the compiler could
+// easily get changed or refactored away in the future.
+
+struct Ctxt<'tcx> {
+    x: &'tcx Vec<int>
+}
+
+struct Foo<'a,'tcx:'a> {
+    cx: &'a Ctxt<'tcx>,
+}
+
+impl<'a,'tcx> Foo<'a,'tcx> {
+    fn bother(&mut self) -> int {
+        self.elaborate_bounds(|this| {
+            // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`,
+            // where `'f0` and `'f1` are fresh, free regions that
+            // result from the bound regions on the closure, and `'2`
+            // is a region inference variable created by the call. Due
+            // to the constraints on the type, we find that `'_2 : 'f1
+            // + 'f2` must hold (and can be assumed by the callee).
+            // Region inference has to do some clever stuff to avoid
+            // inferring `'_2` to be `'static` in this case, because
+            // it is created outside the closure but then related to
+            // regions bound by the closure itself. See the
+            // `region_inference.rs` file (and the `givens` field, in
+            // particular) for more details.
+            this.foo()
+        })
+    }
+
+    fn foo(&mut self) -> int {
+        22
+    }
+
+    fn elaborate_bounds(
+        &mut self,
+        mk_cand: for<'b>|this: &mut Foo<'b, 'tcx>| -> int)
+        -> int
+    {
+        mk_cand(self)
+    }
+}
+
+fn main() {
+    let v = vec!();
+    let cx = Ctxt { x: &v };
+    let mut foo = Foo { cx: &cx };
+    assert_eq!(foo.bother(), 22); // just so the code is not dead, basically
+}
index f1d2adcaf94d876478fe142df78353b6e4388427..0f36dc04575446cf7f6365b6505fc969ae871240 100644 (file)
@@ -8,19 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 struct closure_box<'a> {
-    cl: ||: 'a,
+    cl: Box<FnMut() + 'a>,
 }
 
-fn box_it(x: ||) -> closure_box {
+fn box_it<'a>(x: Box<FnMut() + 'a>) -> closure_box<'a> {
     closure_box {cl: x}
 }
 
-fn call_static_closure(cl: closure_box<'static>) {
-    (cl.cl)();
+fn call_static_closure(mut cl: closure_box<'static>) {
+    cl.cl.call_mut(())
 }
 
 pub fn main() {
-    let cl_box = box_it(|| println!("Hello, world!"));
+    let cl_box = box_it(box |&mut:| println!("Hello, world!"));
     call_static_closure(cl_box);
 }
index c7aa405b513e465bb6404d80d57df928edb5e95b..d610bf09edb958b0503c7795b95f6011cd1a1b18 100644 (file)
@@ -13,8 +13,8 @@
 
 extern crate libc;
 
+use std::ffi::CString;
 use std::io::TempDir;
-use std::c_str::ToCStr;
 use std::io::fs::PathExtensions;
 use std::io::fs;
 use std::io;
@@ -31,20 +31,17 @@ fn rename_directory() {
         let test_file = &old_path.join("temp.txt");
 
         /* Write the temp input file */
-        let ostream = test_file.with_c_str(|fromp| {
-            "w+b".with_c_str(|modebuf| {
-                libc::fopen(fromp, modebuf)
-            })
-        });
+        let fromp = CString::from_slice(test_file.as_vec());
+        let modebuf = CString::from_slice(b"w+b");
+        let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
         assert!((ostream as uint != 0u));
         let s = "hello".to_string();
-        "hello".with_c_str(|buf| {
-            let write_len = libc::fwrite(buf as *const libc::c_void,
-                                         1u as libc::size_t,
-                                         (s.len() + 1u) as libc::size_t,
-                                         ostream);
-            assert_eq!(write_len, (s.len() + 1) as libc::size_t)
-        });
+        let buf = CString::from_slice(b"hello");
+        let write_len = libc::fwrite(buf.as_ptr() as *mut _,
+                                     1u as libc::size_t,
+                                     (s.len() + 1u) as libc::size_t,
+                                     ostream);
+        assert_eq!(write_len, (s.len() + 1) as libc::size_t);
         assert_eq!(libc::fclose(ostream), (0u as libc::c_int));
 
         let new_path = tmpdir.join_many(&["quux", "blat"]);
index b905ebf52fcb3da1ba9af5b270ca18ffdfa861a2..899dc8ddbe90ddd597879cfe756f7d599f406c88 100644 (file)
@@ -13,7 +13,7 @@
 static mut calls: uint = 0;
 
 fn surrounding() {
-    let return_works = |n: int| {
+    let return_works = |&: n: int| {
         unsafe { calls += 1 }
 
         if n >= 0 { return; }
index 3f94c7c8e547a1459c3f4e1865ce76ffaffd7f8f..c70ed9a3d749eb1b21991c37fc54c2b1079805d2 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn test(f: |uint| -> uint) -> uint {
+fn test<F>(f: F) -> uint where F: FnOnce(uint) -> uint {
     return f(22u);
 }
 
index ff6e0e4bbc9f597a19969d5dcfee33f8b37dbe4c..74c0663971ec5e773e6c9e91b26fc34e0186c8fd 100644 (file)
@@ -26,14 +26,14 @@ impl plus for String { fn plus(&self) -> int { 200 } }
 
 trait uint_utils {
     fn str(&self) -> String;
-    fn multi(&self, f: |uint|);
+    fn multi<F>(&self, f: F) where F: FnMut(uint);
 }
 
 impl uint_utils for uint {
     fn str(&self) -> String {
         self.to_string()
     }
-    fn multi(&self, f: |uint|) {
+    fn multi<F>(&self, mut f: F) where F: FnMut(uint) {
         let mut c = 0u;
         while c < *self { f(c); c += 1u; }
     }
@@ -41,14 +41,14 @@ fn multi(&self, f: |uint|) {
 
 trait vec_utils<T> {
     fn length_(&self, ) -> uint;
-    fn iter_(&self, f: |&T|);
-    fn map_<U>(&self, f: |&T| -> U) -> Vec<U> ;
+    fn iter_<F>(&self, f: F) where F: FnMut(&T);
+    fn map_<U, F>(&self, f: F) -> Vec<U> where F: FnMut(&T) -> U;
 }
 
 impl<T> vec_utils<T> for Vec<T> {
     fn length_(&self) -> uint { self.len() }
-    fn iter_(&self, f: |&T|) { for x in self.iter() { f(x); } }
-    fn map_<U>(&self, f: |&T| -> U) -> Vec<U> {
+    fn iter_<F>(&self, mut f: F) where F: FnMut(&T) { for x in self.iter() { f(x); } }
+    fn map_<U, F>(&self, mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
         let mut r = Vec::new();
         for elt in self.iter() {
             r.push(f(elt));
@@ -64,7 +64,7 @@ pub fn main() {
     assert_eq!((vec!(1i)).length_().str(), "1".to_string());
     let vect = vec!(3i, 4).map_(|a| *a + 4);
     assert_eq!(vect[0], 7);
-    let vect = (vec!(3i, 4)).map_::<uint>(|a| *a as uint + 4u);
+    let vect = (vec!(3i, 4)).map_::<uint, _>(|a| *a as uint + 4u);
     assert_eq!(vect[0], 7u);
     let mut x = 0u;
     10u.multi(|_n| x += 2u );
index 8cc4cd142be09ba3d1377ea08bfb0959e57560cc..043ca121b1bb5b3c92ae6811bc3cc6b42cec17c3 100644 (file)
@@ -16,7 +16,7 @@ struct S { val: int }
 impl S { fn new(v: int) -> S { S { val: v } } }
 impl Drop for S { fn drop(&mut self) { } }
 
-pub fn f<T>((b1, b2): (T, T), f: |T| -> T) -> Partial<T> {
+pub fn f<T, F>((b1, b2): (T, T), mut f: F) -> Partial<T> where F: FnMut(T) -> T {
     let p = Partial { x: b1, y: b2 };
 
     // Move of `p` is legal even though we are also moving `p.y`; the
index aafe9e632b1ed46581281f07d2cea0471bd0a70e..6327e03e528afbfad4fcc1b6d402d0a0aaf7db2e 100644 (file)
@@ -18,7 +18,7 @@ impl Drop for S { fn drop(&mut self) { } }
 
 pub type Two<T> = (Partial<T>, Partial<T>);
 
-pub fn f<T>((b1, b2): (T, T), (b3, b4): (T, T), f: |T| -> T) -> Two<T> {
+pub fn f<T, F>((b1, b2): (T, T), (b3, b4): (T, T), mut f: F) -> Two<T> where F: FnMut(T) -> T {
     let p = Partial { x: b1, y: b2 };
     let q = Partial { x: b3, y: b4 };
 
diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs
new file mode 100644 (file)
index 0000000..021cfed
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::kinds::Send;
+
+struct TestType;
+
+impl TestType {}
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+impl !TestTrait for TestType {}
+
+struct TestType2<T>;
+
+impl<T> TestType2<T> {}
+
+unsafe impl<T> !Send for TestType2<T> {}
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
index 8fda8a951693f2a67c20428a8f63adfec97babfb..bf108ecd6764a954e681940487786c1e78a21382 100644 (file)
@@ -29,7 +29,7 @@ fn test_tempdir() {
     let path = {
         let p = TempDir::new_in(&Path::new("."), "foobar").unwrap();
         let p = p.path();
-        assert!(p.as_vec().ends_with(b"foobar"));
+        assert!(p.as_str().unwrap().contains("foobar"));
         p.clone()
     };
     assert!(!path.exists());
@@ -189,7 +189,7 @@ pub fn dont_double_panic() {
     assert!(r.is_err());
 }
 
-fn in_tmpdir(f: ||) {
+fn in_tmpdir<F>(f: F) where F: FnOnce() {
     let tmpdir = TempDir::new("test").ok().expect("can't make tmpdir");
     assert!(os::change_dir(tmpdir.path()).is_ok());
 
index c8abfcaa721de9b72f388602a569b7e4aab85b5d..bc397bb63196e193b6b188278af9d1ba7afdff52 100644 (file)
 // Tests that a heterogeneous list of existential types can be put inside an Arc
 // and shared between tasks as long as all types fulfill Send.
 
+// ignore-pretty
+
+#![feature(unboxed_closures)]
+
 use std::sync::Arc;
 use std::sync::mpsc::channel;
 use std::thread::Thread;
 
 trait Pet {
-    fn name(&self, blk: |&str|);
+    fn name(&self, blk: Box<FnMut(&str)>);
     fn num_legs(&self) -> uint;
     fn of_good_pedigree(&self) -> bool;
 }
@@ -38,19 +42,19 @@ struct Goldfyshe {
 }
 
 impl Pet for Catte {
-    fn name(&self, blk: |&str|) { blk(self.name.as_slice()) }
+    fn name(&self, mut blk: Box<FnMut(&str)>) { blk(self.name.as_slice()) }
     fn num_legs(&self) -> uint { 4 }
     fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 }
 }
 impl Pet for Dogge {
-    fn name(&self, blk: |&str|) { blk(self.name.as_slice()) }
+    fn name(&self, mut blk: Box<FnMut(&str)>) { blk(self.name.as_slice()) }
     fn num_legs(&self) -> uint { 4 }
     fn of_good_pedigree(&self) -> bool {
         self.bark_decibels < 70 || self.tricks_known > 20
     }
 }
 impl Pet for Goldfyshe {
-    fn name(&self, blk: |&str|) { blk(self.name.as_slice()) }
+    fn name(&self, mut blk: Box<FnMut(&str)>) { blk(self.name.as_slice()) }
     fn num_legs(&self) -> uint { 0 }
     fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 }
 }
@@ -98,7 +102,7 @@ fn check_legs(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
 }
 fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
     for pet in arc.iter() {
-        pet.name(|name| {
+        pet.name(box |name| {
             assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
         })
     }
index eeda6e2c88b454e084d07d29811915224e6bd59d..d4c1b688b47b60efed2eafc3452454c963188a01 100644 (file)
@@ -24,10 +24,10 @@ fn to_string_(&self) -> String { "()".to_string() }
 }
 
 trait map<T> {
-    fn map<U>(&self, f: |&T| -> U) -> Vec<U> ;
+    fn map<U, F>(&self, f: F) -> Vec<U> where F: FnMut(&T) -> U;
 }
 impl<T> map<T> for Vec<T> {
-    fn map<U>(&self, f: |&T| -> U) -> Vec<U> {
+    fn map<U, F>(&self, mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
         let mut r = Vec::new();
         for i in self.iter() {
             r.push(f(i));
index efda7771403a393066a13bc24b6d609198d6dad2..7287d149f5100e0a7440a6c1b6132039011ec1aa 100644 (file)
@@ -34,24 +34,6 @@ fn main() {
         let f = TypeId::of::<fn(for<'a> fn(&'a int) -> &'a int)>();
         assert!(e != f);
     }
-    // Stack closures
-    {
-        let a = TypeId::of::<|&'static int, &'static int|>();
-        let b = TypeId::of::<for<'a> |&'static int, &'a int|>();
-        let c = TypeId::of::<for<'a, 'b> |&'a int, &'b int|>();
-        let d = TypeId::of::<for<'a, 'b> |&'b int, &'a int|>();
-        assert!(a != b);
-        assert!(a != c);
-        assert!(a != d);
-        assert!(b != c);
-        assert!(b != d);
-        assert_eq!(c, d);
-
-        // Make sure De Bruijn indices are handled correctly
-        let e = TypeId::of::<for<'a> |(|&'a int| -> &'a int)|>();
-        let f = TypeId::of::<|for<'a> |&'a int| -> &'a int|>();
-        assert!(e != f);
-    }
     // Boxed unboxed closures
     {
         let a = TypeId::of::<Box<Fn(&'static int, &'static int)>>();
index 5bf1a72dc6b2aa70daacac6d1125aeed0d6c9fe7..24cc5fab8ed77016d1ab08a1c7311484616ab5bd 100644 (file)
@@ -14,7 +14,7 @@ struct S<T> {
     b: uint,
 }
 
-fn range_(lo: uint, hi: uint, it: |uint|) {
+fn range_<F>(lo: uint, hi: uint, mut it: F) where F: FnMut(uint) {
     let mut lo_ = lo;
     while lo_ < hi { it(lo_); lo_ += 1u; }
 }
index ab3faa16f948ffc2428e05f466a4f579e9720c96..60e59400e1a092d8149098acf1119a5463702917 100644 (file)
@@ -19,7 +19,7 @@ fn make_adder(x: int) -> Box<FnMut<(int,),int>+'static> {
 
 pub fn main() {
     let mut adder = make_adder(3);
-    let z = adder.call_mut((2,));
+    let z = adder(2);
     println!("{}", z);
     assert_eq!(z, 5);
 }
diff --git a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs
new file mode 100644 (file)
index 0000000..0303954
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// Test that the call operator autoderefs when calling a bounded type parameter.
+
+#![feature(unboxed_closures)]
+
+use std::ops::FnMut;
+
+fn call_with_2(x: &fn(int) -> int) -> int
+{
+    x(2) // look ma, no `*`
+}
+
+fn subtract_22(x: int) -> int { x - 22 }
+
+pub fn main() {
+    let subtract_22: fn(int) -> int = subtract_22;
+    let z = call_with_2(&subtract_22);
+    assert_eq!(z, -20);
+}
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs
new file mode 100644 (file)
index 0000000..305f496
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// Test that the call operator autoderefs when calling a bounded type parameter.
+
+#![feature(unboxed_closures)]
+
+use std::ops::FnMut;
+
+fn call_with_2<F>(x: &mut F) -> int
+    where F : FnMut(int) -> int
+{
+    x(2) // look ma, no `*`
+}
+
+pub fn main() {
+    let z = call_with_2(&mut |x| x - 22);
+    assert_eq!(z, -20);
+}
diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs
new file mode 100644 (file)
index 0000000..8909f4e
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+// Test that the call operator autoderefs when calling to an object type.
+
+#![feature(unboxed_closures)]
+
+use std::ops::FnMut;
+
+fn make_adder(x: int) -> Box<FnMut(int)->int + 'static> {
+    box move |y| { x + y }
+}
+
+pub fn main() {
+    let mut adder = make_adder(3);
+    let z = adder(2);
+    println!("{}", z);
+    assert_eq!(z, 5);
+}
+
index 58657c2b71880dbcbdea73719ad698847e056e58..a25f5e265e81494a8f7eb4db4867f0d3e053a7b6 100644 (file)
 fn square(x: int) -> int { x * x }
 
 fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
-    f.call((x,))
+    f(x)
 }
 
 fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
-    f.call_mut((x,))
+    f(x)
 }
 
 fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
-    f.call_once((x,))
+    f(x)
 }
 
 fn main() {
index 77d41ae190778a738cf39661311eeb7b5fede41e..8af0547e5e57f6384d6d0c0a7c29a4ac6adb8116 100644 (file)
@@ -25,15 +25,15 @@ extern "rust-call" fn call(&self, (x,): (int,)) -> int {
 }
 
 fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
-    f.call((x,))
+    f(x)
 }
 
 fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
-    f.call_mut((x,))
+    f(x)
 }
 
 fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
-    f.call_once((x,))
+    f(x)
 }
 
 fn main() {
index 02395624cd123b2c310115c9920286b5048d5bac..068080e256dba3cd8d093b98ca1e02aa1a923b3f 100644 (file)
@@ -25,11 +25,11 @@ extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
 }
 
 fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
-    f.call_mut((x,))
+    f(x)
 }
 
 fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
-    f.call_once((x,))
+    f(x)
 }
 
 fn main() {
index 9d1d81fe259b3683e0ba7b307694442ac3ddca3d..0edeeb8d198dabe5f615765da529c803bead7a4f 100644 (file)
@@ -13,7 +13,7 @@
 use std::ops::FnMut;
 
 fn call_it<F:FnMut<(int,int),int>>(y: int, mut f: F) -> int {
-    f.call_mut((2, y))
+    f(2, y)
 }
 
 pub fn main() {
index 3a750dadb911c4ca2e30e7746798131b3e9f26b4..88c9ceae4a1248154257d2b828253e7bc5cfa79c 100644 (file)
@@ -22,11 +22,11 @@ extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
 }
 
 fn call_it<F:FnMut(int)->int>(mut f: F, x: int) -> int {
-    f.call_mut((x,)) + 3
+    f(x) + 3
 }
 
 fn call_box(f: &mut FnMut(int) -> int, x: int) -> int {
-    f.call_mut((x,)) + 3
+    f(x) + 3
 }
 
 fn main() {
index e31ef169e16eb2ff5ee5b3e8b83f33605be13f04..d1bd7e908c826019c4088a1504a8d8b8ad03dba7 100644 (file)
@@ -17,12 +17,12 @@ fn main() {
     task.call((0i, ));
 
     let mut task: Box<FnMut(int) -> int> = box |&mut: x| x;
-    task.call_mut((0i, ));
+    task(0i);
 
     call(|:x| x, 22);
 }
 
 fn call<F:FnOnce(int) -> int>(f: F, x: int) -> int {
-    f.call_once((x,))
+    f(x)
 }
 
index f11096ba5ffc6b732ef0f739423e944cee2c9948..c473db4586ff74283027b4873708ec42d9c0b244 100644 (file)
@@ -14,6 +14,6 @@
 
 pub fn main() {
     let mut f = |&mut: x: int, y: int| -> int { x + y };
-    let z = f.call_mut((1, 2));
+    let z = f(1, 2);
     assert_eq!(z, 3);
 }
index beab82e804bf74b8ba0054b3fac8185356a45cd6..780a1e6cdf0340c7b249918e4188a4eca842a9b7 100644 (file)
@@ -12,6 +12,6 @@
 
 fn main() {
     let onetime = |: x| x;
-    onetime.call_once((0i,));
+    onetime(0i);
 }
 
index 3a5e0dd8ae3b9a219549093cb0b37e952ab6df36..d22a6652e16f3d29333ae449a4dca4b29a474737 100644 (file)
@@ -13,7 +13,7 @@ fn good(_a: &int) {
 
 // unnamed argument &int is now parse x: &int
 
-fn called(_f: |&int|) {
+fn called<F>(_f: F) where F: FnOnce(&int) {
 }
 
 pub fn main() {
index ba48ae1c0cef8798952bb27a154ad9428fa4c65d..bd20a174d1e49c1967a33a3217e3254463e7c9df 100644 (file)
@@ -10,6 +10,6 @@
 
 pub fn main() {
     let _x = box 1i;
-    let lam_move: || = || {};
+    let lam_move = |&:| {};
     lam_move();
 }
index ec320c1f8a3092b2407ab68cb1a595ed9d111018..9600a242ca109d57fdc47a5640f2f088621af40f 100644 (file)
@@ -10,7 +10,7 @@
 
 extern crate libc;
 
-use std::c_str::{CString, ToCStr};
+use std::ffi::{self, CString};
 use libc::{c_char, c_int};
 
 // ignore-fast doesn't like extern crate
     fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int;
 }
 
-unsafe fn check<T>(expected: &str, f: |*mut c_char| -> T) {
+unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T {
     let mut x = [0 as c_char; 50];
     f(&mut x[0] as *mut c_char);
-    let res = CString::new(&x[0], false);
-    assert_eq!(expected, res.as_str().unwrap());
+    assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr()));
 }
 
 pub fn main() {
 
     unsafe {
         // Call with just the named parameter
-        "Hello World\n".with_c_str(|c| {
-            check("Hello World\n", |s| sprintf(s, c));
-        });
+        let c = CString::from_slice(b"Hello World\n");
+        check("Hello World\n", |s| sprintf(s, c.as_ptr()));
 
         // Call with variable number of arguments
-        "%d %f %c %s\n".with_c_str(|c| {
-            check("42 42.500000 a %d %f %c %s\n\n", |s| {
-                sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c);
-            })
+        let c = CString::from_slice(b"%d %f %c %s\n");
+        check("42 42.500000 a %d %f %c %s\n\n", |s| {
+            sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
         });
 
         // Make a function pointer
-        let x: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
+        let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
 
         // A function that takes a function pointer
-        unsafe fn call(p: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int) {
-            // Call with just the named parameter via fn pointer
-            "Hello World\n".with_c_str(|c| {
-                check("Hello World\n", |s| p(s, c));
-            });
+        unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
+            // Call with just the named parameter
+            let c = CString::from_slice(b"Hello World\n");
+            check("Hello World\n", |s| sprintf(s, c.as_ptr()));
 
             // Call with variable number of arguments
-            "%d %f %c %s\n".with_c_str(|c| {
-                check("42 42.500000 a %d %f %c %s\n\n", |s| {
-                    p(s, c, 42i, 42.5f64, 'a' as c_int, c);
-                })
+            let c = CString::from_slice(b"%d %f %c %s\n");
+            check("42 42.500000 a %d %f %c %s\n\n", |s| {
+                sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
             });
         }
 
index cc2061c3cf38535901ba58d1a60a367525e0e62e..576601833330d4f746cd0965b6b78fdba325baf8 100644 (file)
 
 #![feature(advanced_slice_patterns)]
 
-fn foldl<T,U:Clone>(values: &[T],
-                    initial: U,
-                    function: |partial: U, element: &T| -> U)
-                    -> U {
+fn foldl<T, U, F>(values: &[T],
+                  initial: U,
+                  mut function: F)
+                  -> U where
+    U: Clone,
+    F: FnMut(U, &T) -> U,
+{
     match values {
         [ref head, tail..] =>
             foldl(tail, function(initial, head), function),
@@ -21,10 +24,13 @@ fn foldl<T,U:Clone>(values: &[T],
     }
 }
 
-fn foldr<T,U:Clone>(values: &[T],
-                    initial: U,
-                    function: |element: &T, partial: U| -> U)
-                    -> U {
+fn foldr<T, U, F>(values: &[T],
+                  initial: U,
+                  mut function: F)
+                  -> U where
+    U: Clone,
+    F: FnMut(&T, U) -> U,
+{
     match values {
         [head.., ref tail] =>
             foldr(head, function(tail, initial), function),
index f73800b89db642e28f0333f1366401dfd01d5bac..c8ed1a2610573ff505cae40c477bc232febfc537 100644 (file)
@@ -26,7 +26,7 @@ fn the(x: &Cell<bool>) {
         return while !x.get() { x.set(true); };
     }
     let i = &Cell::new(false);
-    let dont = {||the(i)};
+    let dont = {|&:|the(i)};
     dont();
     assert!((i.get()));
 }
diff --git a/src/test/run-pass/wf-bound-region-in-object-type.rs b/src/test/run-pass/wf-bound-region-in-object-type.rs
new file mode 100644 (file)
index 0000000..256b199
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the `wf` checker properly handles bound regions in object
+// types. Compiling this code used to trigger an ICE.
+
+pub struct Context<'tcx> {
+    vec: &'tcx Vec<int>
+}
+
+pub type Cmd<'a> = &'a int;
+
+pub type DecodeInlinedItem<'a> =
+    Box<for<'tcx> FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx int, ()> + 'a>;
+
+fn foo(d: DecodeInlinedItem) {
+}
+
+fn main() { }